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