diff --git a/Makefile b/Makefile index be17fbb..918d6a0 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ lint: govulncheck ./... build: - go build -ldflags="$(BUILD_LDFLAGS)" -o gostyle cmd/gostyle/main.go + go build -ldflags="$(BUILD_LDFLAGS)" -o gostyle depsdev: go install github.com/Songmu/ghch/cmd/ghch@latest diff --git a/analyzer/effective/ifacenames/ifacenames.go b/analyzer/effective/ifacenames/ifacenames.go index 9be2380..fab2f9b 100644 --- a/analyzer/effective/ifacenames/ifacenames.go +++ b/analyzer/effective/ifacenames/ifacenames.go @@ -10,12 +10,15 @@ import ( "golang.org/x/tools/go/ast/inspector" ) -const doc = "https://go.dev/doc/effective_go#interface-names" +const doc = "Analyzer based on https://go.dev/doc/effective_go#interface-names." -// Analyzer for https://go.dev/doc/effective_go#interface-names +var all bool + +// Analyzer based on https://go.dev/doc/effective_go#interface-names. var Analyzer = &analysis.Analyzer{ Name: "ifacenames", Doc: doc, + URL: "https://github.com/k1LoW/gostyle/tree/main/analyzer/effective/ifacenames", Run: run, Requires: []*analysis.Analyzer{ inspect.Analyzer, @@ -39,10 +42,15 @@ func run(pass *analysis.Pass) (any, error) { case *ast.InterfaceType: if len(n.Methods.List) == 1 { mn := n.Methods.List[0].Names[0].Name - if !strings.HasPrefix(ii.Name, mn) || !strings.HasSuffix(ii.Name, "er") { - pass.Reportf(n.Pos(), "By convention, one-method interfaces are named by the method name plus an -er suffix or similar modification to construct an agent noun. (ref: https://go.dev/doc/effective_go#interface-names)") + if !strings.HasPrefix(ii.Name, mn) || !strings.HasSuffix(ii.Name, "er") { // huristic + pass.Reportf(n.Pos(), "by convention, one-method interfaces are named by the method name plus an -er suffix or similar modification to construct an agent noun. (ref: https://go.dev/doc/effective_go#interface-names)") + return } } + if all && !strings.HasSuffix(ii.Name, "er") { + pass.Reportf(n.Pos(), "all interface names with the -er suffix are required.") + return + } case *ast.Ident: ii = n } @@ -50,3 +58,7 @@ func run(pass *analysis.Pass) (any, error) { return nil, nil } + +func init() { + Analyzer.Flags.BoolVar(&all, "all", false, "all interface names with the -er suffix are required") +} diff --git a/analyzer/effective/ifacenames/ifacenames_test.go b/analyzer/effective/ifacenames/ifacenames_test.go index 911d4cb..2ffe4c0 100644 --- a/analyzer/effective/ifacenames/ifacenames_test.go +++ b/analyzer/effective/ifacenames/ifacenames_test.go @@ -9,6 +9,16 @@ import ( // TestAnalyzer is a test for Analyzer. func TestAnalyzer(t *testing.T) { - testdata := testutil.WithModules(t, analysistest.TestData(), nil) - analysistest.Run(t, testdata, Analyzer, "a") + tests := []struct { + all bool // -all flag + pkg string + }{ + {false, "a"}, + {true, "b"}, + } + for _, tt := range tests { + all = tt.all + testdata := testutil.WithModules(t, analysistest.TestData(), nil) + analysistest.Run(t, testdata, Analyzer, tt.pkg) + } } diff --git a/analyzer/effective/ifacenames/testdata/src/a/a.go b/analyzer/effective/ifacenames/testdata/src/a/a.go index 89b8d59..b51842a 100644 --- a/analyzer/effective/ifacenames/testdata/src/a/a.go +++ b/analyzer/effective/ifacenames/testdata/src/a/a.go @@ -1,13 +1,18 @@ package a -type Query interface { // want "By convention, one-method interfaces are named by the method name plus an -er suffix or similar modification to construct an agent noun." +type Query interface { // want "-er suffix" Do() error } -type Closer interface { // want "By convention, one-method interfaces are named by the method name plus an -er suffix or similar modification to construct an agent noun." +type Closer interface { // want "-er suffix" Do() error } type Writer interface { Write() error } + +type Add interface { + One() error + Two() error +} diff --git a/analyzer/effective/ifacenames/testdata/src/b/b.go b/analyzer/effective/ifacenames/testdata/src/b/b.go new file mode 100644 index 0000000..4e8ffc5 --- /dev/null +++ b/analyzer/effective/ifacenames/testdata/src/b/b.go @@ -0,0 +1,18 @@ +package b + +type Query interface { // want "-er suffix" + Do() error +} + +type Closer interface { // want "-er suffix" + Do() error +} + +type Writer interface { + Write() error +} + +type Add interface { // want "-er suffix" + One() error + Two() error +} diff --git a/analyzer/effective/ifacenames/testdata/src/b/go.mod b/analyzer/effective/ifacenames/testdata/src/b/go.mod new file mode 100644 index 0000000..bbfbe3a --- /dev/null +++ b/analyzer/effective/ifacenames/testdata/src/b/go.mod @@ -0,0 +1,3 @@ +module b + +go 1.21