Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(917)

Delta Between Two Patch Sets: src/cmd/govet/govet.go

Issue 4645069: code review 4645069: reflect: support for struct tag use by multiple packages (Closed)
Left Patch Set: Created 13 years, 8 months ago
Right Patch Set: diff -r dd7479dd252a https://go.googlecode.com/hg/ Created 13 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « src/cmd/godoc/codewalk.go ('k') | src/pkg/asn1/asn1.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(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 // Govet is a simple checker for static errors in Go source code. 5 // Govet 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 "flag" 10 "flag"
11 "fmt" 11 "fmt"
12 "io" 12 "io"
13 "go/ast" 13 "go/ast"
14 "go/parser" 14 "go/parser"
15 "go/token" 15 "go/token"
16 "os" 16 "os"
17 "path/filepath" 17 "path/filepath"
18 "reflect"
18 "strconv" 19 "strconv"
19 "strings" 20 "strings"
20 "utf8" 21 "utf8"
21 ) 22 )
22 23
23 var verbose = flag.Bool("v", false, "verbose") 24 var verbose = flag.Bool("v", false, "verbose")
24 var printfuncs = flag.String("printfuncs", "", "comma-separated list of print fu nction names to check") 25 var printfuncs = flag.String("printfuncs", "", "comma-separated list of print fu nction names to check")
25 var exitCode = 0 26 var exitCode = 0
26 27
27 // setExit sets the value for os.Exit when it is called, later. It 28 // setExit sets the value for os.Exit when it is called, later. It
(...skipping 24 matching lines...) Expand all
52 if *printfuncs != "" { 53 if *printfuncs != "" {
53 for _, name := range strings.Split(*printfuncs, ",") { 54 for _, name := range strings.Split(*printfuncs, ",") {
54 if len(name) == 0 { 55 if len(name) == 0 {
55 flag.Usage() 56 flag.Usage()
56 } 57 }
57 skip := 0 58 skip := 0
58 if colon := strings.LastIndex(name, ":"); colon > 0 { 59 if colon := strings.LastIndex(name, ":"); colon > 0 {
59 var err os.Error 60 var err os.Error
60 skip, err = strconv.Atoi(name[colon+1:]) 61 skip, err = strconv.Atoi(name[colon+1:])
61 if err != nil { 62 if err != nil {
62 » » » » » error(`illegal format for "Func:N" argum ent %q; %s`, name, err) 63 » » » » » errorf(`illegal format for "Func:N" argu ment %q; %s`, name, err)
63 } 64 }
64 name = name[:colon] 65 name = name[:colon]
65 } 66 }
66 name = strings.ToLower(name) 67 name = strings.ToLower(name)
67 if name[len(name)-1] == 'f' { 68 if name[len(name)-1] == 'f' {
68 printfList[name] = skip 69 printfList[name] = skip
69 } else { 70 } else {
70 printList[name] = skip 71 printList[name] = skip
71 } 72 }
72 } 73 }
(...skipping 13 matching lines...) Expand all
86 } 87 }
87 os.Exit(exitCode) 88 os.Exit(exitCode)
88 } 89 }
89 90
90 // doFile analyzes one file. If the reader is nil, the source code is read from the 91 // doFile analyzes one file. If the reader is nil, the source code is read from the
91 // named file. 92 // named file.
92 func doFile(name string, reader io.Reader) { 93 func doFile(name string, reader io.Reader) {
93 fs := token.NewFileSet() 94 fs := token.NewFileSet()
94 parsedFile, err := parser.ParseFile(fs, name, reader, 0) 95 parsedFile, err := parser.ParseFile(fs, name, reader, 0)
95 if err != nil { 96 if err != nil {
96 » » error("%s: %s", name, err) 97 » » errorf("%s: %s", name, err)
97 return 98 return
98 } 99 }
99 file := &File{fs.File(parsedFile.Pos())} 100 file := &File{fs.File(parsedFile.Pos())}
100 file.checkFile(name, parsedFile) 101 file.checkFile(name, parsedFile)
101 } 102 }
102 103
103 // Visitor for filepath.Walk - trivial. Just calls doFile on each file. 104 // Visitor for filepath.Walk - trivial. Just calls doFile on each file.
104 // TODO: if govet becomes richer, might want to process 105 // TODO: if govet becomes richer, might want to process
105 // a directory (package) at a time. 106 // a directory (package) at a time.
106 type V struct{} 107 type V struct{}
107 108
108 func (v V) VisitDir(path string, f *os.FileInfo) bool { 109 func (v V) VisitDir(path string, f *os.FileInfo) bool {
109 return true 110 return true
110 } 111 }
111 112
112 func (v V) VisitFile(path string, f *os.FileInfo) { 113 func (v V) VisitFile(path string, f *os.FileInfo) {
113 if strings.HasSuffix(path, ".go") { 114 if strings.HasSuffix(path, ".go") {
114 doFile(path, nil) 115 doFile(path, nil)
115 } 116 }
116 } 117 }
117 118
118 // walkDir recursively walks the tree looking for .go files. 119 // walkDir recursively walks the tree looking for .go files.
119 func walkDir(root string) { 120 func walkDir(root string) {
120 errors := make(chan os.Error) 121 errors := make(chan os.Error)
121 done := make(chan bool) 122 done := make(chan bool)
122 go func() { 123 go func() {
123 for e := range errors { 124 for e := range errors {
124 » » » error("walk error: %s", e) 125 » » » errorf("walk error: %s", e)
125 } 126 }
126 done <- true 127 done <- true
127 }() 128 }()
128 filepath.Walk(root, V{}, errors) 129 filepath.Walk(root, V{}, errors)
129 close(errors) 130 close(errors)
130 <-done 131 <-done
131 } 132 }
132 133
133 // error formats the error to standard error, adding program 134 // error formats the error to standard error, adding program
134 // identification and a newline 135 // identification and a newline
135 func error(format string, args ...interface{}) { 136 func errorf(format string, args ...interface{}) {
136 fmt.Fprintf(os.Stderr, "govet: "+format+"\n", args...) 137 fmt.Fprintf(os.Stderr, "govet: "+format+"\n", args...)
137 setExit(2) 138 setExit(2)
138 } 139 }
139 140
140 // Println is fmt.Println guarded by -v. 141 // Println is fmt.Println guarded by -v.
141 func Println(args ...interface{}) { 142 func Println(args ...interface{}) {
142 if !*verbose { 143 if !*verbose {
143 return 144 return
144 } 145 }
145 fmt.Println(args...) 146 fmt.Println(args...)
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 } 179 }
179 180
180 // checkFile checks all the top-level declarations in a file. 181 // checkFile checks all the top-level declarations in a file.
181 func (f *File) checkFile(name string, file *ast.File) { 182 func (f *File) checkFile(name string, file *ast.File) {
182 Println("Checking file", name) 183 Println("Checking file", name)
183 ast.Walk(f, file) 184 ast.Walk(f, file)
184 } 185 }
185 186
186 // Visit implements the ast.Visitor interface. 187 // Visit implements the ast.Visitor interface.
187 func (f *File) Visit(node ast.Node) ast.Visitor { 188 func (f *File) Visit(node ast.Node) ast.Visitor {
188 // TODO: could return nil for nodes that cannot contain a CallExpr -
189 // will shortcut traversal. Worthwhile?
190 switch n := node.(type) { 189 switch n := node.(type) {
191 case *ast.CallExpr: 190 case *ast.CallExpr:
192 f.checkCallExpr(n) 191 f.checkCallExpr(n)
192 case *ast.Field:
193 f.checkFieldTag(n)
193 } 194 }
194 return f 195 return f
195 } 196 }
196 197
198 // checkField checks a struct field tag.
199 func (f *File) checkFieldTag(field *ast.Field) {
200 if field.Tag == nil {
201 return
202 }
203
204 tag, err := strconv.Unquote(field.Tag.Value)
205 if err != nil {
206 f.Warnf(field.Pos(), "unable to read struct tag %s", field.Tag.V alue)
207 return
208 }
209
210 // Check tag for validity by appending
211 // new key:value to end and checking that
212 // the tag parsing code can find it.
213 if reflect.StructTag(tag+` _gofix:"_magic"`).Get("_gofix") != "_magic" {
214 f.Warnf(field.Pos(), "struct field tag %s not compatible with re flect.StructTag.Get", field.Tag.Value)
215 return
216 }
217 }
197 218
198 // checkCallExpr checks a call expression. 219 // checkCallExpr checks a call expression.
199 func (f *File) checkCallExpr(call *ast.CallExpr) { 220 func (f *File) checkCallExpr(call *ast.CallExpr) {
200 switch x := call.Fun.(type) { 221 switch x := call.Fun.(type) {
201 case *ast.Ident: 222 case *ast.Ident:
202 f.checkCall(call, x.Name) 223 f.checkCall(call, x.Name)
203 case *ast.SelectorExpr: 224 case *ast.SelectorExpr:
204 f.checkCall(call, x.Sel.Name) 225 f.checkCall(call, x.Sel.Name)
205 } 226 }
206 } 227 }
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 fmt.Printf("%s%%%d", "hi", 3) // right # percents 387 fmt.Printf("%s%%%d", "hi", 3) // right # percents
367 fmt.Printf("%.*d", 3, 3) // right # percents, with a * 388 fmt.Printf("%.*d", 3, 3) // right # percents, with a *
368 fmt.Printf("%.*d", 3, 3, 3) // wrong # percents, with a * 389 fmt.Printf("%.*d", 3, 3, 3) // wrong # percents, with a *
369 printf("now is the time", "buddy") // no %s 390 printf("now is the time", "buddy") // no %s
370 Printf("now is the time", "buddy") // no %s 391 Printf("now is the time", "buddy") // no %s
371 f := new(File) 392 f := new(File)
372 f.Warn(0, "%s", "hello", 3) // % in call to added function 393 f.Warn(0, "%s", "hello", 3) // % in call to added function
373 f.Warnf(0, "%s", "hello", 3) // wrong # %s in call to added function 394 f.Warnf(0, "%s", "hello", 3) // wrong # %s in call to added function
374 } 395 }
375 396
397 type BadTypeUsedInTests struct {
398 X int "hello" // struct field not well-formed
399 }
400
376 // printf is used by the test. 401 // printf is used by the test.
377 func printf(format string, args ...interface{}) { 402 func printf(format string, args ...interface{}) {
378 panic("don't call - testing only") 403 panic("don't call - testing only")
379 } 404 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b