...

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	// Validate reports an error if any of the analyzers are misconfigured.
    10	// Checks include:
    11	// that the name is a valid identifier;
    12	// that analyzer names are unique;
    13	// that the Requires graph is acylic;
    14	// that analyzer fact types are unique;
    15	// that each fact type is a pointer.
    16	func Validate(analyzers []*Analyzer) error {
    17		names := make(map[string]bool)
    18	
    19		// Map each fact type to its sole generating analyzer.
    20		factTypes := make(map[reflect.Type]*Analyzer)
    21	
    22		// Traverse the Requires graph, depth first.
    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				// names
    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				// fact types
    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				// recursion
    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		// Reject duplicates among analyzers.
    85		// Precondition:  color[a] == black.
    86		// Postcondition: color[a] == finished.
    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