...
Source file src/pkg/cmd/vendor/golang.org/x/tools/go/analysis/validate.go
1 package analysis
2
3 import (
4 "fmt"
5 "reflect"
6 "unicode"
7 )
8
9
10
11
12
13
14
15
16 func Validate(analyzers []*Analyzer) error {
17 names := make(map[string]bool)
18
19
20 factTypes := make(map[reflect.Type]*Analyzer)
21
22
23 const (
24 white = iota
25 grey
26 black
27 finished
28 )
29 color := make(map[*Analyzer]uint8)
30 var visit func(a *Analyzer) error
31 visit = func(a *Analyzer) error {
32 if a == nil {
33 return fmt.Errorf("nil *Analyzer")
34 }
35 if color[a] == white {
36 color[a] = grey
37
38
39 if !validIdent(a.Name) {
40 return fmt.Errorf("invalid analyzer name %q", a)
41 }
42 if names[a.Name] {
43 return fmt.Errorf("duplicate analyzer name %q", a)
44 }
45 names[a.Name] = true
46
47 if a.Doc == "" {
48 return fmt.Errorf("analyzer %q is undocumented", a)
49 }
50
51
52 for _, f := range a.FactTypes {
53 if f == nil {
54 return fmt.Errorf("analyzer %s has nil FactType", a)
55 }
56 t := reflect.TypeOf(f)
57 if prev := factTypes[t]; prev != nil {
58 return fmt.Errorf("fact type %s registered by two analyzers: %v, %v",
59 t, a, prev)
60 }
61 if t.Kind() != reflect.Ptr {
62 return fmt.Errorf("%s: fact type %s is not a pointer", a, t)
63 }
64 factTypes[t] = a
65 }
66
67
68 for i, req := range a.Requires {
69 if err := visit(req); err != nil {
70 return fmt.Errorf("%s.Requires[%d]: %v", a.Name, i, err)
71 }
72 }
73 color[a] = black
74 }
75
76 return nil
77 }
78 for _, a := range analyzers {
79 if err := visit(a); err != nil {
80 return err
81 }
82 }
83
84
85
86
87 for _, a := range analyzers {
88 if color[a] == finished {
89 return fmt.Errorf("duplicate analyzer: %s", a.Name)
90 }
91 color[a] = finished
92 }
93
94 return nil
95 }
96
97 func validIdent(name string) bool {
98 for i, r := range name {
99 if !(r == '_' || unicode.IsLetter(r) || i > 0 && unicode.IsDigit(r)) {
100 return false
101 }
102 }
103 return name != ""
104 }
105
View as plain text