From 63f150ead17e33ecfc5e322b677e2a21081ff5ca Mon Sep 17 00:00:00 2001 From: Florian Bosdorff <26360670+bosix@users.noreply.github.com> Date: Wed, 5 Jan 2022 04:18:53 +0100 Subject: [PATCH] Add decorder linter (#2453) --- .golangci.example.yml | 21 +++++++++++++++++ go.mod | 1 + go.sum | 4 ++++ pkg/config/linters_settings.go | 14 +++++++++++ pkg/golinters/decorder.go | 38 ++++++++++++++++++++++++++++++ pkg/lint/lintersdb/manager.go | 7 ++++++ test/testdata/configs/decorder.yml | 10 ++++++++ test/testdata/decorder.go | 21 +++++++++++++++++ test/testdata/decorder_default.go | 20 ++++++++++++++++ 9 files changed, 136 insertions(+) create mode 100644 pkg/golinters/decorder.go create mode 100644 test/testdata/configs/decorder.yml create mode 100644 test/testdata/decorder.go create mode 100644 test/testdata/decorder_default.go diff --git a/.golangci.example.yml b/.golangci.example.yml index 95abb3c48087..e4f9506ff049 100644 --- a/.golangci.example.yml +++ b/.golangci.example.yml @@ -107,6 +107,27 @@ linters-settings: # should ignore tests (default false) skip-tests: false + decorder: + # required order of type, const, var and func declarations inside a file + # default: types before constants before variables before functions + dec-order: + - type + - const + - var + - func + + # if true, order of declarations is not checked at all + # default: true (disabled) + disable-dec-order-check: false + + # if true, init func can be anywhere in file (must not be declared before all other functions) + # default: true (disabled) + disable-init-func-first-check: false + + # if true, multiple global type, const and var declarations are allowed + # default: true (disabled) + disable-dec-num-check: false + dogsled: # checks assignments with too many blank identifiers; default is 2 max-blank-identifiers: 2 diff --git a/go.mod b/go.mod index 7e1e1279931d..7b7492e2a9e3 100644 --- a/go.mod +++ b/go.mod @@ -92,6 +92,7 @@ require ( github.com/uudashr/gocognit v1.0.5 github.com/valyala/quicktemplate v1.7.0 github.com/yeya24/promlinter v0.1.0 + gitlab.com/bosi/decorder v0.2.0 golang.org/x/tools v0.1.8 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b honnef.co/go/tools v0.2.2 diff --git a/go.sum b/go.sum index a686c7b85ac7..3cdbacc3d3f3 100644 --- a/go.sum +++ b/go.sum @@ -814,6 +814,8 @@ github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +gitlab.com/bosi/decorder v0.2.0 h1:MqNxlLZFUixZsksPm7w3xIrLOLo66WuNaqbDoysPHQ0= +gitlab.com/bosi/decorder v0.2.0/go.mod h1:6C/nhLSbF6qZbYD8bRmISBwc6vcWdNsiIBkRvjJFrH0= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c/go.mod h1:xCI7ZzBfRuGgBXyXO6yfWfDmlWd35khcWpUa4L0xI/k= @@ -1065,6 +1067,8 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827 h1:A0Qkn7Z/n8zC1xd9LTw17AiKlBRK64tw3ejWQiEqca0= golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go index 62edb3c86cb1..49f20cf4ddb0 100644 --- a/pkg/config/linters_settings.go +++ b/pkg/config/linters_settings.go @@ -3,6 +3,12 @@ package config import "github.com/pkg/errors" var defaultLintersSettings = LintersSettings{ + Decorder: DecorderSettings{ + DecOrder: []string{"type", "const", "var", "func"}, + DisableDecNumCheck: true, + DisableDecOrderCheck: true, + DisableInitFuncFirstCheck: true, + }, Dogsled: DogsledSettings{ MaxBlankIdentifiers: 2, }, @@ -85,6 +91,7 @@ var defaultLintersSettings = LintersSettings{ type LintersSettings struct { BiDiChk BiDiChkSettings Cyclop Cyclop + Decorder DecorderSettings Depguard DepGuardSettings Dogsled DogsledSettings Dupl DuplSettings @@ -173,6 +180,13 @@ type DepGuardSettings struct { PackagesWithErrorMessage map[string]string `mapstructure:"packages-with-error-message"` } +type DecorderSettings struct { + DecOrder []string `mapstructure:"dec-order"` + DisableDecNumCheck bool `mapstructure:"disable-dec-num-check"` + DisableDecOrderCheck bool `mapstructure:"disable-dec-order-check"` + DisableInitFuncFirstCheck bool `mapstructure:"disable-init-func-first-check"` +} + type DogsledSettings struct { MaxBlankIdentifiers int `mapstructure:"max-blank-identifiers"` } diff --git a/pkg/golinters/decorder.go b/pkg/golinters/decorder.go new file mode 100644 index 000000000000..672f206ea35c --- /dev/null +++ b/pkg/golinters/decorder.go @@ -0,0 +1,38 @@ +package golinters + +import ( + "strings" + + "gitlab.com/bosi/decorder" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewDecorder(settings *config.DecorderSettings) *goanalysis.Linter { + a := decorder.Analyzer + + analyzers := []*analysis.Analyzer{a} + + // disable all rules/checks by default + cfg := map[string]interface{}{ + "disable-dec-num-check": true, + "disable-dec-order-check": true, + "disable-init-func-first-check": true, + } + + if settings != nil { + cfg["dec-order"] = strings.Join(settings.DecOrder, ",") + cfg["disable-dec-num-check"] = settings.DisableDecNumCheck + cfg["disable-dec-order-check"] = settings.DisableDecOrderCheck + cfg["disable-init-func-first-check"] = settings.DisableInitFuncFirstCheck + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + analyzers, + map[string]map[string]interface{}{a.Name: cfg}, + ).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index fd253f6c1ef0..db386a17d58d 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -102,6 +102,7 @@ func enableLinterConfigs(lcs []*linter.Config, isEnabled func(lc *linter.Config) func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { var bidichkCfg *config.BiDiChkSettings var cyclopCfg *config.Cyclop + var decorderCfg *config.DecorderSettings var errchkjsonCfg *config.ErrChkJSONSettings var errorlintCfg *config.ErrorLintSettings var exhaustiveCfg *config.ExhaustiveSettings @@ -131,6 +132,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { bidichkCfg = &m.cfg.LintersSettings.BiDiChk cyclopCfg = &m.cfg.LintersSettings.Cyclop errchkjsonCfg = &m.cfg.LintersSettings.ErrChkJSON + decorderCfg = &m.cfg.LintersSettings.Decorder errorlintCfg = &m.cfg.LintersSettings.ErrorLint exhaustiveCfg = &m.cfg.LintersSettings.Exhaustive exhaustiveStructCfg = &m.cfg.LintersSettings.ExhaustiveStruct @@ -189,6 +191,11 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithPresets(linter.PresetComplexity). WithURL("https://github.com/bkielbasa/cyclop"), + linter.NewConfig(golinters.NewDecorder(decorderCfg)). + WithSince("v1.44.0"). + WithPresets(linter.PresetFormatting, linter.PresetStyle). + WithURL("https://gitlab.com/bosi/decorder"), + linter.NewConfig(golinters.NewDeadcode()). WithSince("v1.0.0"). WithLoadForGoAnalysis(). diff --git a/test/testdata/configs/decorder.yml b/test/testdata/configs/decorder.yml new file mode 100644 index 000000000000..0ef8e49b3976 --- /dev/null +++ b/test/testdata/configs/decorder.yml @@ -0,0 +1,10 @@ +linters-settings: + decorder: + dec-order: + - type + - const + - var + - func + disable-dec-order-check: false + disable-init-func-first-check: false + disable-dec-num-check: false diff --git a/test/testdata/decorder.go b/test/testdata/decorder.go new file mode 100644 index 000000000000..5cc325cce2e4 --- /dev/null +++ b/test/testdata/decorder.go @@ -0,0 +1,21 @@ +// args: -Edecorder +// config_path: testdata/configs/decorder.yml +package testdata + +import "math" + +const ( + decoc = math.MaxInt64 + decod = 1 +) + +var decoa = 1 +var decob = 1 // ERROR "multiple \"var\" declarations are not allowed; use parentheses instead" + +type decoe int // ERROR "type must not be placed after const" + +func decof() { + const decog = 1 +} + +func init() {} // ERROR "init func must be the first function in file" diff --git a/test/testdata/decorder_default.go b/test/testdata/decorder_default.go new file mode 100644 index 000000000000..69e85a7dac10 --- /dev/null +++ b/test/testdata/decorder_default.go @@ -0,0 +1,20 @@ +// args: -Edecorder +package testdata + +import "math" + +const ( + decoh = math.MaxInt64 + decoi = 1 +) + +var decoj = 1 +var decok = 1 + +type decol int + +func decom() { + const decon = 1 +} + +func init() {}