Use golangci-lints's build-in modernize linter (#34341)
Some checks are pending
API / build (push) Waiting to run
Server CI / Compute Go Version (push) Waiting to run
Server CI / Check mocks (push) Blocked by required conditions
Server CI / Check go mod tidy (push) Blocked by required conditions
Server CI / check-style (push) Blocked by required conditions
Server CI / Check serialization methods for hot structs (push) Blocked by required conditions
Server CI / Vet API (push) Blocked by required conditions
Server CI / Check migration files (push) Blocked by required conditions
Server CI / Generate email templates (push) Blocked by required conditions
Server CI / Check store layers (push) Blocked by required conditions
Server CI / Check mmctl docs (push) Blocked by required conditions
Server CI / Postgres with binary parameters (push) Blocked by required conditions
Server CI / Postgres (push) Blocked by required conditions
Server CI / Postgres (FIPS) (push) Blocked by required conditions
Server CI / Generate Test Coverage (push) Blocked by required conditions
Server CI / Run mmctl tests (push) Blocked by required conditions
Server CI / Run mmctl tests (FIPS) (push) Blocked by required conditions
Server CI / Build mattermost server app (push) Blocked by required conditions
Web App CI / check-lint (push) Waiting to run
Web App CI / check-i18n (push) Waiting to run
Web App CI / check-types (push) Waiting to run
Web App CI / test (push) Waiting to run
Web App CI / build (push) Waiting to run

This commit is contained in:
Ben Schumacher 2025-11-04 12:09:11 +01:00 committed by GitHub
parent 494b570f3a
commit 892a7c9c69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 45 additions and 57 deletions

View file

@ -8,6 +8,7 @@ linters:
- ineffassign
- makezero
- misspell
- modernize
- revive
- staticcheck
- unconvert

View file

@ -322,22 +322,13 @@ golang-versions: ## Install Golang versions used for compatibility testing (e.g.
export GO_COMPATIBILITY_TEST_VERSIONS="${GO_COMPATIBILITY_TEST_VERSIONS}"
golangci-lint: ## Run golangci-lint on codebase
$(GO) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.5.0
$(GO) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.6.0
ifeq ($(BUILD_ENTERPRISE_READY),true)
$(GOBIN)/golangci-lint run ./... ./public/... $(BUILD_ENTERPRISE_DIR)/...
else
$(GOBIN)/golangci-lint run ./... ./public/...
endif
modernize: ## Run modernize linter on codebase
## https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/modernize is not support in golangci-lint.
## We need to invoke it directly.
ifeq ($(BUILD_ENTERPRISE_READY),true)
go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@v0.19.1 -test ./... ./public/... $(BUILD_ENTERPRISE_DIR)/...
else
go run golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@v0.19.1 -test ./... ./public/...
endif
i18n-extract: ## Extract strings for translation from the source code
cd ../tools/mmgotool && $(GO) install .
$(GOBIN)/mmgotool i18n extract --portal-dir=""
@ -431,7 +422,7 @@ ifeq ($(BUILD_ENTERPRISE_READY),true)
endif
endif
check-style: plugin-checker vet modernize golangci-lint ## Runs style/lint checks
check-style: plugin-checker vet golangci-lint ## Runs style/lint checks
gotestsum:
$(GO) install gotest.tools/gotestsum@v1.11.0

View file

@ -3831,11 +3831,11 @@ func TestResetPassword(t *testing.T) {
resp, err = th.Client.ResetPassword(context.Background(), "junk", "newpwd")
require.Error(t, err)
CheckBadRequestStatus(t, resp)
code := ""
var code strings.Builder
for range model.TokenSize {
code += "a"
code.WriteString("a")
}
resp, err = th.Client.ResetPassword(context.Background(), code, "newpwd")
resp, err = th.Client.ResetPassword(context.Background(), code.String(), "newpwd")
require.Error(t, err)
CheckBadRequestStatus(t, resp)
_, err = th.Client.ResetPassword(context.Background(), recoveryToken.Token, "newpwd")

View file

@ -2,7 +2,6 @@
// See LICENSE.txt for license information.
//go:build !race
// +build !race
package api4

View file

@ -1,5 +1,4 @@
//go:build gofuzz
// +build gofuzz
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

View file

@ -149,8 +149,7 @@ func extractStoreMetadata() (*storeMetadata, error) {
metadata.Methods[methodName] = extractMethodMetadata(method, src)
}
}
} else if strings.HasSuffix(x.Name.Name, "Store") {
subStoreName := strings.TrimSuffix(x.Name.Name, "Store")
} else if subStoreName, ok := strings.CutSuffix(x.Name.Name, "Store"); ok {
metadata.SubStores[subStoreName] = subStore{Methods: map[string]methodData{}}
for _, method := range x.Type.(*ast.InterfaceType).Methods.List {
methodName := method.Names[0].Name

View file

@ -46,11 +46,11 @@ type channelRolesPermissions struct {
func NewRoleFromModel(role *model.Role) *Role {
permissionsMap := make(map[string]bool)
permissions := ""
var permissions strings.Builder
for _, permission := range role.Permissions {
if !permissionsMap[permission] {
permissions += fmt.Sprintf(" %v", permission)
permissions.WriteString(fmt.Sprintf(" %v", permission))
permissionsMap[permission] = true
}
}
@ -63,7 +63,7 @@ func NewRoleFromModel(role *model.Role) *Role {
CreateAt: role.CreateAt,
UpdateAt: role.UpdateAt,
DeleteAt: role.DeleteAt,
Permissions: permissions,
Permissions: permissions.String(),
SchemeManaged: role.SchemeManaged,
BuiltIn: role.BuiltIn,
}

View file

@ -940,15 +940,15 @@ func (ss *SqlStore) hasLicense() bool {
func convertMySQLFullTextColumnsToPostgres(columnNames string) string {
columns := strings.Split(columnNames, ", ")
concatenatedColumnNames := ""
var concatenatedColumnNames strings.Builder
for i, c := range columns {
concatenatedColumnNames += c
concatenatedColumnNames.WriteString(c)
if i < len(columns)-1 {
concatenatedColumnNames += " || ' ' || "
concatenatedColumnNames.WriteString(" || ' ' || ")
}
}
return concatenatedColumnNames
return concatenatedColumnNames.String()
}
// IsDuplicate checks whether an error is a duplicate key error, which comes when processes are competing on creating the same

View file

@ -2,7 +2,6 @@
// See LICENSE.txt for license information.
//go:build maincoverage
// +build maincoverage
package main

View file

@ -2,7 +2,6 @@
// See LICENSE.txt for license information.
//go:build enterprise
// +build enterprise
// This file is needed to ensure the enterprise code get complied
// when running tests. See https://mattermost.atlassian.net/browse/MM-54929

View file

@ -2,7 +2,6 @@
// See LICENSE.txt for license information.
//go:build e2e
// +build e2e
package commands

View file

@ -2,7 +2,6 @@
// See LICENSE.txt for license information.
//go:build e2e
// +build e2e
package commands

View file

@ -2,7 +2,6 @@
// See LICENSE.txt for license information.
//go:build unit
// +build unit
package commands

View file

@ -2,7 +2,6 @@
// See LICENSE.txt for license information.
//go:build linux || darwin || freebsd
// +build linux darwin freebsd
package commands

View file

@ -73,7 +73,7 @@ func applyEnvKey(key, value string, rValueSubject reflect.Value) {
rFieldValue.Set(reflect.ValueOf(intVal))
}
case reflect.Slice:
if rFieldValue.Type() == reflect.TypeOf(json.RawMessage{}) {
if rFieldValue.Type() == reflect.TypeFor[json.RawMessage]() {
rFieldValue.Set(reflect.ValueOf([]byte(value)))
break
}
@ -100,7 +100,7 @@ func applyEnvironmentMap(inputConfig *model.Config, env map[string]string) *mode
// generateEnvironmentMap creates a map[string]any containing true at the leaves mirroring the
// configuration structure so the client can know which env variables are overridden
func generateEnvironmentMap(env map[string]string, filter func(reflect.StructField) bool) map[string]any {
rType := reflect.TypeOf(model.Config{})
rType := reflect.TypeFor[model.Config]()
return generateEnvironmentMapWithBaseKey(env, rType, "MM", filter)
}

View file

@ -1350,7 +1350,8 @@ func (es *ElasticsearchInterfaceImpl) PurgeIndexes(rctx request.CTX) *model.AppE
}
indexPrefix := *es.Platform.Config().ElasticsearchSettings.IndexPrefix
indexesToDelete := indexPrefix + "*"
var indexesToDelete strings.Builder
indexesToDelete.WriteString(indexPrefix + "*")
if ignorePurgeIndexes := *es.Platform.Config().ElasticsearchSettings.IgnoredPurgeIndexes; ignorePurgeIndexes != "" {
// we are checking if provided indexes exist. If an index doesn't exist,
@ -1365,14 +1366,14 @@ func (es *ElasticsearchInterfaceImpl) PurgeIndexes(rctx request.CTX) *model.AppE
rctx.Logger().Warn("Elasticsearch index get error", mlog.String("index", ignorePurgeIndex), mlog.Err(err))
continue
}
indexesToDelete += ",-" + strings.TrimSpace(ignorePurgeIndex)
indexesToDelete.WriteString(",-" + strings.TrimSpace(ignorePurgeIndex))
}
}
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(*es.Platform.Config().ElasticsearchSettings.RequestTimeoutSeconds)*time.Second)
defer cancel()
_, err := es.client.Indices.Delete(indexesToDelete).Do(ctx)
_, err := es.client.Indices.Delete(indexesToDelete.String()).Do(ctx)
if err != nil {
rctx.Logger().Error("Elastic Search PurgeIndexes Error", mlog.Err(err))
return model.NewAppError("Elasticsearch.PurgeIndexes", "ent.elasticsearch.purge_index.delete_failed", nil, "", http.StatusInternalServerError).Wrap(err)

View file

@ -2,7 +2,6 @@
// See LICENSE.txt for license information.
//go:build !linux
// +build !linux
package upgrader

View file

@ -4,6 +4,7 @@
package model
import (
"strings"
"testing"
"github.com/stretchr/testify/require"
@ -56,15 +57,15 @@ func TestAccessPolicyVersionV0_1(t *testing.T) {
})
t.Run("parent policy with too long name", func(t *testing.T) {
longName := ""
var longName strings.Builder
for i := 0; i <= MaxPolicyNameLength; i++ {
longName += "a"
longName.WriteString("a")
}
policy := &AccessControlPolicy{
ID: NewId(),
Type: AccessControlPolicyTypeParent,
Name: longName,
Name: longName.String(),
Revision: 1,
Version: AccessControlPolicyVersionV0_1,
Rules: []AccessControlPolicyRule{{Actions: []string{"read"}, Expression: "user.role == 'admin'"}},

View file

@ -8,6 +8,7 @@ import (
"fmt"
"sort"
"strconv"
"strings"
)
type ChannelCounts struct {
@ -24,12 +25,12 @@ func (o *ChannelCounts) Etag() string {
}
sort.Strings(ids)
str := ""
var str strings.Builder
for _, id := range ids {
str += id + strconv.FormatInt(o.Counts[id], 10)
str.WriteString(id + strconv.FormatInt(o.Counts[id], 10))
}
md5Counts := fmt.Sprintf("%x", md5.Sum([]byte(str)))
md5Counts := fmt.Sprintf("%x", md5.Sum([]byte(str.String())))
var update int64
for _, u := range o.UpdateTimes {

View file

@ -130,7 +130,7 @@ func (f *FeatureFlags) SetDefaults() {
// Supports boolean and string feature flags.
func (f *FeatureFlags) ToMap() map[string]string {
refStructVal := reflect.ValueOf(*f)
refStructType := reflect.TypeOf(*f)
refStructType := reflect.TypeFor[FeatureFlags]()
ret := make(map[string]string)
for i := 0; i < refStructVal.NumField(); i++ {
refFieldVal := refStructVal.Field(i)

View file

@ -5,6 +5,7 @@ package model
import (
"net/http"
"strings"
)
const (
@ -2658,12 +2659,13 @@ func MakePermissionError(s *Session, permissions []*Permission) *AppError {
}
func MakePermissionErrorForUser(userId string, permissions []*Permission) *AppError {
permissionsStr := "permission="
var permissionsStr strings.Builder
permissionsStr.WriteString("permission=")
for i, permission := range permissions {
permissionsStr += permission.Id
permissionsStr.WriteString(permission.Id)
if i != len(permissions)-1 {
permissionsStr += ","
permissionsStr.WriteString(",")
}
}
return NewAppError("Permissions", "api.context.permissions.app_error", nil, "userId="+userId+", "+permissionsStr, http.StatusForbidden)
return NewAppError("Permissions", "api.context.permissions.app_error", nil, "userId="+userId+", "+permissionsStr.String(), http.StatusForbidden)
}

View file

@ -692,13 +692,14 @@ func IsValidAlphaNumHyphenUnderscorePlus(s string) bool {
}
func Etag(parts ...any) string {
etag := CurrentVersion
var etag strings.Builder
etag.WriteString(CurrentVersion)
for _, part := range parts {
etag += fmt.Sprintf(".%v", part)
etag.WriteString(fmt.Sprintf(".%v", part))
}
return etag
return etag.String()
}
var (
@ -712,7 +713,7 @@ func ParseHashtags(text string) (string, string) {
words := strings.Fields(text)
hashtagString := ""
plainString := ""
var plainString strings.Builder
for _, word := range words {
// trim off surrounding punctuation
word = puncStart.ReplaceAllString(word, "")
@ -724,7 +725,7 @@ func ParseHashtags(text string) (string, string) {
if validHashtag.MatchString(word) {
hashtagString += " " + word
} else {
plainString += " " + word
plainString.WriteString(" " + word)
}
}
@ -738,7 +739,7 @@ func ParseHashtags(text string) (string, string) {
}
}
return strings.TrimSpace(hashtagString), strings.TrimSpace(plainString)
return strings.TrimSpace(hashtagString), strings.TrimSpace(plainString.String())
}
func ClearMentionTags(post string) string {

View file

@ -189,9 +189,9 @@ func (g *hooksRPCClient) Implemented() (impl []string, err error) {
// Implemented replies with the names of the hooks that are implemented.
func (s *hooksRPCServer) Implemented(args struct{}, reply *[]string) error {
ifaceType := reflect.TypeOf((*Hooks)(nil)).Elem()
ifaceType := reflect.TypeFor[Hooks]()
implType := reflect.TypeOf(s.impl)
selfType := reflect.TypeOf(s)
selfType := reflect.TypeFor[*hooksRPCServer]()
var methods []string
for i := 0; i < ifaceType.NumMethod(); i++ {
method := ifaceType.Method(i)

View file

@ -52,7 +52,7 @@ func TestHumanizeJsonError(t *testing.T) {
[]byte("line 1\nline 2\nline 3"),
&json.UnmarshalTypeError{
Value: "bool",
Type: reflect.TypeOf(testType{}),
Type: reflect.TypeFor[testType](),
Offset: 17,
Struct: "struct",
Field: "field",