LEFT | RIGHT |
(no file at all) | |
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" |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 field *ast.Field | 131 field *ast.Field |
132 funcDecl *ast.FuncDecl | 132 funcDecl *ast.FuncDecl |
133 funcLit *ast.FuncLit | 133 funcLit *ast.FuncLit |
134 genDecl *ast.GenDecl | 134 genDecl *ast.GenDecl |
135 interfaceType *ast.InterfaceType | 135 interfaceType *ast.InterfaceType |
136 rangeStmt *ast.RangeStmt | 136 rangeStmt *ast.RangeStmt |
137 | 137 |
138 // checkers is a two-level map. | 138 // checkers is a two-level map. |
139 // The outer level is keyed by a nil pointer, one of the AST vars above. | 139 // The outer level is keyed by a nil pointer, one of the AST vars above. |
140 // The inner level is keyed by checker name. | 140 // The inner level is keyed by checker name. |
141 » checkers = make(map[ast.Node]map[string]func(*File, ast.Node)) | 141 » checkers = make(map[ast.Node]map[string]checker) |
142 ) | 142 ) |
143 | 143 |
144 func register(name, usage string, fn func(*File, ast.Node), types ...ast.Node) { | 144 type checker struct { |
| 145 » fn func(*File, ast.Node) |
| 146 » filefilter func(*File) bool |
| 147 } |
| 148 |
| 149 func register(name, usage string, filefilter func(*File) bool, fn func(*File, as
t.Node), types ...ast.Node) { |
145 report[name] = triStateFlag(name, unset, usage) | 150 report[name] = triStateFlag(name, unset, usage) |
146 for _, typ := range types { | 151 for _, typ := range types { |
147 m := checkers[typ] | 152 m := checkers[typ] |
148 if m == nil { | 153 if m == nil { |
149 » » » m = make(map[string]func(*File, ast.Node)) | 154 » » » m = make(map[string]checker) |
150 checkers[typ] = m | 155 checkers[typ] = m |
151 } | 156 } |
152 » » m[name] = fn | 157 » » m[name] = checker{fn: fn, filefilter: filefilter} |
153 } | 158 } |
154 } | 159 } |
155 | 160 |
156 // Usage is a replacement usage function for the flags package. | 161 // Usage is a replacement usage function for the flags package. |
157 func Usage() { | 162 func Usage() { |
158 fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) | 163 fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) |
159 fmt.Fprintf(os.Stderr, "\tvet [flags] directory...\n") | 164 fmt.Fprintf(os.Stderr, "\tvet [flags] directory...\n") |
160 fmt.Fprintf(os.Stderr, "\tvet [flags] files... # Must be a single packag
e\n") | 165 fmt.Fprintf(os.Stderr, "\tvet [flags] files... # Must be a single packag
e\n") |
161 fmt.Fprintf(os.Stderr, "For more information run\n") | 166 fmt.Fprintf(os.Stderr, "For more information run\n") |
162 fmt.Fprintf(os.Stderr, "\tgodoc code.google.com/p/go.tools/cmd/vet\n\n") | 167 fmt.Fprintf(os.Stderr, "\tgodoc code.google.com/p/go.tools/cmd/vet\n\n") |
(...skipping 10 matching lines...) Expand all Loading... |
173 name string | 178 name string |
174 content []byte | 179 content []byte |
175 file *ast.File | 180 file *ast.File |
176 b bytes.Buffer // for use by methods | 181 b bytes.Buffer // for use by methods |
177 | 182 |
178 // The objects that are receivers of a "String() string" method. | 183 // The objects that are receivers of a "String() string" method. |
179 // This is used by the recursiveStringer method in print.go. | 184 // This is used by the recursiveStringer method in print.go. |
180 stringers map[*ast.Object]bool | 185 stringers map[*ast.Object]bool |
181 | 186 |
182 // Registered checkers to run. | 187 // Registered checkers to run. |
183 » checkers map[ast.Node][]func(*File, ast.Node) | 188 » checkers map[ast.Node][]checker |
184 } | 189 } |
185 | 190 |
186 func main() { | 191 func main() { |
187 flag.Usage = Usage | 192 flag.Usage = Usage |
188 flag.Parse() | 193 flag.Parse() |
189 | 194 |
190 // If any flag is set, we run only those checks requested. | 195 // If any flag is set, we run only those checks requested. |
191 // If no flags are set true, set all the non-experimental ones not expli
citly set (in effect, set the "-all" flag). | 196 // If no flags are set true, set all the non-experimental ones not expli
citly set (in effect, set the "-all" flag). |
192 if setTrueCount == 0 { | 197 if setTrueCount == 0 { |
193 for name, setting := range report { | 198 for name, setting := range report { |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 pkg := new(Package) | 342 pkg := new(Package) |
338 pkg.path = astFiles[0].Name.Name | 343 pkg.path = astFiles[0].Name.Name |
339 pkg.files = files | 344 pkg.files = files |
340 // Type check the package. | 345 // Type check the package. |
341 err := pkg.check(fs, astFiles) | 346 err := pkg.check(fs, astFiles) |
342 if err != nil && *verbose { | 347 if err != nil && *verbose { |
343 warnf("%s", err) | 348 warnf("%s", err) |
344 } | 349 } |
345 | 350 |
346 // Check. | 351 // Check. |
347 » chk := make(map[ast.Node][]func(*File, ast.Node)) | 352 » for _, file := range files { |
348 » for typ, set := range checkers { | 353 » » chk := make(map[ast.Node][]checker) |
349 » » for name, fn := range set { | 354 » » for typ, set := range checkers { |
350 » » » if vet(name) { | 355 » » » for name, checker := range set { |
351 » » » » chk[typ] = append(chk[typ], fn) | 356 » » » » if vet(name) && checker.filefilter(file) { |
| 357 » » » » » chk[typ] = append(chk[typ], checker) |
| 358 » » » » } |
352 } | 359 } |
353 } | 360 } |
354 } | |
355 for _, file := range files { | |
356 file.pkg = pkg | 361 file.pkg = pkg |
357 file.checkers = chk | 362 file.checkers = chk |
358 if file.file != nil { | 363 if file.file != nil { |
359 file.walkFile(file.name, file.file) | 364 file.walkFile(file.name, file.file) |
360 } | 365 } |
361 } | 366 } |
362 asmCheck(pkg) | 367 asmCheck(pkg) |
363 return true | 368 return true |
364 } | 369 } |
365 | 370 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 key = funcDecl | 483 key = funcDecl |
479 case *ast.FuncLit: | 484 case *ast.FuncLit: |
480 key = funcLit | 485 key = funcLit |
481 case *ast.GenDecl: | 486 case *ast.GenDecl: |
482 key = genDecl | 487 key = genDecl |
483 case *ast.InterfaceType: | 488 case *ast.InterfaceType: |
484 key = interfaceType | 489 key = interfaceType |
485 case *ast.RangeStmt: | 490 case *ast.RangeStmt: |
486 key = rangeStmt | 491 key = rangeStmt |
487 } | 492 } |
488 » for _, fn := range f.checkers[key] { | 493 » for _, checker := range f.checkers[key] { |
489 » » fn(f, node) | 494 » » checker.fn(f, node) |
490 } | 495 } |
491 return f | 496 return f |
492 } | 497 } |
493 | 498 |
494 // gofmt returns a string representation of the expression. | 499 // gofmt returns a string representation of the expression. |
495 func (f *File) gofmt(x ast.Expr) string { | 500 func (f *File) gofmt(x ast.Expr) string { |
496 f.b.Reset() | 501 f.b.Reset() |
497 printer.Fprint(&f.b, f.fset, x) | 502 printer.Fprint(&f.b, f.fset, x) |
498 return f.b.String() | 503 return f.b.String() |
499 } | 504 } |
| 505 |
| 506 func (f *File) imports(path string) bool { |
| 507 if f.file == nil { |
| 508 return false |
| 509 } |
| 510 for _, imp := range f.file.Imports { |
| 511 if imp.Path.Value == path { |
| 512 return true |
| 513 } |
| 514 } |
| 515 return false |
| 516 } |
LEFT | RIGHT |