analysis.go 9.7 KB

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