LEFT | RIGHT |
1 // Copyright 2014 The Go Authors. All rights reserved. | 1 // Copyright 2014 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 // This file contains the regexp-checker. | 5 // This file contains the regexp-checker. |
6 | 6 |
7 package main | 7 package main |
8 | 8 |
9 import ( | 9 import ( |
10 "go/ast" | 10 "go/ast" |
11 "go/token" | 11 "go/token" |
12 "regexp" | 12 "regexp" |
| 13 "strconv" |
13 "strings" | 14 "strings" |
14 ) | 15 ) |
15 | 16 |
| 17 func init() { |
| 18 register("regexp", |
| 19 "check regular expressions compilations", |
| 20 checkRegexpCompile, |
| 21 callExpr) |
| 22 } |
| 23 |
16 // checkRegexpCompile triggers the regexp-specific checks if the call invokes a
regexp compilation function. | 24 // checkRegexpCompile triggers the regexp-specific checks if the call invokes a
regexp compilation function. |
17 func (f *File) checkRegexpCompile(call *ast.CallExpr) { | 25 func checkRegexpCompile(f *File, n ast.Node) { |
18 » if !vet("regexp") { | 26 » call := n.(*ast.CallExpr) |
| 27 » if len(call.Args) != 1 { |
19 return | 28 return |
20 } | 29 } |
21 x, ok := call.Fun.(*ast.SelectorExpr) | 30 x, ok := call.Fun.(*ast.SelectorExpr) |
22 if !ok { | 31 if !ok { |
23 return | 32 return |
24 } | 33 } |
25 name := x.Sel.Name | 34 name := x.Sel.Name |
26 if !strings.Contains(name, "Compile") { | 35 if !strings.Contains(name, "Compile") { |
27 return | 36 return |
28 } | 37 } |
29 » if i, ok := x.X.(*ast.Ident); !ok || i.Name != "regexp" { | 38 » if pkg, ok := x.X.(*ast.Ident); !ok || pkg.Name != "regexp" { |
30 » » return | |
31 » } | |
32 » if len(call.Args) != 1 { | |
33 return | 39 return |
34 } | 40 } |
35 lit, ok := call.Args[0].(*ast.BasicLit) | 41 lit, ok := call.Args[0].(*ast.BasicLit) |
36 if !ok || lit.Kind != token.STRING { | 42 if !ok || lit.Kind != token.STRING { |
37 return | 43 return |
38 } | 44 } |
39 » re := lit.Value | 45 » re, err := strconv.Unquote(lit.Value) |
| 46 » if err != nil { |
| 47 » » f.Warn(lit.Pos(), "unable to parse string literal", err.Error()) |
| 48 » » return |
| 49 » } |
40 | 50 |
41 var err error | |
42 if strings.HasSuffix(name, "POSIX") { | 51 if strings.HasSuffix(name, "POSIX") { |
43 _, err = regexp.CompilePOSIX(re) | 52 _, err = regexp.CompilePOSIX(re) |
44 } else { | 53 } else { |
45 _, err = regexp.Compile(re) | 54 _, err = regexp.Compile(re) |
46 } | 55 } |
47 if err != nil { | 56 if err != nil { |
48 » » f.Badf(call.Pos(), err.Error()) | 57 » » f.Bad(lit.Pos(), err.Error()) |
49 } | 58 } |
50 } | 59 } |
LEFT | RIGHT |