OLD | NEW |
1 // Copyright 2010 The Go Authors. All rights reserved. | 1 // Copyright 2010 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Vet is a simple checker for static errors in Go source code. | 5 // Vet is a simple checker for static errors in Go source code. |
6 // See doc.go for more information. | 6 // See doc.go for more information. |
7 package main | 7 package main |
8 | 8 |
9 import ( | 9 import ( |
10 "bytes" | 10 "bytes" |
11 "flag" | 11 "flag" |
12 "fmt" | 12 "fmt" |
13 "go/ast" | 13 "go/ast" |
14 "go/parser" | 14 "go/parser" |
| 15 "go/printer" |
15 "go/token" | 16 "go/token" |
16 "io" | 17 "io" |
17 "os" | 18 "os" |
18 "path/filepath" | 19 "path/filepath" |
19 "strconv" | 20 "strconv" |
20 "strings" | 21 "strings" |
21 ) | 22 ) |
22 | 23 |
23 var verbose = flag.Bool("v", false, "verbose") | 24 var verbose = flag.Bool("v", false, "verbose") |
24 var exitCode = 0 | 25 var exitCode = 0 |
25 | 26 |
26 // Flags to control which checks to perform | 27 // Flags to control which checks to perform |
27 var ( | 28 var ( |
28 vetAll = flag.Bool("all", true, "check everything; disabled
if any explicit check is requested") | 29 vetAll = flag.Bool("all", true, "check everything; disabled
if any explicit check is requested") |
29 vetMethods = flag.Bool("methods", false, "check that canonically
named methods are canonically defined") | 30 vetMethods = flag.Bool("methods", false, "check that canonically
named methods are canonically defined") |
30 vetPrintf = flag.Bool("printf", false, "check printf-like invoc
ations") | 31 vetPrintf = flag.Bool("printf", false, "check printf-like invoc
ations") |
31 vetStructTags = flag.Bool("structtags", false, "check that struct f
ield tags have canonical format") | 32 vetStructTags = flag.Bool("structtags", false, "check that struct f
ield tags have canonical format") |
32 vetUntaggedLiteral = flag.Bool("composites", false, "check that composit
e literals used type-tagged elements") | 33 vetUntaggedLiteral = flag.Bool("composites", false, "check that composit
e literals used type-tagged elements") |
33 vetRangeLoops = flag.Bool("rangeloops", false, "check that range lo
op variables are used correctly") | 34 vetRangeLoops = flag.Bool("rangeloops", false, "check that range lo
op variables are used correctly") |
| 35 vetAtomic = flag.Bool("atomic", false, "check for common mistak
en usages of the sync/atomic package") |
34 ) | 36 ) |
35 | 37 |
36 // setExit sets the value for os.Exit when it is called, later. It | 38 // setExit sets the value for os.Exit when it is called, later. It |
37 // remembers the highest value. | 39 // remembers the highest value. |
38 func setExit(err int) { | 40 func setExit(err int) { |
39 if err > exitCode { | 41 if err > exitCode { |
40 exitCode = err | 42 exitCode = err |
41 } | 43 } |
42 } | 44 } |
43 | 45 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 | 183 |
182 // walkFile walks the file's tree. | 184 // walkFile walks the file's tree. |
183 func (f *File) walkFile(name string, file *ast.File) { | 185 func (f *File) walkFile(name string, file *ast.File) { |
184 Println("Checking file", name) | 186 Println("Checking file", name) |
185 ast.Walk(f, file) | 187 ast.Walk(f, file) |
186 } | 188 } |
187 | 189 |
188 // Visit implements the ast.Visitor interface. | 190 // Visit implements the ast.Visitor interface. |
189 func (f *File) Visit(node ast.Node) ast.Visitor { | 191 func (f *File) Visit(node ast.Node) ast.Visitor { |
190 switch n := node.(type) { | 192 switch n := node.(type) { |
| 193 case *ast.AssignStmt: |
| 194 f.walkAssignStmt(n) |
191 case *ast.CallExpr: | 195 case *ast.CallExpr: |
192 f.walkCallExpr(n) | 196 f.walkCallExpr(n) |
193 case *ast.CompositeLit: | 197 case *ast.CompositeLit: |
194 f.walkCompositeLit(n) | 198 f.walkCompositeLit(n) |
195 case *ast.Field: | 199 case *ast.Field: |
196 f.walkFieldTag(n) | 200 f.walkFieldTag(n) |
197 case *ast.FuncDecl: | 201 case *ast.FuncDecl: |
198 f.walkMethodDecl(n) | 202 f.walkMethodDecl(n) |
199 case *ast.InterfaceType: | 203 case *ast.InterfaceType: |
200 f.walkInterfaceType(n) | 204 f.walkInterfaceType(n) |
201 case *ast.RangeStmt: | 205 case *ast.RangeStmt: |
202 f.walkRangeStmt(n) | 206 f.walkRangeStmt(n) |
203 } | 207 } |
204 return f | 208 return f |
205 } | 209 } |
206 | 210 |
| 211 // walkCall walks an assignment statement |
| 212 func (f *File) walkAssignStmt(stmt *ast.AssignStmt) { |
| 213 f.checkAtomicAssignment(stmt) |
| 214 } |
| 215 |
207 // walkCall walks a call expression. | 216 // walkCall walks a call expression. |
208 func (f *File) walkCall(call *ast.CallExpr, name string) { | 217 func (f *File) walkCall(call *ast.CallExpr, name string) { |
209 f.checkFmtPrintfCall(call, name) | 218 f.checkFmtPrintfCall(call, name) |
210 } | 219 } |
211 | 220 |
212 // walkCallExpr walks a call expression. | 221 // walkCallExpr walks a call expression. |
213 func (f *File) walkCallExpr(call *ast.CallExpr) { | 222 func (f *File) walkCallExpr(call *ast.CallExpr) { |
214 switch x := call.Fun.(type) { | 223 switch x := call.Fun.(type) { |
215 case *ast.Ident: | 224 case *ast.Ident: |
216 f.walkCall(call, x.Name) | 225 f.walkCall(call, x.Name) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 for _, id := range field.Names { | 261 for _, id := range field.Names { |
253 f.walkMethod(id, field.Type.(*ast.FuncType)) | 262 f.walkMethod(id, field.Type.(*ast.FuncType)) |
254 } | 263 } |
255 } | 264 } |
256 } | 265 } |
257 | 266 |
258 // walkRangeStmt walks a range statement. | 267 // walkRangeStmt walks a range statement. |
259 func (f *File) walkRangeStmt(n *ast.RangeStmt) { | 268 func (f *File) walkRangeStmt(n *ast.RangeStmt) { |
260 checkRangeLoop(f, n) | 269 checkRangeLoop(f, n) |
261 } | 270 } |
| 271 |
| 272 // goFmt returns a string representation of the expression |
| 273 func (f *File) goFmt(x ast.Expr) string { |
| 274 f.b.Reset() |
| 275 printer.Fprint(&f.b, f.fset, x) |
| 276 return f.b.String() |
| 277 } |
OLD | NEW |