From 1a2732a36dd189778960662b5f7e26c00ddc69de Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Mon, 18 Nov 2024 19:22:36 +0200 Subject: [PATCH] feat: add `redundant-build-tag` rule --- README.md | 1 + RULES_DESCRIPTIONS.md | 8 ++++ config/config.go | 1 + rule/redundant_build_tag.go | 43 ++++++++++++++++++++++ test/redundant_build_tag_test.go | 20 ++++++++++ testdata/redundant_build_tag.go | 6 +++ testdata/redundant_build_tag_go116.go | 6 +++ testdata/redundant_build_tag_no_failure.go | 3 ++ 8 files changed, 88 insertions(+) create mode 100644 rule/redundant_build_tag.go create mode 100644 test/redundant_build_tag_test.go create mode 100644 testdata/redundant_build_tag.go create mode 100644 testdata/redundant_build_tag_go116.go create mode 100644 testdata/redundant_build_tag_no_failure.go diff --git a/README.md b/README.md index e40bf9793..6a5aa611b 100644 --- a/README.md +++ b/README.md @@ -550,6 +550,7 @@ List of all available rules. The rules ported from `golint` are left unchanged a | [`comments-density`](./RULES_DESCRIPTIONS.md#comments-density) | int (defaults to 0) | Enforces a minimum comment / code relation | no | no | | [`file-length-limit`](./RULES_DESCRIPTIONS.md#file-length-limit) | map (optional)| Enforces a maximum number of lines per file | no | no | | [`filename-format`](./RULES_DESCRIPTIONS.md#filename-format) | regular expression (optional) | Enforces the formatting of filenames | no | no | +| [`redundant-build-tag`](./RULES_DESCRIPTIONS.md#redundant-build-tag) | n/a | Warns about redundant `// +build` comment lines | no | no | ## Configurable rules diff --git a/RULES_DESCRIPTIONS.md b/RULES_DESCRIPTIONS.md index d76f6b11e..31b0a7e95 100644 --- a/RULES_DESCRIPTIONS.md +++ b/RULES_DESCRIPTIONS.md @@ -65,6 +65,7 @@ List of all available rules. - [receiver-naming](#receiver-naming) - [redefines-builtin-id](#redefines-builtin-id) - [redundant-import-alias](#redundant-import-alias) + - [redundant-build-tag](#redundant-build-tag) - [string-format](#string-format) - [string-of-int](#string-of-int) - [struct-tag](#struct-tag) @@ -799,6 +800,13 @@ _Description_: This rule warns on redundant import aliases. This happens when th _Configuration_: N/A +## redundant-build-tag + +_Description_: This rule warns about redundant build tag comments `// +build` when `//go:build` is present. +`gofmt` in Go 1.17+ automatically adds the `//go:build` constraint, making the `// +build` comment unnecessary. + +_Configuration_: N/A + ## string-format _Description_: This rule allows you to configure a list of regular expressions that string literals in certain function calls are checked against. diff --git a/config/config.go b/config/config.go index b8b236003..1da7386ca 100644 --- a/config/config.go +++ b/config/config.go @@ -98,6 +98,7 @@ var allRules = append([]lint.Rule{ &rule.CommentsDensityRule{}, &rule.FileLengthLimitRule{}, &rule.FilenameFormatRule{}, + &rule.RedundantBuildTagRule{}, }, defaultRules...) var allFormatters = []lint.Formatter{ diff --git a/rule/redundant_build_tag.go b/rule/redundant_build_tag.go new file mode 100644 index 000000000..b7bc0d4b9 --- /dev/null +++ b/rule/redundant_build_tag.go @@ -0,0 +1,43 @@ +package rule + +import ( + "strings" + + "github.com/mgechev/revive/lint" +) + +// RedundantBuildTagRule lints the presence of redundant build tags. +type RedundantBuildTagRule struct{} + +// Apply triggers if an old build tag `// +build` is found after a new one `//go:build`. +// `//go:build` comments are automatically added by gofmt when Go 1.17+ is used. +// See https://pkg.go.dev/cmd/go#hdr-Build_constraints +func (*RedundantBuildTagRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + var failures []lint.Failure + + for _, group := range file.AST.Comments { + hasGoBuild := false + for _, comment := range group.List { + if strings.HasPrefix(comment.Text, "//go:build ") { + hasGoBuild = true + continue + } + if hasGoBuild && strings.HasPrefix(comment.Text, "// +build ") { + failures = append(failures, lint.Failure{ + Category: "style", + Confidence: 1, + Node: comment, + Failure: `The build tag "// +build" is redundant since Go 1.17 and can be removed`, + }) + return failures + } + } + } + + return failures +} + +// Name returns the rule name. +func (*RedundantBuildTagRule) Name() string { + return "redundant-build-tag" +} diff --git a/test/redundant_build_tag_test.go b/test/redundant_build_tag_test.go new file mode 100644 index 000000000..736587021 --- /dev/null +++ b/test/redundant_build_tag_test.go @@ -0,0 +1,20 @@ +package test + +import ( + "testing" + + "github.com/mgechev/revive/lint" + "github.com/mgechev/revive/rule" +) + +func TestRedundantBuildTagRule(t *testing.T) { + testRule(t, "redundant_build_tag", &rule.RedundantBuildTagRule{}, &lint.RuleConfig{}) +} + +func TestRedundantBuildTagRuleNoFailure(t *testing.T) { + testRule(t, "redundant_build_tag_no_failure", &rule.RedundantBuildTagRule{}, &lint.RuleConfig{}) +} + +func TestRedundantBuildTagRuleGo116(t *testing.T) { + testRule(t, "redundant_build_tag_go116", &rule.RedundantBuildTagRule{}, &lint.RuleConfig{}) +} diff --git a/testdata/redundant_build_tag.go b/testdata/redundant_build_tag.go new file mode 100644 index 000000000..8a38f96d9 --- /dev/null +++ b/testdata/redundant_build_tag.go @@ -0,0 +1,6 @@ +//go:build tag +// +build tag + +// MATCH:2 /The build tag "// +build" is redundant since Go 1.17 and can be removed/ + +package pkg diff --git a/testdata/redundant_build_tag_go116.go b/testdata/redundant_build_tag_go116.go new file mode 100644 index 000000000..81b72821d --- /dev/null +++ b/testdata/redundant_build_tag_go116.go @@ -0,0 +1,6 @@ +// +build tag + +// This means that the file is for Go less than 1.17 because +// gofmt automatically adds the new build tag `//go:build` when Go 1.17+ is used. + +package pkg diff --git a/testdata/redundant_build_tag_no_failure.go b/testdata/redundant_build_tag_no_failure.go new file mode 100644 index 000000000..4f58c8877 --- /dev/null +++ b/testdata/redundant_build_tag_no_failure.go @@ -0,0 +1,3 @@ +//go:build tag + +package pkg