1package analysis 2 3import ( 4 "flag" 5 "fmt" 6 "go/ast" 7 "go/token" 8 "go/types" 9 "reflect" 10 11 "golang.org/x/tools/internal/analysisinternal" 12) 13 14// An Analyzer describes an analysis function and its options. 15type Analyzer struct { 16 // The Name of the analyzer must be a valid Go identifier 17 // as it may appear in command-line flags, URLs, and so on. 18 Name string 19 20 // Doc is the documentation for the analyzer. 21 // The part before the first "\n\n" is the title 22 // (no capital or period, max ~60 letters). 23 Doc string 24 25 // Flags defines any flags accepted by the analyzer. 26 // The manner in which these flags are exposed to the user 27 // depends on the driver which runs the analyzer. 28 Flags flag.FlagSet 29 30 // Run applies the analyzer to a package. 31 // It returns an error if the analyzer failed. 32 // 33 // On success, the Run function may return a result 34 // computed by the Analyzer; its type must match ResultType. 35 // The driver makes this result available as an input to 36 // another Analyzer that depends directly on this one (see 37 // Requires) when it analyzes the same package. 38 // 39 // To pass analysis results between packages (and thus 40 // potentially between address spaces), use Facts, which are 41 // serializable. 42 Run func(*Pass) (interface{}, error) 43 44 // RunDespiteErrors allows the driver to invoke 45 // the Run method of this analyzer even on a 46 // package that contains parse or type errors. 47 RunDespiteErrors bool 48 49 // Requires is a set of analyzers that must run successfully 50 // before this one on a given package. This analyzer may inspect 51 // the outputs produced by each analyzer in Requires. 52 // The graph over analyzers implied by Requires edges must be acyclic. 53 // 54 // Requires establishes a "horizontal" dependency between 55 // analysis passes (different analyzers, same package). 56 Requires []*Analyzer 57 58 // ResultType is the type of the optional result of the Run function. 59 ResultType reflect.Type 60 61 // FactTypes indicates that this analyzer imports and exports 62 // Facts of the specified concrete types. 63 // An analyzer that uses facts may assume that its import 64 // dependencies have been similarly analyzed before it runs. 65 // Facts must be pointers. 66 // 67 // FactTypes establishes a "vertical" dependency between 68 // analysis passes (same analyzer, different packages). 69 FactTypes []Fact 70} 71 72func (a *Analyzer) String() string { return a.Name } 73 74func init() { 75 // Set the analysisinternal functions to be able to pass type errors 76 // to the Pass type without modifying the go/analysis API. 77 analysisinternal.SetTypeErrors = func(p interface{}, errors []types.Error) { 78 p.(*Pass).typeErrors = errors 79 } 80 analysisinternal.GetTypeErrors = func(p interface{}) []types.Error { 81 return p.(*Pass).typeErrors 82 } 83} 84 85// A Pass provides information to the Run function that 86// applies a specific analyzer to a single Go package. 87// 88// It forms the interface between the analysis logic and the driver 89// program, and has both input and an output components. 90// 91// As in a compiler, one pass may depend on the result computed by another. 92// 93// The Run function should not call any of the Pass functions concurrently. 94type Pass struct { 95 Analyzer *Analyzer // the identity of the current analyzer 96 97 // syntax and type information 98 Fset *token.FileSet // file position information 99 Files []*ast.File // the abstract syntax tree of each file 100 OtherFiles []string // names of non-Go files of this package 101 IgnoredFiles []string // names of ignored source files in this package 102 Pkg *types.Package // type information about the package 103 TypesInfo *types.Info // type information about the syntax trees 104 TypesSizes types.Sizes // function for computing sizes of types 105 106 // Report reports a Diagnostic, a finding about a specific location 107 // in the analyzed source code such as a potential mistake. 108 // It may be called by the Run function. 109 Report func(Diagnostic) 110 111 // ResultOf provides the inputs to this analysis pass, which are 112 // the corresponding results of its prerequisite analyzers. 113 // The map keys are the elements of Analysis.Required, 114 // and the type of each corresponding value is the required 115 // analysis's ResultType. 116 ResultOf map[*Analyzer]interface{} 117 118 // -- facts -- 119 120 // ImportObjectFact retrieves a fact associated with obj. 121 // Given a value ptr of type *T, where *T satisfies Fact, 122 // ImportObjectFact copies the value to *ptr. 123 // 124 // ImportObjectFact panics if called after the pass is complete. 125 // ImportObjectFact is not concurrency-safe. 126 ImportObjectFact func(obj types.Object, fact Fact) bool 127 128 // ImportPackageFact retrieves a fact associated with package pkg, 129 // which must be this package or one of its dependencies. 130 // See comments for ImportObjectFact. 131 ImportPackageFact func(pkg *types.Package, fact Fact) bool 132 133 // ExportObjectFact associates a fact of type *T with the obj, 134 // replacing any previous fact of that type. 135 // 136 // ExportObjectFact panics if it is called after the pass is 137 // complete, or if obj does not belong to the package being analyzed. 138 // ExportObjectFact is not concurrency-safe. 139 ExportObjectFact func(obj types.Object, fact Fact) 140 141 // ExportPackageFact associates a fact with the current package. 142 // See comments for ExportObjectFact. 143 ExportPackageFact func(fact Fact) 144 145 // AllPackageFacts returns a new slice containing all package facts of the analysis's FactTypes 146 // in unspecified order. 147 // WARNING: This is an experimental API and may change in the future. 148 AllPackageFacts func() []PackageFact 149 150 // AllObjectFacts returns a new slice containing all object facts of the analysis's FactTypes 151 // in unspecified order. 152 // WARNING: This is an experimental API and may change in the future. 153 AllObjectFacts func() []ObjectFact 154 155 // typeErrors contains types.Errors that are associated with the pkg. 156 typeErrors []types.Error 157 158 /* Further fields may be added in future. */ 159 // For example, suggested or applied refactorings. 160} 161 162// PackageFact is a package together with an associated fact. 163// WARNING: This is an experimental API and may change in the future. 164type PackageFact struct { 165 Package *types.Package 166 Fact Fact 167} 168 169// ObjectFact is an object together with an associated fact. 170// WARNING: This is an experimental API and may change in the future. 171type ObjectFact struct { 172 Object types.Object 173 Fact Fact 174} 175 176// Reportf is a helper function that reports a Diagnostic using the 177// specified position and formatted error message. 178func (pass *Pass) Reportf(pos token.Pos, format string, args ...interface{}) { 179 msg := fmt.Sprintf(format, args...) 180 pass.Report(Diagnostic{Pos: pos, Message: msg}) 181} 182 183// The Range interface provides a range. It's equivalent to and satisfied by 184// ast.Node. 185type Range interface { 186 Pos() token.Pos // position of first character belonging to the node 187 End() token.Pos // position of first character immediately after the node 188} 189 190// ReportRangef is a helper function that reports a Diagnostic using the 191// range provided. ast.Node values can be passed in as the range because 192// they satisfy the Range interface. 193func (pass *Pass) ReportRangef(rng Range, format string, args ...interface{}) { 194 msg := fmt.Sprintf(format, args...) 195 pass.Report(Diagnostic{Pos: rng.Pos(), End: rng.End(), Message: msg}) 196} 197 198func (pass *Pass) String() string { 199 return fmt.Sprintf("%s@%s", pass.Analyzer.Name, pass.Pkg.Path()) 200} 201 202// A Fact is an intermediate fact produced during analysis. 203// 204// Each fact is associated with a named declaration (a types.Object) or 205// with a package as a whole. A single object or package may have 206// multiple associated facts, but only one of any particular fact type. 207// 208// A Fact represents a predicate such as "never returns", but does not 209// represent the subject of the predicate such as "function F" or "package P". 210// 211// Facts may be produced in one analysis pass and consumed by another 212// analysis pass even if these are in different address spaces. 213// If package P imports Q, all facts about Q produced during 214// analysis of that package will be available during later analysis of P. 215// Facts are analogous to type export data in a build system: 216// just as export data enables separate compilation of several passes, 217// facts enable "separate analysis". 218// 219// Each pass (a, p) starts with the set of facts produced by the 220// same analyzer a applied to the packages directly imported by p. 221// The analysis may add facts to the set, and they may be exported in turn. 222// An analysis's Run function may retrieve facts by calling 223// Pass.Import{Object,Package}Fact and update them using 224// Pass.Export{Object,Package}Fact. 225// 226// A fact is logically private to its Analysis. To pass values 227// between different analyzers, use the results mechanism; 228// see Analyzer.Requires, Analyzer.ResultType, and Pass.ResultOf. 229// 230// A Fact type must be a pointer. 231// Facts are encoded and decoded using encoding/gob. 232// A Fact may implement the GobEncoder/GobDecoder interfaces 233// to customize its encoding. Fact encoding should not fail. 234// 235// A Fact should not be modified once exported. 236type Fact interface { 237 AFact() // dummy method to avoid type errors 238} 239