Skip to content

Commit a228403

Browse files
authored
Merge pull request #5 from uudashr/opaque_suggestedfix
Add fix suggestion for opaque analyzer
2 parents 016239e + ddf997c commit a228403

File tree

6 files changed

+243
-11
lines changed

6 files changed

+243
-11
lines changed

opaque/opaque.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,12 +274,28 @@ func (r *runner) run(pass *analysis.Pass) (interface{}, error) {
274274
stmtTypName = removePkgPrefix(stmtTypName)
275275
}
276276

277-
pass.Reportf(result.Pos(),
278-
"%s function return %s interface at the %s result, abstract a single concrete implementation of %s",
277+
msg := fmt.Sprintf("%s function return %s interface at the %s result, abstract a single concrete implementation of %s",
279278
funcDecl.Name.Name,
280279
retTypeName,
281280
positionStr(currentIdx),
282281
stmtTypName)
282+
283+
pass.Report(analysis.Diagnostic{
284+
Pos: result.Pos(),
285+
Message: msg,
286+
SuggestedFixes: []analysis.SuggestedFix{
287+
{
288+
Message: "Replace the interface return type with the concrete type",
289+
TextEdits: []analysis.TextEdit{
290+
{
291+
Pos: result.Pos(),
292+
End: result.End(),
293+
NewText: []byte(stmtTypName),
294+
},
295+
},
296+
},
297+
},
298+
})
283299
}
284300
})
285301

opaque/opaque_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ import (
99

1010
func TestAnalyzer(t *testing.T) {
1111
testdata := analysistest.TestData()
12-
analysistest.Run(t, testdata, opaque.Analyzer, "a")
13-
analysistest.Run(t, testdata, opaque.Analyzer, "b")
14-
analysistest.Run(t, testdata, opaque.Analyzer, "c")
15-
analysistest.Run(t, testdata, opaque.Analyzer, "d")
16-
analysistest.Run(t, testdata, opaque.Analyzer, "e")
17-
analysistest.Run(t, testdata, opaque.Analyzer, "f")
18-
analysistest.Run(t, testdata, opaque.Analyzer, "g")
19-
analysistest.Run(t, testdata, opaque.Analyzer, "h")
20-
analysistest.Run(t, testdata, opaque.Analyzer, "x")
12+
analysistest.RunWithSuggestedFixes(t, testdata, opaque.Analyzer, "a")
13+
analysistest.RunWithSuggestedFixes(t, testdata, opaque.Analyzer, "b")
14+
analysistest.RunWithSuggestedFixes(t, testdata, opaque.Analyzer, "c")
15+
analysistest.RunWithSuggestedFixes(t, testdata, opaque.Analyzer, "d")
16+
analysistest.RunWithSuggestedFixes(t, testdata, opaque.Analyzer, "e")
17+
analysistest.RunWithSuggestedFixes(t, testdata, opaque.Analyzer, "f")
18+
analysistest.RunWithSuggestedFixes(t, testdata, opaque.Analyzer, "g")
19+
analysistest.RunWithSuggestedFixes(t, testdata, opaque.Analyzer, "h")
20+
analysistest.RunWithSuggestedFixes(t, testdata, opaque.Analyzer, "x")
2121
}

opaque/testdata/src/a/a.go.golden

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package app
2+
3+
type Server interface {
4+
Serve() error
5+
}
6+
7+
type server struct {
8+
addr string
9+
}
10+
11+
func (s server) Serve() error {
12+
return nil
13+
}
14+
15+
func NewServer(addr string) *server { // want "NewServer function return Server interface at the 1st result, abstract a single concrete implementation of \\*server"
16+
return newServer(addr)
17+
}
18+
19+
func NewServer2(addr string) server { // want "NewServer2 function return Server interface at the 1st result, abstract a single concrete implementation of server"
20+
return server{addr: addr}
21+
}
22+
23+
func NewServer3(addr string) *server { // want "NewServer3 function return Server interface at the 1st result, abstract a single concrete implementation of \\*server"
24+
return &server{addr: addr}
25+
}
26+
27+
func newServer(addr string) *server {
28+
return &server{addr: addr}
29+
}
30+
31+
type secureServer struct {
32+
addr string
33+
}
34+
35+
func (ss *secureServer) Serve() error {
36+
return nil
37+
}
38+
39+
func NewSecureServer(addr string) *secureServer { // want "NewSecureServer function return Server interface at the 1st result, abstract a single concrete implementation of \\*secureServer"
40+
return &secureServer{addr: addr}
41+
}

opaque/testdata/src/f/f.go.golden

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package tracing
2+
3+
import "context"
4+
5+
type Tracer interface{}
6+
7+
var GlobalTracer Tracer
8+
9+
type Span interface {
10+
Finish()
11+
}
12+
13+
type span struct {
14+
}
15+
16+
func (s *span) Finish() {
17+
}
18+
19+
func StartSpanFromContext(ctx context.Context) (Span, error) {
20+
return StartSpanFromContextWithTracer(ctx, GlobalTracer)
21+
}
22+
23+
func StartSpanFromContextWithTracer(ctx context.Context, tracer Tracer) (Span, error) {
24+
return nil, nil
25+
}
26+
27+
func StartSpanFromContext2(ctx context.Context) (*span, error) { // want "StartSpanFromContext2 function return Span interface at the 1st result, abstract a single concrete implementation of \\*span"
28+
return startSpanFromContextWithTracer(ctx, GlobalTracer)
29+
}
30+
31+
func startSpanFromContextWithTracer(ctx context.Context, tracer Tracer) (*span, error) {
32+
return nil, nil
33+
}

opaque/testdata/src/h/h.go.golden

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package app
2+
3+
type Server interface {
4+
Serve() error
5+
}
6+
7+
type server struct {
8+
addr string
9+
}
10+
11+
func (s server) Serve() error {
12+
return nil
13+
}
14+
15+
//iface:ignore
16+
func NewServer(addr string) Server {
17+
return newServer(addr)
18+
}
19+
20+
func NewServer2(addr string) server { // want "NewServer2 function return Server interface at the 1st result, abstract a single concrete implementation of server"
21+
return server{addr: addr}
22+
}
23+
24+
func newServer(addr string) *server {
25+
return &server{addr: addr}
26+
}

opaque/testdata/src/x/x.go.golden

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package mask
2+
3+
import (
4+
"context"
5+
"errors"
6+
"strings"
7+
)
8+
9+
type Doer interface {
10+
Do()
11+
DoItAgain()
12+
}
13+
14+
type DoerImpl struct {
15+
}
16+
17+
func (di DoerImpl) Do() {
18+
19+
}
20+
21+
func (di *DoerImpl) DoItAgain() {
22+
23+
}
24+
25+
type DoerV2Impl struct {
26+
}
27+
28+
func (d2i DoerV2Impl) Do() {
29+
30+
}
31+
32+
func (d2i *DoerV2Impl) DoItAgain() {
33+
34+
}
35+
36+
func NewDoer() *DoerImpl { // want "NewDoer function return Doer interface at the 1st result, abstract a single concrete implementation of \\*DoerImpl"
37+
return &DoerImpl{}
38+
}
39+
40+
func MultiDoer(spec string) Doer {
41+
if spec == "v2" {
42+
return &DoerV2Impl{}
43+
}
44+
45+
if spec == "v1" {
46+
return &DoerImpl{}
47+
}
48+
49+
return &DoerImpl{}
50+
}
51+
52+
func NewDoerWithError() (Doer, error) {
53+
return nil, nil
54+
}
55+
56+
func NewDoerWithOK() (Doer, bool) {
57+
Inspect(func(in interface{}) bool {
58+
return true
59+
})
60+
61+
var x = func() bool {
62+
return true
63+
}
64+
65+
if x() {
66+
return nil, true
67+
}
68+
69+
return nil, false
70+
}
71+
72+
func NewDoerWithContext(ctx context.Context) (context.Context, Doer) {
73+
if ctx == nil {
74+
return newDoerWithContext()
75+
}
76+
77+
return context.TODO(), nil
78+
}
79+
80+
func newDoerWithContext() (context.Context, Doer) {
81+
return nil, nil
82+
// return newDoerImplWithContext()
83+
}
84+
85+
func newDoerImplWithContext() (context.Context, *DoerImpl) {
86+
return context.TODO(), nil
87+
}
88+
89+
func NewDoerImpl() *DoerImpl {
90+
return &DoerImpl{}
91+
}
92+
93+
func NewDoerStruct() DoerImpl {
94+
return DoerImpl{}
95+
}
96+
97+
func Inspect(fn func(in interface{}) bool) {
98+
_ = fn(DoerImpl{})
99+
}
100+
101+
func NewContext() context.Context {
102+
return &myContextImpl{}
103+
}
104+
105+
type myContextImpl struct {
106+
context.Context
107+
}
108+
109+
func SplitCompleteVer(ver string) (major, minor, patch string, err error) {
110+
parts := strings.Split(ver, ".")
111+
if len(parts) != 3 {
112+
return "", "", "", errors.New("invalid complete version")
113+
}
114+
115+
return parts[0], parts[1], parts[2], nil
116+
}

0 commit comments

Comments
 (0)