runner.go 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
  1. // Package runner implements a go/analysis runner. It makes heavy use
  2. // of on-disk caching to reduce overall memory usage and to speed up
  3. // repeat runs.
  4. //
  5. // Public API
  6. //
  7. // A Runner maps a list of analyzers and package patterns to a list of
  8. // results. Results provide access to diagnostics, directives, errors
  9. // encountered, and information about packages. Results explicitly do
  10. // not contain ASTs or type information. All position information is
  11. // returned in the form of token.Position, not token.Pos. All work
  12. // that requires access to the loaded representation of a package has
  13. // to occur inside analyzers.
  14. //
  15. // Planning and execution
  16. //
  17. // Analyzing packages is split into two phases: planning and
  18. // execution.
  19. //
  20. // During planning, a directed acyclic graph of package dependencies
  21. // is computed. We materialize the full graph so that we can execute
  22. // the graph from the bottom up, without keeping unnecessary data in
  23. // memory during a DFS and with simplified parallel execution.
  24. //
  25. // During execution, leaf nodes (nodes with no outstanding
  26. // dependencies) get executed in parallel, bounded by a semaphore
  27. // sized according to the number of CPUs. Conceptually, this happens
  28. // in a loop, processing new leaf nodes as they appear, until no more
  29. // nodes are left. In the actual implementation, nodes know their
  30. // dependents, and the last dependency of a node to be processed is
  31. // responsible for scheduling its dependent.
  32. //
  33. // The graph is rooted at a synthetic root node. Upon execution of the
  34. // root node, the algorithm terminates.
  35. //
  36. // Analyzing a package repeats the same planning + execution steps,
  37. // but this time on a graph of analyzers for the package. Parallel
  38. // execution of individual analyzers is bounded by the same semaphore
  39. // as executing packages.
  40. //
  41. // Parallelism
  42. //
  43. // Actions are executed in parallel where the dependency graph allows.
  44. // Overall parallelism is bounded by a semaphore, sized according to
  45. // GOMAXPROCS. Each concurrently processed package takes up a
  46. // token, as does each analyzer – but a package can always execute at
  47. // least one analyzer, using the package's token.
  48. //
  49. // Depending on the overall shape of the graph, there may be GOMAXPROCS
  50. // packages running a single analyzer each, a single package running
  51. // GOMAXPROCS analyzers, or anything in between.
  52. //
  53. // Total memory consumption grows roughly linearly with the number of
  54. // CPUs, while total execution time is inversely proportional to the
  55. // number of CPUs. Overall, parallelism is affected by the shape of
  56. // the dependency graph. A lot of inter-connected packages will see
  57. // less parallelism than a lot of independent packages.
  58. //
  59. // Caching
  60. //
  61. // The runner caches facts, directives and diagnostics in a
  62. // content-addressable cache that is designed after Go's own cache.
  63. // Additionally, it makes use of Go's export data.
  64. //
  65. // This cache not only speeds up repeat runs, it also reduces peak
  66. // memory usage. When we've analyzed a package, we cache the results
  67. // and drop them from memory. When a dependent needs any of this
  68. // information, or when analysis is complete and we wish to render the
  69. // results, the data gets loaded from disk again.
  70. //
  71. // Data only exists in memory when it is immediately needed, not
  72. // retained for possible future uses. This trades increased CPU usage
  73. // for reduced memory usage. A single dependency may be loaded many
  74. // times over, but it greatly reduces peak memory usage, as an
  75. // arbitrary amount of time may pass between analyzing a dependency
  76. // and its dependent, during which other packages will be processed.
  77. package runner
  78. // OPT(dh): we could reduce disk storage usage of cached data by
  79. // compressing it, either directly at the cache layer, or by feeding
  80. // compressed data to the cache. Of course doing so may negatively
  81. // affect CPU usage, and there are lower hanging fruit, such as
  82. // needing to cache less data in the first place.
  83. // OPT(dh): right now, each package is analyzed completely
  84. // independently. Each package loads all of its dependencies from
  85. // export data and cached facts. If we have two packages A and B,
  86. // which both depend on C, and which both get analyzed in parallel,
  87. // then C will be loaded twice. This wastes CPU time and memory. It
  88. // would be nice if we could reuse a single C for the analysis of both
  89. // A and B.
  90. //
  91. // We can't reuse the actual types.Package or facts, because each
  92. // package gets its own token.FileSet. Sharing a global FileSet has
  93. // several drawbacks, including increased memory usage and running the
  94. // risk of running out of FileSet address space.
  95. //
  96. // We could however avoid loading the same raw export data from disk
  97. // twice, as well as deserializing gob data twice. One possible
  98. // solution would be a duplicate-suppressing in-memory cache that
  99. // caches data for a limited amount of time. When the same package
  100. // needs to be loaded twice in close succession, we can reuse work,
  101. // without holding unnecessary data in memory for an extended period
  102. // of time.
  103. //
  104. // We would likely need to do extensive benchmarking to figure out how
  105. // long to keep data around to find a sweet spot where we reduce CPU
  106. // load without increasing memory usage.
  107. //
  108. // We can probably populate the cache after we've analyzed a package,
  109. // on the assumption that it will have to be loaded again in the near
  110. // future.
  111. import (
  112. "bytes"
  113. "encoding/gob"
  114. "fmt"
  115. "go/token"
  116. "go/types"
  117. "io"
  118. "io/ioutil"
  119. "os"
  120. "reflect"
  121. "runtime"
  122. "sort"
  123. "strings"
  124. "sync/atomic"
  125. "time"
  126. "honnef.co/go/tools/analysis/lint"
  127. "honnef.co/go/tools/analysis/report"
  128. "honnef.co/go/tools/config"
  129. "honnef.co/go/tools/go/loader"
  130. tsync "honnef.co/go/tools/internal/sync"
  131. "honnef.co/go/tools/lintcmd/cache"
  132. "honnef.co/go/tools/unused"
  133. "golang.org/x/tools/go/analysis"
  134. "golang.org/x/tools/go/packages"
  135. "golang.org/x/tools/go/types/objectpath"
  136. )
  137. const sanityCheck = false
  138. // Diagnostic is like go/analysis.Diagnostic, but with all token.Pos resolved to token.Position.
  139. type Diagnostic struct {
  140. Position token.Position
  141. End token.Position
  142. Category string
  143. Message string
  144. SuggestedFixes []SuggestedFix
  145. Related []RelatedInformation
  146. }
  147. // RelatedInformation provides additional context for a diagnostic.
  148. type RelatedInformation struct {
  149. Position token.Position
  150. End token.Position
  151. Message string
  152. }
  153. type SuggestedFix struct {
  154. Message string
  155. TextEdits []TextEdit
  156. }
  157. type TextEdit struct {
  158. Position token.Position
  159. End token.Position
  160. NewText []byte
  161. }
  162. // A Result describes the result of analyzing a single package.
  163. //
  164. // It holds references to cached diagnostics and directives. They can
  165. // be loaded on demand with the Load method.
  166. type Result struct {
  167. Package *loader.PackageSpec
  168. Config config.Config
  169. Initial bool
  170. Skipped bool
  171. Failed bool
  172. Errors []error
  173. // Action results, path to file
  174. results string
  175. // Results relevant to testing, only set when test mode is enabled, path to file
  176. testData string
  177. }
  178. type SerializedDirective struct {
  179. Command string
  180. Arguments []string
  181. // The position of the comment
  182. DirectivePosition token.Position
  183. // The position of the node that the comment is attached to
  184. NodePosition token.Position
  185. }
  186. func serializeDirective(dir lint.Directive, fset *token.FileSet) SerializedDirective {
  187. return SerializedDirective{
  188. Command: dir.Command,
  189. Arguments: dir.Arguments,
  190. DirectivePosition: report.DisplayPosition(fset, dir.Directive.Pos()),
  191. NodePosition: report.DisplayPosition(fset, dir.Node.Pos()),
  192. }
  193. }
  194. type ResultData struct {
  195. Directives []SerializedDirective
  196. Diagnostics []Diagnostic
  197. Unused unused.SerializedResult
  198. }
  199. func (r Result) Load() (ResultData, error) {
  200. if r.Failed {
  201. panic("Load called on failed Result")
  202. }
  203. if r.results == "" {
  204. // this package was only a dependency
  205. return ResultData{}, nil
  206. }
  207. f, err := os.Open(r.results)
  208. if err != nil {
  209. return ResultData{}, fmt.Errorf("failed loading result: %w", err)
  210. }
  211. defer f.Close()
  212. var out ResultData
  213. err = gob.NewDecoder(f).Decode(&out)
  214. return out, err
  215. }
  216. type Want struct {
  217. Position token.Position
  218. Comment string
  219. }
  220. // TestData contains extra information about analysis runs that is only available in test mode.
  221. type TestData struct {
  222. // Wants contains a list of '// want' comments extracted from Go files.
  223. // These comments are used in unit tests.
  224. Wants []Want
  225. // Facts contains facts produced by analyzers for a package.
  226. // Unlike vetx, this list only contains facts specific to this package,
  227. // not all facts for the transitive closure of dependencies.
  228. Facts []TestFact
  229. }
  230. // LoadTest returns data relevant to testing.
  231. // It should only be called if Runner.TestMode was set to true.
  232. func (r Result) LoadTest() (TestData, error) {
  233. if r.Failed {
  234. panic("Load called on failed Result")
  235. }
  236. if r.results == "" {
  237. // this package was only a dependency
  238. return TestData{}, nil
  239. }
  240. f, err := os.Open(r.testData)
  241. if err != nil {
  242. return TestData{}, fmt.Errorf("failed loading test data: %w", err)
  243. }
  244. defer f.Close()
  245. var out TestData
  246. err = gob.NewDecoder(f).Decode(&out)
  247. return out, err
  248. }
  249. type action interface {
  250. Deps() []action
  251. Triggers() []action
  252. DecrementPending() bool
  253. MarkFailed()
  254. IsFailed() bool
  255. AddError(error)
  256. }
  257. type baseAction struct {
  258. // Action description
  259. deps []action
  260. triggers []action
  261. pending uint32
  262. // Action results
  263. // failed is set to true if the action couldn't be processed. This
  264. // may either be due to an error specific to this action, in
  265. // which case the errors field will be populated, or due to a
  266. // dependency being marked as failed, in which case errors will be
  267. // empty.
  268. failed bool
  269. errors []error
  270. }
  271. func (act *baseAction) Deps() []action { return act.deps }
  272. func (act *baseAction) Triggers() []action { return act.triggers }
  273. func (act *baseAction) DecrementPending() bool {
  274. return atomic.AddUint32(&act.pending, ^uint32(0)) == 0
  275. }
  276. func (act *baseAction) MarkFailed() { act.failed = true }
  277. func (act *baseAction) IsFailed() bool { return act.failed }
  278. func (act *baseAction) AddError(err error) { act.errors = append(act.errors, err) }
  279. // packageAction describes the act of loading a package, fully
  280. // analyzing it, and storing the results.
  281. type packageAction struct {
  282. baseAction
  283. // Action description
  284. Package *loader.PackageSpec
  285. factsOnly bool
  286. hash cache.ActionID
  287. // Action results
  288. cfg config.Config
  289. vetx string
  290. results string
  291. testData string
  292. skipped bool
  293. }
  294. func (act *packageAction) String() string {
  295. return fmt.Sprintf("packageAction(%s)", act.Package)
  296. }
  297. type objectFact struct {
  298. fact analysis.Fact
  299. // TODO(dh): why do we store the objectpath when producing the
  300. // fact? Is it just for the sanity checking, which compares the
  301. // stored path with a path recomputed from objectFactKey.Obj?
  302. path objectpath.Path
  303. }
  304. type objectFactKey struct {
  305. Obj types.Object
  306. Type reflect.Type
  307. }
  308. type packageFactKey struct {
  309. Pkg *types.Package
  310. Type reflect.Type
  311. }
  312. type gobFact struct {
  313. PkgPath string
  314. ObjPath string
  315. Fact analysis.Fact
  316. }
  317. // TestFact is a serialization of facts that is specific to the test mode.
  318. type TestFact struct {
  319. ObjectName string
  320. Position token.Position
  321. FactString string
  322. Analyzer string
  323. }
  324. // analyzerAction describes the act of analyzing a package with a
  325. // single analyzer.
  326. type analyzerAction struct {
  327. baseAction
  328. // Action description
  329. Analyzer *analysis.Analyzer
  330. // Action results
  331. // We can store actual results here without worrying about memory
  332. // consumption because analyzer actions get garbage collected once
  333. // a package has been fully analyzed.
  334. Result interface{}
  335. Diagnostics []Diagnostic
  336. ObjectFacts map[objectFactKey]objectFact
  337. PackageFacts map[packageFactKey]analysis.Fact
  338. Pass *analysis.Pass
  339. }
  340. func (act *analyzerAction) String() string {
  341. return fmt.Sprintf("analyzerAction(%s)", act.Analyzer)
  342. }
  343. // A Runner executes analyzers on packages.
  344. type Runner struct {
  345. Stats Stats
  346. GoVersion string
  347. // if GoVersion == "module", and we couldn't determine the
  348. // module's Go version, use this as the fallback
  349. FallbackGoVersion string
  350. // If set to true, Runner will populate results with data relevant to testing analyzers
  351. TestMode bool
  352. // GoVersion might be "module"; actualGoVersion contains the resolved version
  353. actualGoVersion string
  354. // Config that gets merged with per-package configs
  355. cfg config.Config
  356. cache *cache.Cache
  357. semaphore tsync.Semaphore
  358. }
  359. type subrunner struct {
  360. *Runner
  361. analyzers []*analysis.Analyzer
  362. factAnalyzers []*analysis.Analyzer
  363. analyzerNames string
  364. cache *cache.Cache
  365. }
  366. // New returns a new Runner.
  367. func New(cfg config.Config, c *cache.Cache) (*Runner, error) {
  368. return &Runner{
  369. cfg: cfg,
  370. cache: c,
  371. semaphore: tsync.NewSemaphore(runtime.GOMAXPROCS(0)),
  372. }, nil
  373. }
  374. func newSubrunner(r *Runner, analyzers []*analysis.Analyzer) *subrunner {
  375. analyzerNames := make([]string, len(analyzers))
  376. for i, a := range analyzers {
  377. analyzerNames[i] = a.Name
  378. }
  379. sort.Strings(analyzerNames)
  380. var factAnalyzers []*analysis.Analyzer
  381. for _, a := range analyzers {
  382. if len(a.FactTypes) > 0 {
  383. factAnalyzers = append(factAnalyzers, a)
  384. }
  385. }
  386. return &subrunner{
  387. Runner: r,
  388. analyzers: analyzers,
  389. factAnalyzers: factAnalyzers,
  390. analyzerNames: strings.Join(analyzerNames, ","),
  391. cache: r.cache,
  392. }
  393. }
  394. func newPackageActionRoot(pkg *loader.PackageSpec, cache map[*loader.PackageSpec]*packageAction) *packageAction {
  395. a := newPackageAction(pkg, cache)
  396. a.factsOnly = false
  397. return a
  398. }
  399. func newPackageAction(pkg *loader.PackageSpec, cache map[*loader.PackageSpec]*packageAction) *packageAction {
  400. if a, ok := cache[pkg]; ok {
  401. return a
  402. }
  403. a := &packageAction{
  404. Package: pkg,
  405. factsOnly: true, // will be overwritten by any call to Action
  406. }
  407. cache[pkg] = a
  408. if len(pkg.Errors) > 0 {
  409. a.errors = make([]error, len(pkg.Errors))
  410. for i, err := range pkg.Errors {
  411. a.errors[i] = err
  412. }
  413. a.failed = true
  414. // We don't need to process our imports if this package is
  415. // already broken.
  416. return a
  417. }
  418. a.deps = make([]action, 0, len(pkg.Imports))
  419. for _, dep := range pkg.Imports {
  420. depa := newPackageAction(dep, cache)
  421. depa.triggers = append(depa.triggers, a)
  422. a.deps = append(a.deps, depa)
  423. if depa.failed {
  424. a.failed = true
  425. }
  426. }
  427. // sort dependencies because the list of dependencies is part of
  428. // the cache key
  429. sort.Slice(a.deps, func(i, j int) bool {
  430. return a.deps[i].(*packageAction).Package.ID < a.deps[j].(*packageAction).Package.ID
  431. })
  432. a.pending = uint32(len(a.deps))
  433. return a
  434. }
  435. func newAnalyzerAction(an *analysis.Analyzer, cache map[*analysis.Analyzer]*analyzerAction) *analyzerAction {
  436. if a, ok := cache[an]; ok {
  437. return a
  438. }
  439. a := &analyzerAction{
  440. Analyzer: an,
  441. ObjectFacts: map[objectFactKey]objectFact{},
  442. PackageFacts: map[packageFactKey]analysis.Fact{},
  443. }
  444. cache[an] = a
  445. for _, dep := range an.Requires {
  446. depa := newAnalyzerAction(dep, cache)
  447. depa.triggers = append(depa.triggers, a)
  448. a.deps = append(a.deps, depa)
  449. }
  450. a.pending = uint32(len(a.deps))
  451. return a
  452. }
  453. func getCachedFiles(cache *cache.Cache, ids []cache.ActionID, out []*string) error {
  454. for i, id := range ids {
  455. var err error
  456. *out[i], _, err = cache.GetFile(id)
  457. if err != nil {
  458. return err
  459. }
  460. }
  461. return nil
  462. }
  463. func (r *subrunner) do(act action) error {
  464. a := act.(*packageAction)
  465. defer func() {
  466. r.Stats.finishPackage()
  467. if !a.factsOnly {
  468. r.Stats.finishInitialPackage()
  469. }
  470. }()
  471. // compute hash of action
  472. a.cfg = a.Package.Config.Merge(r.cfg)
  473. h := r.cache.NewHash("staticcheck " + a.Package.PkgPath)
  474. // Note that we do not filter the list of analyzers by the
  475. // package's configuration. We don't allow configuration to
  476. // accidentally break dependencies between analyzers, and it's
  477. // easier to always run all checks and filter the output. This
  478. // also makes cached data more reusable.
  479. // OPT(dh): not all changes in configuration invalidate cached
  480. // data. specifically, when a.factsOnly == true, we only care
  481. // about checks that produce facts, and settings that affect those
  482. // checks.
  483. // Config used for constructing the hash; this config doesn't have
  484. // Checks populated, because we always run all checks.
  485. //
  486. // This even works for users who add custom checks, because we include the binary's hash.
  487. hashCfg := a.cfg
  488. hashCfg.Checks = nil
  489. // note that we don't hash staticcheck's version; it is set as the
  490. // salt by a package main.
  491. fmt.Fprintf(h, "cfg %#v\n", hashCfg)
  492. fmt.Fprintf(h, "pkg %x\n", a.Package.Hash)
  493. fmt.Fprintf(h, "analyzers %s\n", r.analyzerNames)
  494. fmt.Fprintf(h, "go %s\n", r.actualGoVersion)
  495. // OPT(dh): do we actually need to hash vetx? can we not assume
  496. // that for identical inputs, staticcheck will produce identical
  497. // vetx?
  498. for _, dep := range a.deps {
  499. dep := dep.(*packageAction)
  500. vetxHash, err := cache.FileHash(dep.vetx)
  501. if err != nil {
  502. return fmt.Errorf("failed computing hash: %w", err)
  503. }
  504. fmt.Fprintf(h, "vetout %q %x\n", dep.Package.PkgPath, vetxHash)
  505. }
  506. a.hash = cache.ActionID(h.Sum())
  507. // try to fetch hashed data
  508. ids := make([]cache.ActionID, 0, 2)
  509. ids = append(ids, cache.Subkey(a.hash, "vetx"))
  510. if !a.factsOnly {
  511. ids = append(ids, cache.Subkey(a.hash, "results"))
  512. if r.TestMode {
  513. ids = append(ids, cache.Subkey(a.hash, "testdata"))
  514. }
  515. }
  516. if err := getCachedFiles(r.cache, ids, []*string{&a.vetx, &a.results, &a.testData}); err != nil {
  517. result, err := r.doUncached(a)
  518. if err != nil {
  519. return err
  520. }
  521. if a.failed {
  522. return nil
  523. }
  524. a.skipped = result.skipped
  525. // OPT(dh) instead of collecting all object facts and encoding
  526. // them after analysis finishes, we could encode them as we
  527. // go. however, that would require some locking.
  528. //
  529. // OPT(dh): We could sort gobFacts for more consistent output,
  530. // but it doesn't matter. The hash of a package includes all
  531. // of its files, so whether the vetx hash changes or not, a
  532. // change to a package requires re-analyzing all dependents,
  533. // even if the vetx data stayed the same. See also the note at
  534. // the top of loader/hash.go.
  535. tf := &bytes.Buffer{}
  536. enc := gob.NewEncoder(tf)
  537. for _, gf := range result.facts {
  538. if err := enc.Encode(gf); err != nil {
  539. return fmt.Errorf("failed gob encoding data: %w", err)
  540. }
  541. }
  542. a.vetx, err = r.writeCacheReader(a, "vetx", bytes.NewReader(tf.Bytes()))
  543. if err != nil {
  544. return err
  545. }
  546. if a.factsOnly {
  547. return nil
  548. }
  549. var out ResultData
  550. out.Directives = make([]SerializedDirective, len(result.dirs))
  551. for i, dir := range result.dirs {
  552. out.Directives[i] = serializeDirective(dir, result.lpkg.Fset)
  553. }
  554. out.Diagnostics = result.diags
  555. out.Unused = result.unused
  556. a.results, err = r.writeCacheGob(a, "results", out)
  557. if err != nil {
  558. return err
  559. }
  560. if r.TestMode {
  561. out := TestData{
  562. Wants: result.wants,
  563. Facts: result.testFacts,
  564. }
  565. a.testData, err = r.writeCacheGob(a, "testdata", out)
  566. if err != nil {
  567. return err
  568. }
  569. }
  570. }
  571. return nil
  572. }
  573. // ActiveWorkers returns the number of currently running workers.
  574. func (r *Runner) ActiveWorkers() int {
  575. return r.semaphore.Len()
  576. }
  577. // TotalWorkers returns the maximum number of possible workers.
  578. func (r *Runner) TotalWorkers() int {
  579. return r.semaphore.Cap()
  580. }
  581. func (r *Runner) writeCacheReader(a *packageAction, kind string, rs io.ReadSeeker) (string, error) {
  582. h := cache.Subkey(a.hash, kind)
  583. out, _, err := r.cache.Put(h, rs)
  584. if err != nil {
  585. return "", fmt.Errorf("failed caching data: %w", err)
  586. }
  587. return r.cache.OutputFile(out), nil
  588. }
  589. func (r *Runner) writeCacheGob(a *packageAction, kind string, data interface{}) (string, error) {
  590. f, err := ioutil.TempFile("", "staticcheck")
  591. if err != nil {
  592. return "", err
  593. }
  594. defer f.Close()
  595. os.Remove(f.Name())
  596. if err := gob.NewEncoder(f).Encode(data); err != nil {
  597. return "", fmt.Errorf("failed gob encoding data: %w", err)
  598. }
  599. if _, err := f.Seek(0, io.SeekStart); err != nil {
  600. return "", err
  601. }
  602. return r.writeCacheReader(a, kind, f)
  603. }
  604. type packageActionResult struct {
  605. facts []gobFact
  606. diags []Diagnostic
  607. unused unused.SerializedResult
  608. dirs []lint.Directive
  609. lpkg *loader.Package
  610. skipped bool
  611. // Only set when using test mode
  612. testFacts []TestFact
  613. wants []Want
  614. }
  615. func (r *subrunner) doUncached(a *packageAction) (packageActionResult, error) {
  616. // OPT(dh): for a -> b; c -> b; if both a and b are being
  617. // processed concurrently, we shouldn't load b's export data
  618. // twice.
  619. pkg, _, err := loader.Load(a.Package)
  620. if err != nil {
  621. return packageActionResult{}, err
  622. }
  623. if len(pkg.Errors) > 0 {
  624. // this handles errors that occurred during type-checking the
  625. // package in loader.Load
  626. for _, err := range pkg.Errors {
  627. a.errors = append(a.errors, err)
  628. }
  629. a.failed = true
  630. return packageActionResult{}, nil
  631. }
  632. if len(pkg.Syntax) == 0 && pkg.PkgPath != "unsafe" {
  633. return packageActionResult{lpkg: pkg, skipped: true}, nil
  634. }
  635. // OPT(dh): instead of parsing directives twice (twice because
  636. // U1000 depends on the facts.Directives analyzer), reuse the
  637. // existing result
  638. var dirs []lint.Directive
  639. if !a.factsOnly {
  640. dirs = lint.ParseDirectives(pkg.Syntax, pkg.Fset)
  641. }
  642. res, err := r.runAnalyzers(a, pkg)
  643. var wants []Want
  644. if r.TestMode {
  645. // Extract 'want' comments from parsed Go files.
  646. for _, f := range pkg.Syntax {
  647. for _, cgroup := range f.Comments {
  648. for _, c := range cgroup.List {
  649. text := strings.TrimPrefix(c.Text, "//")
  650. if text == c.Text { // not a //-comment.
  651. text = strings.TrimPrefix(text, "/*")
  652. text = strings.TrimSuffix(text, "*/")
  653. }
  654. // Hack: treat a comment of the form "//...// want..."
  655. // or "/*...// want... */
  656. // as if it starts at 'want'.
  657. // This allows us to add comments on comments,
  658. // as required when testing the buildtag analyzer.
  659. if i := strings.Index(text, "// want"); i >= 0 {
  660. text = text[i+len("// "):]
  661. }
  662. posn := pkg.Fset.Position(c.Pos())
  663. wants = append(wants, Want{Position: posn, Comment: text})
  664. }
  665. }
  666. }
  667. // TODO(dh): add support for non-Go files
  668. }
  669. return packageActionResult{
  670. facts: res.facts,
  671. testFacts: res.testFacts,
  672. wants: wants,
  673. diags: res.diagnostics,
  674. unused: res.unused,
  675. dirs: dirs,
  676. lpkg: pkg,
  677. }, err
  678. }
  679. func pkgPaths(root *types.Package) map[string]*types.Package {
  680. out := map[string]*types.Package{}
  681. var dfs func(*types.Package)
  682. dfs = func(pkg *types.Package) {
  683. if _, ok := out[pkg.Path()]; ok {
  684. return
  685. }
  686. out[pkg.Path()] = pkg
  687. for _, imp := range pkg.Imports() {
  688. dfs(imp)
  689. }
  690. }
  691. dfs(root)
  692. return out
  693. }
  694. func (r *Runner) loadFacts(root *types.Package, dep *packageAction, objFacts map[objectFactKey]objectFact, pkgFacts map[packageFactKey]analysis.Fact) error {
  695. // Load facts of all imported packages
  696. vetx, err := os.Open(dep.vetx)
  697. if err != nil {
  698. return fmt.Errorf("failed loading cached facts: %w", err)
  699. }
  700. defer vetx.Close()
  701. pathToPkg := pkgPaths(root)
  702. dec := gob.NewDecoder(vetx)
  703. for {
  704. var gf gobFact
  705. err := dec.Decode(&gf)
  706. if err != nil {
  707. if err == io.EOF {
  708. break
  709. }
  710. return fmt.Errorf("failed loading cached facts: %w", err)
  711. }
  712. pkg, ok := pathToPkg[gf.PkgPath]
  713. if !ok {
  714. continue
  715. }
  716. if gf.ObjPath == "" {
  717. pkgFacts[packageFactKey{
  718. Pkg: pkg,
  719. Type: reflect.TypeOf(gf.Fact),
  720. }] = gf.Fact
  721. } else {
  722. obj, err := objectpath.Object(pkg, objectpath.Path(gf.ObjPath))
  723. if err != nil {
  724. continue
  725. }
  726. objFacts[objectFactKey{
  727. Obj: obj,
  728. Type: reflect.TypeOf(gf.Fact),
  729. }] = objectFact{gf.Fact, objectpath.Path(gf.ObjPath)}
  730. }
  731. }
  732. return nil
  733. }
  734. func genericHandle(a action, root action, queue chan action, sem *tsync.Semaphore, exec func(a action) error) {
  735. if a == root {
  736. close(queue)
  737. if sem != nil {
  738. sem.Release()
  739. }
  740. return
  741. }
  742. if !a.IsFailed() {
  743. // the action may have already been marked as failed during
  744. // construction of the action graph, for example because of
  745. // unresolved imports.
  746. for _, dep := range a.Deps() {
  747. if dep.IsFailed() {
  748. // One of our dependencies failed, so mark this package as
  749. // failed and bail. We don't need to record an error for
  750. // this package, the relevant error will have been
  751. // reported by the first package in the chain that failed.
  752. a.MarkFailed()
  753. break
  754. }
  755. }
  756. }
  757. if !a.IsFailed() {
  758. if err := exec(a); err != nil {
  759. a.MarkFailed()
  760. a.AddError(err)
  761. }
  762. }
  763. if sem != nil {
  764. sem.Release()
  765. }
  766. for _, t := range a.Triggers() {
  767. if t.DecrementPending() {
  768. queue <- t
  769. }
  770. }
  771. }
  772. type analyzerRunner struct {
  773. pkg *loader.Package
  774. // object facts of our dependencies; may contain facts of
  775. // analyzers other than the current one
  776. depObjFacts map[objectFactKey]objectFact
  777. // package facts of our dependencies; may contain facts of
  778. // analyzers other than the current one
  779. depPkgFacts map[packageFactKey]analysis.Fact
  780. factsOnly bool
  781. stats *Stats
  782. }
  783. func (ar *analyzerRunner) do(act action) error {
  784. a := act.(*analyzerAction)
  785. results := map[*analysis.Analyzer]interface{}{}
  786. // TODO(dh): does this have to be recursive?
  787. for _, dep := range a.deps {
  788. dep := dep.(*analyzerAction)
  789. results[dep.Analyzer] = dep.Result
  790. }
  791. // OPT(dh): cache factTypes, it is the same for all packages for a given analyzer
  792. //
  793. // OPT(dh): do we need the factTypes map? most analyzers have 0-1
  794. // fact types. iterating over the slice is probably faster than
  795. // indexing a map.
  796. factTypes := map[reflect.Type]struct{}{}
  797. for _, typ := range a.Analyzer.FactTypes {
  798. factTypes[reflect.TypeOf(typ)] = struct{}{}
  799. }
  800. filterFactType := func(typ reflect.Type) bool {
  801. _, ok := factTypes[typ]
  802. return ok
  803. }
  804. a.Pass = &analysis.Pass{
  805. Analyzer: a.Analyzer,
  806. Fset: ar.pkg.Fset,
  807. Files: ar.pkg.Syntax,
  808. OtherFiles: ar.pkg.OtherFiles,
  809. Pkg: ar.pkg.Types,
  810. TypesInfo: ar.pkg.TypesInfo,
  811. TypesSizes: ar.pkg.TypesSizes,
  812. Report: func(diag analysis.Diagnostic) {
  813. if !ar.factsOnly {
  814. if diag.Category == "" {
  815. diag.Category = a.Analyzer.Name
  816. }
  817. d := Diagnostic{
  818. Position: report.DisplayPosition(ar.pkg.Fset, diag.Pos),
  819. End: report.DisplayPosition(ar.pkg.Fset, diag.End),
  820. Category: diag.Category,
  821. Message: diag.Message,
  822. }
  823. for _, sugg := range diag.SuggestedFixes {
  824. s := SuggestedFix{
  825. Message: sugg.Message,
  826. }
  827. for _, edit := range sugg.TextEdits {
  828. s.TextEdits = append(s.TextEdits, TextEdit{
  829. Position: report.DisplayPosition(ar.pkg.Fset, edit.Pos),
  830. End: report.DisplayPosition(ar.pkg.Fset, edit.End),
  831. NewText: edit.NewText,
  832. })
  833. }
  834. d.SuggestedFixes = append(d.SuggestedFixes, s)
  835. }
  836. for _, rel := range diag.Related {
  837. d.Related = append(d.Related, RelatedInformation{
  838. Position: report.DisplayPosition(ar.pkg.Fset, rel.Pos),
  839. End: report.DisplayPosition(ar.pkg.Fset, rel.End),
  840. Message: rel.Message,
  841. })
  842. }
  843. a.Diagnostics = append(a.Diagnostics, d)
  844. }
  845. },
  846. ResultOf: results,
  847. ImportObjectFact: func(obj types.Object, fact analysis.Fact) bool {
  848. key := objectFactKey{
  849. Obj: obj,
  850. Type: reflect.TypeOf(fact),
  851. }
  852. if f, ok := ar.depObjFacts[key]; ok {
  853. reflect.ValueOf(fact).Elem().Set(reflect.ValueOf(f.fact).Elem())
  854. return true
  855. } else if f, ok := a.ObjectFacts[key]; ok {
  856. reflect.ValueOf(fact).Elem().Set(reflect.ValueOf(f.fact).Elem())
  857. return true
  858. }
  859. return false
  860. },
  861. ImportPackageFact: func(pkg *types.Package, fact analysis.Fact) bool {
  862. key := packageFactKey{
  863. Pkg: pkg,
  864. Type: reflect.TypeOf(fact),
  865. }
  866. if f, ok := ar.depPkgFacts[key]; ok {
  867. reflect.ValueOf(fact).Elem().Set(reflect.ValueOf(f).Elem())
  868. return true
  869. } else if f, ok := a.PackageFacts[key]; ok {
  870. reflect.ValueOf(fact).Elem().Set(reflect.ValueOf(f).Elem())
  871. return true
  872. }
  873. return false
  874. },
  875. ExportObjectFact: func(obj types.Object, fact analysis.Fact) {
  876. key := objectFactKey{
  877. Obj: obj,
  878. Type: reflect.TypeOf(fact),
  879. }
  880. path, _ := objectpath.For(obj)
  881. a.ObjectFacts[key] = objectFact{fact, path}
  882. },
  883. ExportPackageFact: func(fact analysis.Fact) {
  884. key := packageFactKey{
  885. Pkg: ar.pkg.Types,
  886. Type: reflect.TypeOf(fact),
  887. }
  888. a.PackageFacts[key] = fact
  889. },
  890. AllPackageFacts: func() []analysis.PackageFact {
  891. out := make([]analysis.PackageFact, 0, len(ar.depPkgFacts)+len(a.PackageFacts))
  892. for key, fact := range ar.depPkgFacts {
  893. out = append(out, analysis.PackageFact{
  894. Package: key.Pkg,
  895. Fact: fact,
  896. })
  897. }
  898. for key, fact := range a.PackageFacts {
  899. out = append(out, analysis.PackageFact{
  900. Package: key.Pkg,
  901. Fact: fact,
  902. })
  903. }
  904. return out
  905. },
  906. AllObjectFacts: func() []analysis.ObjectFact {
  907. out := make([]analysis.ObjectFact, 0, len(ar.depObjFacts)+len(a.ObjectFacts))
  908. for key, fact := range ar.depObjFacts {
  909. if filterFactType(key.Type) {
  910. out = append(out, analysis.ObjectFact{
  911. Object: key.Obj,
  912. Fact: fact.fact,
  913. })
  914. }
  915. }
  916. for key, fact := range a.ObjectFacts {
  917. if filterFactType(key.Type) {
  918. out = append(out, analysis.ObjectFact{
  919. Object: key.Obj,
  920. Fact: fact.fact,
  921. })
  922. }
  923. }
  924. return out
  925. },
  926. }
  927. t := time.Now()
  928. res, err := a.Analyzer.Run(a.Pass)
  929. ar.stats.measureAnalyzer(a.Analyzer, ar.pkg.PackageSpec, time.Since(t))
  930. if err != nil {
  931. return err
  932. }
  933. a.Result = res
  934. return nil
  935. }
  936. type analysisResult struct {
  937. facts []gobFact
  938. diagnostics []Diagnostic
  939. unused unused.SerializedResult
  940. // Only set when using test mode
  941. testFacts []TestFact
  942. }
  943. func (r *subrunner) runAnalyzers(pkgAct *packageAction, pkg *loader.Package) (analysisResult, error) {
  944. depObjFacts := map[objectFactKey]objectFact{}
  945. depPkgFacts := map[packageFactKey]analysis.Fact{}
  946. for _, dep := range pkgAct.deps {
  947. if err := r.loadFacts(pkg.Types, dep.(*packageAction), depObjFacts, depPkgFacts); err != nil {
  948. return analysisResult{}, err
  949. }
  950. }
  951. root := &analyzerAction{}
  952. var analyzers []*analysis.Analyzer
  953. if pkgAct.factsOnly {
  954. // When analyzing non-initial packages, we only care about
  955. // analyzers that produce facts.
  956. analyzers = r.factAnalyzers
  957. } else {
  958. analyzers = r.analyzers
  959. }
  960. all := map[*analysis.Analyzer]*analyzerAction{}
  961. for _, a := range analyzers {
  962. a := newAnalyzerAction(a, all)
  963. root.deps = append(root.deps, a)
  964. a.triggers = append(a.triggers, root)
  965. }
  966. root.pending = uint32(len(root.deps))
  967. ar := &analyzerRunner{
  968. pkg: pkg,
  969. factsOnly: pkgAct.factsOnly,
  970. depObjFacts: depObjFacts,
  971. depPkgFacts: depPkgFacts,
  972. stats: &r.Stats,
  973. }
  974. queue := make(chan action, len(all))
  975. for _, a := range all {
  976. if len(a.Deps()) == 0 {
  977. queue <- a
  978. }
  979. }
  980. // Don't hang if there are no analyzers to run; for example
  981. // because we are analyzing a dependency but have no analyzers
  982. // that produce facts.
  983. if len(all) == 0 {
  984. close(queue)
  985. }
  986. for item := range queue {
  987. b := r.semaphore.AcquireMaybe()
  988. if b {
  989. go genericHandle(item, root, queue, &r.semaphore, ar.do)
  990. } else {
  991. // the semaphore is exhausted; run the analysis under the
  992. // token we've acquired for analyzing the package.
  993. genericHandle(item, root, queue, nil, ar.do)
  994. }
  995. }
  996. var unusedResult unused.SerializedResult
  997. for _, a := range all {
  998. if a != root && a.Analyzer.Name == "U1000" && !a.failed {
  999. // TODO(dh): figure out a clean abstraction, instead of
  1000. // special-casing U1000.
  1001. unusedResult = unused.Serialize(a.Pass, a.Result.(unused.Result), pkg.Fset)
  1002. }
  1003. for key, fact := range a.ObjectFacts {
  1004. depObjFacts[key] = fact
  1005. }
  1006. for key, fact := range a.PackageFacts {
  1007. depPkgFacts[key] = fact
  1008. }
  1009. }
  1010. // OPT(dh): cull objects not reachable via the exported closure
  1011. var testFacts []TestFact
  1012. gobFacts := make([]gobFact, 0, len(depObjFacts)+len(depPkgFacts))
  1013. for key, fact := range depObjFacts {
  1014. if fact.path == "" {
  1015. continue
  1016. }
  1017. if sanityCheck {
  1018. p, _ := objectpath.For(key.Obj)
  1019. if p != fact.path {
  1020. panic(fmt.Sprintf("got different object paths for %v. old: %q new: %q", key.Obj, fact.path, p))
  1021. }
  1022. }
  1023. gf := gobFact{
  1024. PkgPath: key.Obj.Pkg().Path(),
  1025. ObjPath: string(fact.path),
  1026. Fact: fact.fact,
  1027. }
  1028. gobFacts = append(gobFacts, gf)
  1029. }
  1030. for key, fact := range depPkgFacts {
  1031. gf := gobFact{
  1032. PkgPath: key.Pkg.Path(),
  1033. Fact: fact,
  1034. }
  1035. gobFacts = append(gobFacts, gf)
  1036. }
  1037. if r.TestMode {
  1038. for _, a := range all {
  1039. for key, fact := range a.ObjectFacts {
  1040. tgf := TestFact{
  1041. ObjectName: key.Obj.Name(),
  1042. Position: pkg.Fset.Position(key.Obj.Pos()),
  1043. FactString: fmt.Sprint(fact.fact),
  1044. Analyzer: a.Analyzer.Name,
  1045. }
  1046. testFacts = append(testFacts, tgf)
  1047. }
  1048. for _, fact := range a.PackageFacts {
  1049. tgf := TestFact{
  1050. ObjectName: "",
  1051. Position: pkg.Fset.Position(pkg.Syntax[0].Pos()),
  1052. FactString: fmt.Sprint(fact),
  1053. Analyzer: a.Analyzer.Name,
  1054. }
  1055. testFacts = append(testFacts, tgf)
  1056. }
  1057. }
  1058. }
  1059. var diags []Diagnostic
  1060. for _, a := range root.deps {
  1061. a := a.(*analyzerAction)
  1062. diags = append(diags, a.Diagnostics...)
  1063. }
  1064. return analysisResult{
  1065. facts: gobFacts,
  1066. testFacts: testFacts,
  1067. diagnostics: diags,
  1068. unused: unusedResult,
  1069. }, nil
  1070. }
  1071. func registerGobTypes(analyzers []*analysis.Analyzer) {
  1072. for _, a := range analyzers {
  1073. for _, typ := range a.FactTypes {
  1074. // FIXME(dh): use RegisterName so we can work around collisions
  1075. // in names. For pointer-types, gob incorrectly qualifies
  1076. // type names with the package name, not the import path.
  1077. gob.Register(typ)
  1078. }
  1079. }
  1080. }
  1081. func allAnalyzers(analyzers []*analysis.Analyzer) []*analysis.Analyzer {
  1082. seen := map[*analysis.Analyzer]struct{}{}
  1083. out := make([]*analysis.Analyzer, 0, len(analyzers))
  1084. var dfs func(*analysis.Analyzer)
  1085. dfs = func(a *analysis.Analyzer) {
  1086. if _, ok := seen[a]; ok {
  1087. return
  1088. }
  1089. seen[a] = struct{}{}
  1090. out = append(out, a)
  1091. for _, dep := range a.Requires {
  1092. dfs(dep)
  1093. }
  1094. }
  1095. for _, a := range analyzers {
  1096. dfs(a)
  1097. }
  1098. return out
  1099. }
  1100. // Run loads the packages specified by patterns, runs analyzers on
  1101. // them and returns the results. Each result corresponds to a single
  1102. // package. Results will be returned for all packages, including
  1103. // dependencies. Errors specific to packages will be reported in the
  1104. // respective results.
  1105. //
  1106. // If cfg is nil, a default config will be used. Otherwise, cfg will
  1107. // be used, with the exception of the Mode field.
  1108. func (r *Runner) Run(cfg *packages.Config, analyzers []*analysis.Analyzer, patterns []string) ([]Result, error) {
  1109. analyzers = allAnalyzers(analyzers)
  1110. registerGobTypes(analyzers)
  1111. r.Stats.setState(StateLoadPackageGraph)
  1112. lpkgs, err := loader.Graph(r.cache, cfg, patterns...)
  1113. if err != nil {
  1114. return nil, err
  1115. }
  1116. r.Stats.setInitialPackages(len(lpkgs))
  1117. if len(lpkgs) == 0 {
  1118. return nil, nil
  1119. }
  1120. var goVersion string
  1121. if r.GoVersion == "module" {
  1122. for _, lpkg := range lpkgs {
  1123. if m := lpkg.Module; m != nil {
  1124. if goVersion == "" {
  1125. goVersion = m.GoVersion
  1126. } else if goVersion != m.GoVersion {
  1127. // Theoretically, we should only ever see a single Go
  1128. // module. At least that's currently (as of Go 1.15)
  1129. // true when using 'go list'.
  1130. fmt.Fprintln(os.Stderr, "warning: encountered multiple modules and could not deduce targeted Go version")
  1131. goVersion = ""
  1132. break
  1133. }
  1134. }
  1135. }
  1136. } else {
  1137. goVersion = r.GoVersion
  1138. }
  1139. if goVersion == "" {
  1140. if r.FallbackGoVersion == "" {
  1141. panic("could not determine Go version of module, and fallback version hasn't been set")
  1142. }
  1143. goVersion = r.FallbackGoVersion
  1144. }
  1145. r.actualGoVersion = goVersion
  1146. for _, a := range analyzers {
  1147. flag := a.Flags.Lookup("go")
  1148. if flag == nil {
  1149. continue
  1150. }
  1151. if err := flag.Value.Set(goVersion); err != nil {
  1152. return nil, err
  1153. }
  1154. }
  1155. r.Stats.setState(StateBuildActionGraph)
  1156. all := map[*loader.PackageSpec]*packageAction{}
  1157. root := &packageAction{}
  1158. for _, lpkg := range lpkgs {
  1159. a := newPackageActionRoot(lpkg, all)
  1160. root.deps = append(root.deps, a)
  1161. a.triggers = append(a.triggers, root)
  1162. }
  1163. root.pending = uint32(len(root.deps))
  1164. queue := make(chan action)
  1165. r.Stats.setTotalPackages(len(all) - 1)
  1166. r.Stats.setState(StateProcessing)
  1167. go func() {
  1168. for _, a := range all {
  1169. if len(a.Deps()) == 0 {
  1170. queue <- a
  1171. }
  1172. }
  1173. }()
  1174. sr := newSubrunner(r, analyzers)
  1175. for item := range queue {
  1176. r.semaphore.Acquire()
  1177. go genericHandle(item, root, queue, &r.semaphore, func(act action) error {
  1178. return sr.do(act)
  1179. })
  1180. }
  1181. r.Stats.setState(StateFinalizing)
  1182. out := make([]Result, 0, len(all))
  1183. for _, item := range all {
  1184. if item.Package == nil {
  1185. continue
  1186. }
  1187. out = append(out, Result{
  1188. Package: item.Package,
  1189. Config: item.cfg,
  1190. Initial: !item.factsOnly,
  1191. Skipped: item.skipped,
  1192. Failed: item.failed,
  1193. Errors: item.errors,
  1194. results: item.results,
  1195. testData: item.testData,
  1196. })
  1197. }
  1198. return out, nil
  1199. }