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