Skip to content

Commit 4c3641e

Browse files
authored
fix #1032 by comparing string representations of types (#1049)
1 parent 3249a5e commit 4c3641e

6 files changed

+22
-39
lines changed

RULES_DESCRIPTIONS.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,6 @@ declaration. The 'short' style encourages omitting repeated types for concisenes
389389
whereas the 'full' style mandates explicitly stating the type for each argument
390390
and return value, even if they are repeated, promoting clarity.
391391

392-
_IMPORTANT_: When `short` style is used, the rule will not flag the arguments that use
393-
imported types. This is because the rule cannot efficiently determine the imported type.
394-
395392
_Configuration (1)_: (string) as a single string, it configures both argument
396393
and return value styles. Accepts 'any', 'short', or 'full' (default: 'any').
397394

rule/enforce-repeated-arg-type-style.go

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package rule
33
import (
44
"fmt"
55
"go/ast"
6-
"go/types"
7-
"strings"
86
"sync"
97

108
"github.com/mgechev/revive/lint"
@@ -105,13 +103,6 @@ func (r *EnforceRepeatedArgTypeStyleRule) Apply(file *lint.File, arguments lint.
105103

106104
var failures []lint.Failure
107105

108-
err := file.Pkg.TypeCheck()
109-
if err != nil {
110-
// the file has other issues
111-
return nil
112-
}
113-
typesInfo := file.Pkg.TypesInfo()
114-
115106
astFile := file.AST
116107
ast.Inspect(astFile, func(n ast.Node) bool {
117108
switch fn := n.(type) {
@@ -135,13 +126,14 @@ func (r *EnforceRepeatedArgTypeStyleRule) Apply(file *lint.File, arguments lint.
135126
var prevType ast.Expr
136127
if fn.Type.Params != nil {
137128
for _, field := range fn.Type.Params.List {
138-
// TODO: For invalid types we could have compared raw import names (import package alias + selector), but will it work properly in all the cases?
139-
if !r.isInvalidType(typesInfo.Types[field.Type].Type) && types.Identical(typesInfo.Types[field.Type].Type, typesInfo.Types[prevType].Type) {
129+
prevTypeStr := gofmt(prevType)
130+
currentTypeStr := gofmt(field.Type)
131+
if currentTypeStr == prevTypeStr {
140132
failures = append(failures, lint.Failure{
141133
Confidence: 1,
142-
Node: field,
134+
Node: prevType,
143135
Category: "style",
144-
Failure: "repeated argument type can be omitted",
136+
Failure: fmt.Sprintf("repeated argument type %q can be omitted", prevTypeStr),
145137
})
146138
}
147139
prevType = field.Type
@@ -168,13 +160,14 @@ func (r *EnforceRepeatedArgTypeStyleRule) Apply(file *lint.File, arguments lint.
168160
var prevType ast.Expr
169161
if fn.Type.Results != nil {
170162
for _, field := range fn.Type.Results.List {
171-
// TODO: For invalid types we could have compared raw import names (import package alias + selector), but will it work properly in all the cases?
172-
if !r.isInvalidType(typesInfo.Types[field.Type].Type) && field.Names != nil && types.Identical(typesInfo.Types[field.Type].Type, typesInfo.Types[prevType].Type) {
163+
prevTypeStr := gofmt(prevType)
164+
currentTypeStr := gofmt(field.Type)
165+
if field.Names != nil && currentTypeStr == prevTypeStr {
173166
failures = append(failures, lint.Failure{
174167
Confidence: 1,
175-
Node: field,
168+
Node: prevType,
176169
Category: "style",
177-
Failure: "repeated return type can be omitted",
170+
Failure: fmt.Sprintf("repeated return type %q can be omitted", prevTypeStr),
178171
})
179172
}
180173
prevType = field.Type
@@ -192,10 +185,3 @@ func (r *EnforceRepeatedArgTypeStyleRule) Apply(file *lint.File, arguments lint.
192185
func (*EnforceRepeatedArgTypeStyleRule) Name() string {
193186
return "enforce-repeated-arg-type-style"
194187
}
195-
196-
// Invalid types are imported from other packages, and we can't compare them.
197-
// Note, we check the string suffix to cover all the cases: non-pointer, pointer, double pointer, etc.
198-
// See: https://github.com/mgechev/revive/issues/1032
199-
func (*EnforceRepeatedArgTypeStyleRule) isInvalidType(t types.Type) bool {
200-
return strings.HasSuffix(t.String(), "invalid type")
201-
}

testdata/enforce-repeated-arg-type-style-mixed-full-short.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ package fixtures
22

33
func compliantFunc(a int, b int, c string) (x, y int, z string) // Must not match - compliant with rule
44

5-
func nonCompliantFunc1(a int, b int, c string) (x int, y int, z string) { panic("implement me") } // MATCH /repeated return type can be omitted/
5+
func nonCompliantFunc1(a int, b int, c string) (x int, y int, z string) { panic("implement me") } // MATCH /repeated return type "int" can be omitted/
66
func nonCompliantFunc2(a, b int, c string) (x, y int, z string) { panic("implement me") } // MATCH /argument types should not be omitted/

testdata/enforce-repeated-arg-type-style-mixed-short-full.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ package fixtures
33
func compliantFunc(a, b int, c string) (x int, y int, z string) // Must not match - compliant with rule
44

55
func nonCompliantFunc1(a, b int, c string) (x, y int, z string) { panic("implement me") } // MATCH /return types should not be omitted/
6-
func nonCompliantFunc2(a int, b int, c string) (x int, y int, z string) { panic("implement me") } // MATCH /repeated argument type can be omitted/
6+
func nonCompliantFunc2(a int, b int, c string) (x int, y int, z string) { panic("implement me") } // MATCH /repeated argument type "int" can be omitted/

testdata/enforce-repeated-arg-type-style-short-args.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ package fixtures
22

33
func compliantFunc(a, b int, c string) {} // Must not match - compliant with rule
44

5-
func nonCompliantFunc1(a int, b int, c string) {} // MATCH /repeated argument type can be omitted/
6-
func nonCompliantFunc2(a int, b, c int) {} // MATCH /repeated argument type can be omitted/
5+
func nonCompliantFunc1(a int, b int, c string) {} // MATCH /repeated argument type "int" can be omitted/
6+
func nonCompliantFunc2(a int, b, c int) {} // MATCH /repeated argument type "int" can be omitted/
77

88
type myStruct struct{}
99

1010
func (m myStruct) compliantMethod(a, b int, c string) {} // Must not match - compliant with rule
1111

12-
func (m myStruct) nonCompliantMethod1(a int, b int, c string) {} // MATCH /repeated argument type can be omitted/
13-
func (m myStruct) nonCompliantMethod2(a int, b, c int) {} // MATCH /repeated argument type can be omitted/
12+
func (m myStruct) nonCompliantMethod1(a int, b int, c string) {} // MATCH /repeated argument type "int" can be omitted/
13+
func (m myStruct) nonCompliantMethod2(a int, b, c int) {} // MATCH /repeated argument type "int" can be omitted/
1414

1515
func variadicFunction(a int, b ...int) {} // Must not match - variadic parameters are a special case
1616

1717
func singleArgFunction(a int) {} // Must not match - only one argument
1818

1919
func multiTypeArgs(a int, b string, c float64) {} // Must not match - different types for each argument
2020

21-
func mixedCompliance(a, b int, c int, d string) {} // MATCH /repeated argument type can be omitted/ - 'c int' could be combined with 'a, b int'
21+
func mixedCompliance(a, b int, c int, d string) {} // MATCH /repeated argument type "int" can be omitted/ - 'c int' could be combined with 'a, b int'

testdata/enforce-repeated-arg-type-style-short-return.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ package fixtures
33
func compliantFunc() (a, b int, c string) { panic("implement me") } // Must not match - compliant with rule
44
func compliantFunc2() (int, int, string) // Must not match - compliant with rule
55

6-
func nonCompliantFunc1() (a int, b int, c string) { panic("implement me") } // MATCH /repeated return type can be omitted/
7-
func nonCompliantFunc2() (a int, b, c int) { panic("implement me") } // MATCH /repeated return type can be omitted/
6+
func nonCompliantFunc1() (a int, b int, c string) { panic("implement me") } // MATCH /repeated return type "int" can be omitted/
7+
func nonCompliantFunc2() (a int, b, c int) { panic("implement me") } // MATCH /repeated return type "int" can be omitted/
88

99
type myStruct struct{}
1010

1111
func (m myStruct) compliantMethod() (a, b int, c string) { panic("implement me") } // Must not match - compliant with rule
1212

13-
func (m myStruct) nonCompliantMethod1() (a int, b int, c string) { panic("implement me") } // MATCH /repeated return type can be omitted/
14-
func (m myStruct) nonCompliantMethod2() (a int, b, c int) { panic("implement me") } // MATCH /repeated return type can be omitted/
13+
func (m myStruct) nonCompliantMethod1() (a int, b int, c string) { panic("implement me") } // MATCH /repeated return type "int" can be omitted/
14+
func (m myStruct) nonCompliantMethod2() (a int, b, c int) { panic("implement me") } // MATCH /repeated return type "int" can be omitted/
1515

1616
func singleArgFunction() (a int) { panic("implement me") } // Must not match - only one return
1717

1818
func multiTypeArgs() (a int, b string, c float64) { panic("implement me") } // Must not match - different types for each return
1919

20-
func mixedCompliance() (a, b int, c int, d string) { panic("implement me") } // MATCH /repeated return type can be omitted/ - 'c int' could be combined with 'a, b int'
20+
func mixedCompliance() (a, b int, c int, d string) { panic("implement me") } // MATCH /repeated return type "int" can be omitted/ - 'c int' could be combined with 'a, b int'

0 commit comments

Comments
 (0)