add goprintffuncname linter (#850)

This commit is contained in:
Isaev Denis 2020-01-19 16:46:51 +03:00 committed by GitHub
parent 40d7bcd53e
commit 5f1096cf80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 108 additions and 0 deletions

View File

@ -221,6 +221,7 @@ gofmt: Gofmt checks whether code was gofmt-ed. By default this tool runs with -s
goimports: Goimports does everything that gofmt does. Additionally it checks unused imports [fast: true, auto-fix: true]
golint: Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes [fast: true, auto-fix: false]
gomnd: An analyzer to detect magic numbers. [fast: true, auto-fix: false]
goprintffuncname: Checks that printf-like functions are named with `f` at the end [fast: true, auto-fix: false]
gosec (gas): Inspects source code for security problems [fast: true, auto-fix: false]
interfacer: Linter that suggests narrower interface types [fast: true, auto-fix: false]
lll: Reports long lines [fast: true, auto-fix: false]
@ -485,6 +486,7 @@ golangci-lint help linters
- [whitespace](https://github.com/ultraware/whitespace) - Tool for detection of leading and trailing whitespace
- [wsl](https://github.com/bombsimon/wsl) - Whitespace Linter - Forces you to use empty lines!
- [gomnd](https://github.com/tommy-muehle/go-mnd) - An analyzer to detect magic numbers.
- [goprintffuncname](https://github.com/jirfag/go-printf-func-name) - Checks that printf-like functions are named with `f` at the end
## Configuration
@ -1232,6 +1234,7 @@ Thanks to developers and authors of used linters:
- [matoous](https://github.com/matoous)
- [ultraware](https://github.com/ultraware)
- [bombsimon](https://github.com/bombsimon)
- [jirfag](https://github.com/jirfag)
- [tommy-muehle](https://github.com/tommy-muehle)
## Changelog

1
go.mod
View File

@ -23,6 +23,7 @@ require (
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a
github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb // v1.0
github.com/mattn/go-colorable v0.1.4

2
go.sum
View File

@ -130,6 +130,8 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3 h1:jNYPNLe3d8smommaoQlK7LOA5ESyUJJ+Wf79ZtA7Vp4=
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0=
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a h1:GmsqmapfzSJkm28dhRoHz2tLRbJmqhU86IPgBtN3mmk=
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:xRskid8CManxVta/ALEhJha/pweKBaVG6fWgc0yH25s=
github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5 h1:lrdPtrORjGv1HbbEvKWDUAy97mPpFm4B8hp77tcCUJY=

View File

@ -0,0 +1,17 @@
package golinters
import (
"github.com/jirfag/go-printf-func-name/pkg/analyzer"
"golang.org/x/tools/go/analysis"
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
)
func NewGoPrintfFuncName() *goanalysis.Linter {
return goanalysis.NewLinter(
"goprintffuncname",
"Checks that printf-like functions are named with `f` at the end",
[]*analysis.Analyzer{analyzer.Analyzer},
nil,
).WithLoadMode(goanalysis.LoadModeSyntax)
}

View File

@ -241,6 +241,9 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
linter.NewConfig(golinters.NewWSL()).
WithPresets(linter.PresetStyle).
WithURL("https://github.com/bombsimon/wsl"),
linter.NewConfig(golinters.NewGoPrintfFuncName()).
WithPresets(linter.PresetStyle).
WithURL("https://github.com/jirfag/go-printf-func-name"),
linter.NewConfig(golinters.NewGoMND()).
WithPresets(linter.PresetStyle).
WithURL("https://github.com/tommy-muehle/go-mnd"),

5
test/testdata/goprintffuncname.go vendored Normal file
View File

@ -0,0 +1,5 @@
//args: -Egoprintffuncname
package testdata
func PrintfLikeFuncWithBadName(format string, args ...interface{}) { // ERROR "printf-like formatting function 'PrintfLikeFuncWithBadName' should be named 'PrintfLikeFuncWithBadNamef'"
}

View File

@ -0,0 +1,74 @@
package analyzer
import (
"go/ast"
"strings"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/ast/inspector"
"golang.org/x/tools/go/analysis"
)
var Analyzer = &analysis.Analyzer{
Name: "goprintffuncname",
Doc: "Checks that printf-like functions are named with `f` at the end.",
Run: run,
Requires: []*analysis.Analyzer{inspect.Analyzer},
}
func run(pass *analysis.Pass) (interface{}, error) {
inspector := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
nodeFilter := []ast.Node{
(*ast.FuncDecl)(nil),
}
inspector.Preorder(nodeFilter, func(node ast.Node) {
funcDecl := node.(*ast.FuncDecl)
if res := funcDecl.Type.Results; res != nil && len(res.List) != 0 {
return
}
params := funcDecl.Type.Params.List
if len(params) < 2 { // [0] must be format (string), [1] must be args (...interface{})
return
}
formatParamType, ok := params[len(params)-2].Type.(*ast.Ident)
if !ok { // first param type isn't identificator so it can't be of type "string"
return
}
if formatParamType.Name != "string" { // first param (format) type is not string
return
}
if formatParamNames := params[len(params)-2].Names; len(formatParamNames) == 0 || formatParamNames[len(formatParamNames)-1].Name != "format" {
return
}
argsParamType, ok := params[len(params)-1].Type.(*ast.Ellipsis)
if !ok { // args are not ellipsis (...args)
return
}
elementType, ok := argsParamType.Elt.(*ast.InterfaceType)
if !ok { // args are not of interface type, but we need interface{}
return
}
if elementType.Methods != nil && len(elementType.Methods.List) != 0 {
return // has >= 1 method in interface, but we need an empty interface "interface{}"
}
if strings.HasSuffix(funcDecl.Name.Name, "f") {
return
}
pass.Reportf(node.Pos(), "printf-like formatting function '%s' should be named '%sf'",
funcDecl.Name.Name, funcDecl.Name.Name)
})
return nil, nil
}

3
vendor/modules.txt vendored
View File

@ -99,6 +99,8 @@ github.com/hashicorp/hcl/json/scanner
github.com/hashicorp/hcl/json/token
# github.com/inconshreveable/mousetrap v1.0.0
github.com/inconshreveable/mousetrap
# github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3
github.com/jirfag/go-printf-func-name/pkg/analyzer
# github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a
github.com/jingyugao/rowserrcheck/passes/rowserr
# github.com/kisielk/gotool v1.0.0
@ -194,6 +196,7 @@ golang.org/x/sys/windows
golang.org/x/text/transform
golang.org/x/text/unicode/norm
golang.org/x/text/width
# golang.org/x/tools v0.0.0-20191108193012-7d206e10da11 => github.com/golangci/tools v0.0.0-20190915081525-6aa350649b1c
# golang.org/x/tools v0.0.0-20200102140908-9497f49d5709 => github.com/golangci/tools v0.0.0-20190915081525-6aa350649b1c
golang.org/x/tools/go/analysis
golang.org/x/tools/go/analysis/passes/asmdecl