diff --git a/README.md b/README.md index d19166d..ef8e59e 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ linters-settings: target-methods: ["reportFlushError", "reportError"] # optional. Enabled by default "Debug", "Info", "Warn", "Error" disable-packages: ["pkg1", "pkg2"] # List of packages for which the check should be disabled. constants-package: "git.frostfs.info/rep/logs" # if not set, then the check is disabled + position: 1 # Optional. Argument position in a function that must not be literals. Default: 0. ``` ### useStrconv @@ -73,4 +74,4 @@ linters-settings: settings: useStrconv: # optional enable: true -``` +``` \ No newline at end of file diff --git a/internal/analyzers/noliteral/linter.go b/internal/analyzers/noliteral/linter.go index 26fb97f..af50d95 100644 --- a/internal/analyzers/noliteral/linter.go +++ b/internal/analyzers/noliteral/linter.go @@ -1,6 +1,7 @@ package noliteral import ( + "fmt" "go/ast" "go/token" "slices" @@ -23,6 +24,7 @@ type Configuration struct { DisablePackages []string `mapstructure:"disable-packages"` ConstantsPackage string `mapstructure:"constants-package"` Enable bool `mapstructure:"enable"` + Position *int `mapstructure:"position"` } var defaultTargetMethods = []string{"Debug", "Info", "Warn", "Error"} @@ -44,6 +46,15 @@ func New(conf any) (*analysis.Analyzer, error) { } linter.config.TargetMethods = append(linter.config.TargetMethods, defaultTargetMethods...) + + if linter.config.Position == nil { + linter.config.Position = new(int) + } + + if *linter.config.Position < 0 { + return nil, fmt.Errorf("position contains negative value: %d", *linter.config.Position) + } + return &linter.analyzer, nil } @@ -80,13 +91,14 @@ func (l *noliteral) run(pass *analysis.Pass) (interface{}, error) { func (l *noliteral) analyzeCallExpr(pass *analysis.Pass, expr *ast.CallExpr, file *ast.File) bool { isLog, _ := astutils.IsTargetMethod(expr.Fun, l.config.TargetMethods) - if !isLog || len(expr.Args) == 0 || astutils.HasNoLintComment(pass, expr.Pos()) { + pos := *l.config.Position + if !isLog || len(expr.Args) == 0 || pos >= len(expr.Args) || astutils.HasNoLintComment(pass, expr.Pos()) { return false } - if !astutils.IsStringValue(expr.Args[0]) { + if !astutils.IsStringValue(expr.Args[pos]) { alias, _ := astutils.GetAliasByPkgName(file, l.config.ConstantsPackage) - pkgName := astutils.GetPackageName(expr.Args[0]) + pkgName := astutils.GetPackageName(expr.Args[pos]) if l.config.ConstantsPackage == "" || pkgName == alias || pkgName == "" || slices.Contains(l.config.DisablePackages, pkgName) { return false } diff --git a/internal/analyzers/noliteral/linter_test.go b/internal/analyzers/noliteral/linter_test.go index 96f06c4..8553978 100644 --- a/internal/analyzers/noliteral/linter_test.go +++ b/internal/analyzers/noliteral/linter_test.go @@ -52,6 +52,44 @@ func TestAnalyzer_negative(t *testing.T) { } } +func TestAnalyzer_negativeExtend(t *testing.T) { + const ( + countNegativeCases = 1 + testFilePath = "test-case/literals/negative._go" + ) + + linter, err := New(Configuration{ + ConstantsPackage: "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs", + Position: func(i int) *int { return &i }(1), + }) + if err != nil { + t.Fatal(err) + } + + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, testFilePath, nil, parser.AllErrors) + if err != nil { + t.Fatal(err) + } + + var count int + pass := &analysis.Pass{ + Fset: fset, + Files: []*ast.File{f}, + Report: func(analysis.Diagnostic) { + count++ + }, + } + + if _, err := linter.Run(pass); err != nil { + t.Fatal(err) + } + + if count != countNegativeCases { + t.Errorf("got %d negative cases, want %d", count, countNegativeCases) + } +} + func TestAnalyzer_literals_positive(t *testing.T) { _, filename, _, _ := runtime.Caller(0) dir := filepath.Dir(filename) diff --git a/internal/analyzers/noliteral/test-case/literals/negative._go b/internal/analyzers/noliteral/test-case/literals/negative._go index acfd3f4..95570e3 100644 --- a/internal/analyzers/noliteral/test-case/literals/negative._go +++ b/internal/analyzers/noliteral/test-case/literals/negative._go @@ -17,6 +17,9 @@ func (c *cfg) error_n() { c.log.Error("logs.MSG") //unacceptable } +func (c *cfg) error_n1() { + c.log.Error(ctx, "logs.MSG") +} type Logger interface { Debug(msg string)