diff --git a/.golangci.example.yml b/.golangci.example.yml index 3512ec05a942..06517e15f95a 100644 --- a/.golangci.example.yml +++ b/.golangci.example.yml @@ -444,6 +444,11 @@ linters-settings: - ginkgo\\.F.* # these are used just for local development # Exclude godoc examples from forbidigo checks. Default is true. exclude_godoc_examples: false + importas: + # using `servingv1` alias for `knative.dev/serving/pkg/apis/serving/v1` package + servingv1: knative.dev/serving/pkg/apis/serving/v1 + # using `autoscalingv1alpha1` alias for `knative.dev/serving/pkg/apis/autoscaling/v1alpha1` package + autoscalingv1alpha1: knative.dev/serving/pkg/apis/autoscaling/v1alpha1 # The custom section can be used to define linter plugins to be loaded at runtime. See README doc # for more info. diff --git a/go.mod b/go.mod index 2302e8707fb5..e09e9009570e 100644 --- a/go.mod +++ b/go.mod @@ -34,6 +34,7 @@ require ( github.com/jgautheron/goconst v0.0.0-20201117150253-ccae5bf973f3 github.com/jingyugao/rowserrcheck v0.0.0-20210130005344-c6a0c12dd98d github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3 + github.com/julz/importas v0.0.0-20210226073942-60b4fa260dd0 github.com/kisielk/errcheck v1.6.0 github.com/kulti/thelper v0.4.0 github.com/kunwardeep/paralleltest v1.0.2 diff --git a/go.sum b/go.sum index 9e88d7142295..cde06d192067 100644 --- a/go.sum +++ b/go.sum @@ -219,6 +219,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julz/importas v0.0.0-20210226073942-60b4fa260dd0 h1:exZBMUS/kB/AhxSj/9lIIxhqkCpXXdKScjFWQUTbi3M= +github.com/julz/importas v0.0.0-20210226073942-60b4fa260dd0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.6.0 h1:YTDO4pNy7AUN/021p+JGHycQyYNIyMoenM1YDVK6RlY= github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= diff --git a/pkg/config/config.go b/pkg/config/config.go index fdf57875c0c1..202ae6bc44cb 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -275,6 +275,7 @@ type LintersSettings struct { Ifshort IfshortSettings Predeclared PredeclaredSettings Cyclop Cyclop + ImportAs ImportAsSettings Custom map[string]CustomLinterSettings } @@ -461,6 +462,8 @@ type Cyclop struct { SkipTests bool `mapstructure:"skip-tests"` } +type ImportAsSettings map[string]string + var defaultLintersSettings = LintersSettings{ Lll: LllSettings{ LineLength: 120, diff --git a/pkg/golinters/importas.go b/pkg/golinters/importas.go new file mode 100644 index 000000000000..41fbcb71248b --- /dev/null +++ b/pkg/golinters/importas.go @@ -0,0 +1,34 @@ +package golinters + +import ( + "fmt" + + "github.com/julz/importas" // nolint: misspell + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + "github.com/golangci/golangci-lint/pkg/lint/linter" +) + +func NewImportAs(settings *config.ImportAsSettings) *goanalysis.Linter { + analyzer := importas.Analyzer + + return goanalysis.NewLinter( + analyzer.Name, + analyzer.Doc, + []*analysis.Analyzer{analyzer}, + nil, + ).WithContextSetter(func(lintCtx *linter.Context) { + if settings == nil { + return + } + + for alias, pkg := range *settings { + err := analyzer.Flags.Set("alias", fmt.Sprintf("%s:%s", pkg, alias)) + if err != nil { + lintCtx.Log.Errorf("failed to parse configuration: %v", err) + } + } + }).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index 17f621898d75..8881bc46f579 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -99,6 +99,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { var ifshortCfg *config.IfshortSettings var reviveCfg *config.ReviveSettings var cyclopCfg *config.Cyclop + var importAsCfg *config.ImportAsSettings if m.cfg != nil { govetCfg = &m.cfg.LintersSettings.Govet testpackageCfg = &m.cfg.LintersSettings.Testpackage @@ -110,6 +111,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { ifshortCfg = &m.cfg.LintersSettings.Ifshort reviveCfg = &m.cfg.LintersSettings.Revive cyclopCfg = &m.cfg.LintersSettings.Cyclop + importAsCfg = &m.cfg.LintersSettings.ImportAs } const megacheckName = "megacheck" lcs := []*linter.Config{ @@ -380,6 +382,10 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithPresets(linter.PresetStyle). WithLoadForGoAnalysis(). WithURL("https://github.com/sanposhiho/wastedassign"), + linter.NewConfig(golinters.NewImportAs(importAsCfg)). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/julz/importas"), // nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives linter.NewConfig(golinters.NewNoLintLint()). diff --git a/test/testdata/configs/importas.yml b/test/testdata/configs/importas.yml new file mode 100644 index 000000000000..698f00b7f5c3 --- /dev/null +++ b/test/testdata/configs/importas.yml @@ -0,0 +1,4 @@ +linters-settings: + importas: + fff: fmt + std_os: os diff --git a/test/testdata/importas.go b/test/testdata/importas.go new file mode 100644 index 000000000000..ee560c1c3a3e --- /dev/null +++ b/test/testdata/importas.go @@ -0,0 +1,13 @@ +//args: -Eimportas +//config_path: testdata/configs/importas.yml +package testdata + +import ( + wrong_alias "fmt" // ERROR `import "fmt" imported as "wrong_alias" but must be "fff" according to config` + wrong_alias_again "os" // ERROR `import "os" imported as "wrong_alias_again" but must be "std_os" according to config` +) + +func ImportAsWrongAlias() { + wrong_alias.Println("foo") + wrong_alias_again.Stdout.WriteString("bar") +}