Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / go / analysis / doc.go
1 /*
2
3 Package analysis defines the interface between a modular static
4 analysis and an analysis driver program.
5
6
7 Background
8
9 A static analysis is a function that inspects a package of Go code and
10 reports a set of diagnostics (typically mistakes in the code), and
11 perhaps produces other results as well, such as suggested refactorings
12 or other facts. An analysis that reports mistakes is informally called a
13 "checker". For example, the printf checker reports mistakes in
14 fmt.Printf format strings.
15
16 A "modular" analysis is one that inspects one package at a time but can
17 save information from a lower-level package and use it when inspecting a
18 higher-level package, analogous to separate compilation in a toolchain.
19 The printf checker is modular: when it discovers that a function such as
20 log.Fatalf delegates to fmt.Printf, it records this fact, and checks
21 calls to that function too, including calls made from another package.
22
23 By implementing a common interface, checkers from a variety of sources
24 can be easily selected, incorporated, and reused in a wide range of
25 driver programs including command-line tools (such as vet), text editors and
26 IDEs, build and test systems (such as go build, Bazel, or Buck), test
27 frameworks, code review tools, code-base indexers (such as SourceGraph),
28 documentation viewers (such as godoc), batch pipelines for large code
29 bases, and so on.
30
31
32 Analyzer
33
34 The primary type in the API is Analyzer. An Analyzer statically
35 describes an analysis function: its name, documentation, flags,
36 relationship to other analyzers, and of course, its logic.
37
38 To define an analysis, a user declares a (logically constant) variable
39 of type Analyzer. Here is a typical example from one of the analyzers in
40 the go/analysis/passes/ subdirectory:
41
42         package unusedresult
43
44         var Analyzer = &analysis.Analyzer{
45                 Name: "unusedresult",
46                 Doc:  "check for unused results of calls to some functions",
47                 Run:  run,
48                 ...
49         }
50
51         func run(pass *analysis.Pass) (interface{}, error) {
52                 ...
53         }
54
55 An analysis driver is a program such as vet that runs a set of
56 analyses and prints the diagnostics that they report.
57 The driver program must import the list of Analyzers it needs.
58 Typically each Analyzer resides in a separate package.
59 To add a new Analyzer to an existing driver, add another item to the list:
60
61         import ( "unusedresult"; "nilness"; "printf" )
62
63         var analyses = []*analysis.Analyzer{
64                 unusedresult.Analyzer,
65                 nilness.Analyzer,
66                 printf.Analyzer,
67         }
68
69 A driver may use the name, flags, and documentation to provide on-line
70 help that describes the analyses it performs.
71 The doc comment contains a brief one-line summary,
72 optionally followed by paragraphs of explanation.
73
74 The Analyzer type has more fields besides those shown above:
75
76         type Analyzer struct {
77                 Name             string
78                 Doc              string
79                 Flags            flag.FlagSet
80                 Run              func(*Pass) (interface{}, error)
81                 RunDespiteErrors bool
82                 ResultType       reflect.Type
83                 Requires         []*Analyzer
84                 FactTypes        []Fact
85         }
86
87 The Flags field declares a set of named (global) flag variables that
88 control analysis behavior. Unlike vet, analysis flags are not declared
89 directly in the command line FlagSet; it is up to the driver to set the
90 flag variables. A driver for a single analysis, a, might expose its flag
91 f directly on the command line as -f, whereas a driver for multiple
92 analyses might prefix the flag name by the analysis name (-a.f) to avoid
93 ambiguity. An IDE might expose the flags through a graphical interface,
94 and a batch pipeline might configure them from a config file.
95 See the "findcall" analyzer for an example of flags in action.
96
97 The RunDespiteErrors flag indicates whether the analysis is equipped to
98 handle ill-typed code. If not, the driver will skip the analysis if
99 there were parse or type errors.
100 The optional ResultType field specifies the type of the result value
101 computed by this analysis and made available to other analyses.
102 The Requires field specifies a list of analyses upon which
103 this one depends and whose results it may access, and it constrains the
104 order in which a driver may run analyses.
105 The FactTypes field is discussed in the section on Modularity.
106 The analysis package provides a Validate function to perform basic
107 sanity checks on an Analyzer, such as that its Requires graph is
108 acyclic, its fact and result types are unique, and so on.
109
110 Finally, the Run field contains a function to be called by the driver to
111 execute the analysis on a single package. The driver passes it an
112 instance of the Pass type.
113
114
115 Pass
116
117 A Pass describes a single unit of work: the application of a particular
118 Analyzer to a particular package of Go code.
119 The Pass provides information to the Analyzer's Run function about the
120 package being analyzed, and provides operations to the Run function for
121 reporting diagnostics and other information back to the driver.
122
123         type Pass struct {
124                 Fset         *token.FileSet
125                 Files        []*ast.File
126                 OtherFiles   []string
127                 IgnoredFiles []string
128                 Pkg          *types.Package
129                 TypesInfo    *types.Info
130                 ResultOf     map[*Analyzer]interface{}
131                 Report       func(Diagnostic)
132                 ...
133         }
134
135 The Fset, Files, Pkg, and TypesInfo fields provide the syntax trees,
136 type information, and source positions for a single package of Go code.
137
138 The OtherFiles field provides the names, but not the contents, of non-Go
139 files such as assembly that are part of this package. See the "asmdecl"
140 or "buildtags" analyzers for examples of loading non-Go files and reporting
141 diagnostics against them.
142
143 The IgnoredFiles field provides the names, but not the contents,
144 of ignored Go and non-Go source files that are not part of this package
145 with the current build configuration but may be part of other build
146 configurations. See the "buildtags" analyzer for an example of loading
147 and checking IgnoredFiles.
148
149 The ResultOf field provides the results computed by the analyzers
150 required by this one, as expressed in its Analyzer.Requires field. The
151 driver runs the required analyzers first and makes their results
152 available in this map. Each Analyzer must return a value of the type
153 described in its Analyzer.ResultType field.
154 For example, the "ctrlflow" analyzer returns a *ctrlflow.CFGs, which
155 provides a control-flow graph for each function in the package (see
156 golang.org/x/tools/go/cfg); the "inspect" analyzer returns a value that
157 enables other Analyzers to traverse the syntax trees of the package more
158 efficiently; and the "buildssa" analyzer constructs an SSA-form
159 intermediate representation.
160 Each of these Analyzers extends the capabilities of later Analyzers
161 without adding a dependency to the core API, so an analysis tool pays
162 only for the extensions it needs.
163
164 The Report function emits a diagnostic, a message associated with a
165 source position. For most analyses, diagnostics are their primary
166 result.
167 For convenience, Pass provides a helper method, Reportf, to report a new
168 diagnostic by formatting a string.
169 Diagnostic is defined as:
170
171         type Diagnostic struct {
172                 Pos      token.Pos
173                 Category string // optional
174                 Message  string
175         }
176
177 The optional Category field is a short identifier that classifies the
178 kind of message when an analysis produces several kinds of diagnostic.
179
180 Many analyses want to associate diagnostics with a severity level.
181 Because Diagnostic does not have a severity level field, an Analyzer's
182 diagnostics effectively all have the same severity level. To separate which
183 diagnostics are high severity and which are low severity, expose multiple
184 Analyzers instead. Analyzers should also be separated when their
185 diagnostics belong in different groups, or could be tagged differently
186 before being shown to the end user. Analyzers should document their severity
187 level to help downstream tools surface diagnostics properly.
188
189 Most Analyzers inspect typed Go syntax trees, but a few, such as asmdecl
190 and buildtag, inspect the raw text of Go source files or even non-Go
191 files such as assembly. To report a diagnostic against a line of a
192 raw text file, use the following sequence:
193
194         content, err := ioutil.ReadFile(filename)
195         if err != nil { ... }
196         tf := fset.AddFile(filename, -1, len(content))
197         tf.SetLinesForContent(content)
198         ...
199         pass.Reportf(tf.LineStart(line), "oops")
200
201
202 Modular analysis with Facts
203
204 To improve efficiency and scalability, large programs are routinely
205 built using separate compilation: units of the program are compiled
206 separately, and recompiled only when one of their dependencies changes;
207 independent modules may be compiled in parallel. The same technique may
208 be applied to static analyses, for the same benefits. Such analyses are
209 described as "modular".
210
211 A compiler’s type checker is an example of a modular static analysis.
212 Many other checkers we would like to apply to Go programs can be
213 understood as alternative or non-standard type systems. For example,
214 vet's printf checker infers whether a function has the "printf wrapper"
215 type, and it applies stricter checks to calls of such functions. In
216 addition, it records which functions are printf wrappers for use by
217 later analysis passes to identify other printf wrappers by induction.
218 A result such as “f is a printf wrapper” that is not interesting by
219 itself but serves as a stepping stone to an interesting result (such as
220 a diagnostic) is called a "fact".
221
222 The analysis API allows an analysis to define new types of facts, to
223 associate facts of these types with objects (named entities) declared
224 within the current package, or with the package as a whole, and to query
225 for an existing fact of a given type associated with an object or
226 package.
227
228 An Analyzer that uses facts must declare their types:
229
230         var Analyzer = &analysis.Analyzer{
231                 Name:      "printf",
232                 FactTypes: []analysis.Fact{new(isWrapper)},
233                 ...
234         }
235
236         type isWrapper struct{} // => *types.Func f “is a printf wrapper”
237
238 The driver program ensures that facts for a pass’s dependencies are
239 generated before analyzing the package and is responsible for propagating
240 facts from one package to another, possibly across address spaces.
241 Consequently, Facts must be serializable. The API requires that drivers
242 use the gob encoding, an efficient, robust, self-describing binary
243 protocol. A fact type may implement the GobEncoder/GobDecoder interfaces
244 if the default encoding is unsuitable. Facts should be stateless.
245
246 The Pass type has functions to import and export facts,
247 associated either with an object or with a package:
248
249         type Pass struct {
250                 ...
251                 ExportObjectFact func(types.Object, Fact)
252                 ImportObjectFact func(types.Object, Fact) bool
253
254                 ExportPackageFact func(fact Fact)
255                 ImportPackageFact func(*types.Package, Fact) bool
256         }
257
258 An Analyzer may only export facts associated with the current package or
259 its objects, though it may import facts from any package or object that
260 is an import dependency of the current package.
261
262 Conceptually, ExportObjectFact(obj, fact) inserts fact into a hidden map keyed by
263 the pair (obj, TypeOf(fact)), and the ImportObjectFact function
264 retrieves the entry from this map and copies its value into the variable
265 pointed to by fact. This scheme assumes that the concrete type of fact
266 is a pointer; this assumption is checked by the Validate function.
267 See the "printf" analyzer for an example of object facts in action.
268
269 Some driver implementations (such as those based on Bazel and Blaze) do
270 not currently apply analyzers to packages of the standard library.
271 Therefore, for best results, analyzer authors should not rely on
272 analysis facts being available for standard packages.
273 For example, although the printf checker is capable of deducing during
274 analysis of the log package that log.Printf is a printf wrapper,
275 this fact is built in to the analyzer so that it correctly checks
276 calls to log.Printf even when run in a driver that does not apply
277 it to standard packages. We would like to remove this limitation in future.
278
279
280 Testing an Analyzer
281
282 The analysistest subpackage provides utilities for testing an Analyzer.
283 In a few lines of code, it is possible to run an analyzer on a package
284 of testdata files and check that it reported all the expected
285 diagnostics and facts (and no more). Expectations are expressed using
286 "// want ..." comments in the input code.
287
288
289 Standalone commands
290
291 Analyzers are provided in the form of packages that a driver program is
292 expected to import. The vet command imports a set of several analyzers,
293 but users may wish to define their own analysis commands that perform
294 additional checks. To simplify the task of creating an analysis command,
295 either for a single analyzer or for a whole suite, we provide the
296 singlechecker and multichecker subpackages.
297
298 The singlechecker package provides the main function for a command that
299 runs one analyzer. By convention, each analyzer such as
300 go/passes/findcall should be accompanied by a singlechecker-based
301 command such as go/analysis/passes/findcall/cmd/findcall, defined in its
302 entirety as:
303
304         package main
305
306         import (
307                 "golang.org/x/tools/go/analysis/passes/findcall"
308                 "golang.org/x/tools/go/analysis/singlechecker"
309         )
310
311         func main() { singlechecker.Main(findcall.Analyzer) }
312
313 A tool that provides multiple analyzers can use multichecker in a
314 similar way, giving it the list of Analyzers.
315
316 */
317 package analysis