Skip to content

Commit 62b850f

Browse files
mvdanadonovan
authored andcommitted
cmd/vet: rewrite method check to use go/types
Now that vet can rely on go/types, there's no reason to do extra work to avoid using it. The rewrite lets us get rid of the field list flattening code, as well as the slight verbosity that comes with go/printer. While at it, make the testdata/method.go expected errors be more specific, to make sure that we're not breaking the warnings that are printed. Finally, update whitelist/all.txt, since the reported errors now include qualified types. Change-Id: I760a1b3b1f60e4a478c9dc43bd7f584a8459593e Reviewed-on: https://go-review.googlesource.com/c/148919 Run-TryBot: Daniel Martí <[email protected]> Reviewed-by: Alan Donovan <[email protected]>
1 parent 160ddf7 commit 62b850f

File tree

3 files changed

+21
-50
lines changed

3 files changed

+21
-50
lines changed

src/cmd/vet/all/whitelist/all.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ runtime/pprof/pprof.go: method WriteTo(w io.Writer, debug int) error should have
5757
// vet doesn't know it because they are *in* the encoding/xml package.
5858
// It's not worth teaching vet about the distinction, so whitelist them.
5959
encoding/gob/encode.go: method WriteByte(c byte) should have signature WriteByte(byte) error
60-
encoding/xml/marshal.go: method MarshalXML(e *Encoder, start StartElement) error should have signature MarshalXML(*xml.Encoder, xml.StartElement) error
61-
encoding/xml/marshal_test.go: method MarshalXML(e *Encoder, start StartElement) error should have signature MarshalXML(*xml.Encoder, xml.StartElement) error
62-
encoding/xml/read.go: method UnmarshalXML(d *Decoder, start StartElement) error should have signature UnmarshalXML(*xml.Decoder, xml.StartElement) error
63-
encoding/xml/read_test.go: method UnmarshalXML(d *Decoder, start StartElement) error should have signature UnmarshalXML(*xml.Decoder, xml.StartElement) error
64-
encoding/xml/xml_test.go: method UnmarshalXML(*Decoder, StartElement) error should have signature UnmarshalXML(*xml.Decoder, xml.StartElement) error
60+
encoding/xml/marshal.go: method MarshalXML(e *xml.Encoder, start xml.StartElement) error should have signature MarshalXML(*xml.Encoder, xml.StartElement) error
61+
encoding/xml/marshal_test.go: method MarshalXML(e *xml.Encoder, start xml.StartElement) error should have signature MarshalXML(*xml.Encoder, xml.StartElement) error
62+
encoding/xml/read.go: method UnmarshalXML(d *xml.Decoder, start xml.StartElement) error should have signature UnmarshalXML(*xml.Decoder, xml.StartElement) error
63+
encoding/xml/read_test.go: method UnmarshalXML(d *xml.Decoder, start xml.StartElement) error should have signature UnmarshalXML(*xml.Decoder, xml.StartElement) error
64+
encoding/xml/xml_test.go: method UnmarshalXML(*xml.Decoder, xml.StartElement) error should have signature UnmarshalXML(*xml.Decoder, xml.StartElement) error
6565

6666
// Long struct tags used to test reflect internals
6767
cmd/link/link_test.go: struct field tag "\n\tLondon. Michaelmas term lately over, and the Lord Chancellor sitting in Lincoln’s Inn Hall. Implacable November weather. As much mud in the streets as if the waters had but newly retired from the face of the earth, and it would not be wonderful to meet a Megalosaurus, forty feet long or so, waddling like an elephantine lizard up Holborn Hill. Smoke lowering down from chimney-pots, making a soft black drizzle, with flakes of soot in it as big as full-grown snowflakes—gone into mourning, one might imagine, for the death of the sun. Dogs, undistinguishable in mire. Horses, scarcely better; splashed to their very blinkers. Foot passengers, jostling one another’s umbrellas in a general infection of ill temper, and losing their foot-hold at street-corners, where tens of thousands of other foot passengers have been slipping and sliding since the day broke (if this day ever broke), adding new deposits to the crust upon crust of mud, sticking at those points tenaciously to the pavement, and accumulating at compound interest.\n\n\tFog everywhere. Fog up the river, where it flows among green aits and meadows; fog down the river, where it rolls defiled among the tiers of shipping and the waterside pollutions of a great (and dirty) city. Fog on the Essex marshes, fog on the Kentish heights. Fog creeping into the cabooses of collier-brigs; fog lying out on the yards and hovering in the rigging of great ships; fog drooping on the gunwales of barges and small boats. Fog in the eyes and throats of ancient Greenwich pensioners, wheezing by the firesides of their wards; fog in the stem and bowl of the afternoon pipe of the wrathful skipper, down in his close cabin; fog cruelly pinching the toes and fingers of his shivering little ‘prentice boy on deck. Chance people on the bridges peeping over the parapets into a nether sky of fog, with fog all round them, as if they were up in a balloon and hanging in the misty clouds.\n\n\tGas looming through the fog in divers places in the streets, much as the sun may, from the spongey fields, be seen to loom by husbandman and ploughboy. Most of the shops lighted two hours before their time—as the gas seems to know, for it has a haggard and unwilling look.\n\n\tThe raw afternoon is rawest, and the dense fog is densest, and the muddy streets are muddiest near that leaden-headed old obstruction, appropriate ornament for the threshold of a leaden-headed old corporation, Temple Bar. And hard by Temple Bar, in Lincoln’s Inn Hall, at the very heart of the fog, sits the Lord High Chancellor in his High Court of Chancery." not compatible with reflect.StructTag.Get: bad syntax for struct tag key

src/cmd/vet/method.go

Lines changed: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@
77
package main
88

99
import (
10-
"fmt"
1110
"go/ast"
12-
"go/printer"
11+
"go/types"
1312
"strings"
1413
)
1514

@@ -65,30 +64,26 @@ func checkCanonicalMethod(f *File, node ast.Node) {
6564
switch n := node.(type) {
6665
case *ast.FuncDecl:
6766
if n.Recv != nil {
68-
canonicalMethod(f, n.Name, n.Type)
67+
canonicalMethod(f, n.Name)
6968
}
7069
case *ast.InterfaceType:
7170
for _, field := range n.Methods.List {
7271
for _, id := range field.Names {
73-
canonicalMethod(f, id, field.Type.(*ast.FuncType))
72+
canonicalMethod(f, id)
7473
}
7574
}
7675
}
7776
}
7877

79-
func canonicalMethod(f *File, id *ast.Ident, t *ast.FuncType) {
78+
func canonicalMethod(f *File, id *ast.Ident) {
8079
// Expected input/output.
8180
expect, ok := canonicalMethods[id.Name]
8281
if !ok {
8382
return
8483
}
85-
86-
// Actual input/output
87-
args := typeFlatten(t.Params.List)
88-
var results []ast.Expr
89-
if t.Results != nil {
90-
results = typeFlatten(t.Results.List)
91-
}
84+
sign := f.pkg.defs[id].Type().(*types.Signature)
85+
args := sign.Params()
86+
results := sign.Results()
9287

9388
// Do the =s (if any) all match?
9489
if !f.matchParams(expect.args, args, "=") || !f.matchParams(expect.results, results, "=") {
@@ -104,11 +99,7 @@ func canonicalMethod(f *File, id *ast.Ident, t *ast.FuncType) {
10499
expectFmt += " (" + argjoin(expect.results) + ")"
105100
}
106101

107-
f.b.Reset()
108-
if err := printer.Fprint(&f.b, f.fset, t); err != nil {
109-
fmt.Fprintf(&f.b, "<%s>", err)
110-
}
111-
actual := f.b.String()
102+
actual := sign.String()
112103
actual = strings.TrimPrefix(actual, "func")
113104
actual = id.Name + actual
114105

@@ -127,53 +118,33 @@ func argjoin(x []string) string {
127118
return strings.Join(y, ", ")
128119
}
129120

130-
// Turn parameter list into slice of types
131-
// (in the ast, types are Exprs).
132-
// Have to handle f(int, bool) and f(x, y, z int)
133-
// so not a simple 1-to-1 conversion.
134-
func typeFlatten(l []*ast.Field) []ast.Expr {
135-
var t []ast.Expr
136-
for _, f := range l {
137-
if len(f.Names) == 0 {
138-
t = append(t, f.Type)
139-
continue
140-
}
141-
for range f.Names {
142-
t = append(t, f.Type)
143-
}
144-
}
145-
return t
146-
}
147-
148121
// Does each type in expect with the given prefix match the corresponding type in actual?
149-
func (f *File) matchParams(expect []string, actual []ast.Expr, prefix string) bool {
122+
func (f *File) matchParams(expect []string, actual *types.Tuple, prefix string) bool {
150123
for i, x := range expect {
151124
if !strings.HasPrefix(x, prefix) {
152125
continue
153126
}
154-
if i >= len(actual) {
127+
if i >= actual.Len() {
155128
return false
156129
}
157-
if !f.matchParamType(x, actual[i]) {
130+
if !f.matchParamType(x, actual.At(i).Type()) {
158131
return false
159132
}
160133
}
161-
if prefix == "" && len(actual) > len(expect) {
134+
if prefix == "" && actual.Len() > len(expect) {
162135
return false
163136
}
164137
return true
165138
}
166139

167140
// Does this one type match?
168-
func (f *File) matchParamType(expect string, actual ast.Expr) bool {
141+
func (f *File) matchParamType(expect string, actual types.Type) bool {
169142
expect = strings.TrimPrefix(expect, "=")
170143
// Strip package name if we're in that package.
171144
if n := len(f.file.Name.Name); len(expect) > n && expect[:n] == f.file.Name.Name && expect[n] == '.' {
172145
expect = expect[n+1:]
173146
}
174147

175148
// Overkill but easy.
176-
f.b.Reset()
177-
printer.Fprint(&f.b, f.fset, actual)
178-
return f.b.String() == expect
149+
return actual.String() == expect
179150
}

src/cmd/vet/testdata/method.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ import (
1414

1515
type MethodTest int
1616

17-
func (t *MethodTest) Scan(x fmt.ScanState, c byte) { // ERROR "should have signature Scan"
17+
func (t *MethodTest) Scan(x fmt.ScanState, c byte) { // ERROR "should have signature Scan\(fmt\.ScanState, rune\) error"
1818
}
1919

2020
type MethodTestInterface interface {
21-
ReadByte() byte // ERROR "should have signature ReadByte"
21+
ReadByte() byte // ERROR "should have signature ReadByte\(\) \(byte, error\)"
2222
}

0 commit comments

Comments
 (0)