You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

237 lines
8.8 KiB

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