Analyze applies the set of enabled analyzers to the packages in the pkgs map, and returns their diagnostics. Notifications of progress may be sent to the optional reporter.
(ctx context.Context, pkgs map[PackageID]*metadata.Package, reporter *progress.Tracker)
| 112 | // |
| 113 | // Notifications of progress may be sent to the optional reporter. |
| 114 | func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Package, reporter *progress.Tracker) ([]*Diagnostic, error) { |
| 115 | start := time.Now() // for progress reporting |
| 116 | |
| 117 | var tagStr string // sorted comma-separated list of PackageIDs |
| 118 | { |
| 119 | keys := make([]string, 0, len(pkgs)) |
| 120 | for id := range pkgs { |
| 121 | keys = append(keys, string(id)) |
| 122 | } |
| 123 | sort.Strings(keys) |
| 124 | tagStr = strings.Join(keys, ",") |
| 125 | } |
| 126 | ctx, done := event.Start(ctx, "snapshot.Analyze", label.Package.Of(tagStr)) |
| 127 | defer done() |
| 128 | |
| 129 | // Filter and sort enabled root analyzers. |
| 130 | // A disabled analyzer may still be run if required by another. |
| 131 | var ( |
| 132 | toSrc = make(map[*analysis.Analyzer]*settings.Analyzer) |
| 133 | enabledAnalyzers []*analysis.Analyzer // enabled subset + transitive requirements |
| 134 | ) |
| 135 | for _, a := range settings.AllAnalyzers { |
| 136 | if a.Enabled(s.Options()) { |
| 137 | toSrc[a.Analyzer()] = a |
| 138 | enabledAnalyzers = append(enabledAnalyzers, a.Analyzer()) |
| 139 | } |
| 140 | } |
| 141 | sort.Slice(enabledAnalyzers, func(i, j int) bool { |
| 142 | return enabledAnalyzers[i].Name < enabledAnalyzers[j].Name |
| 143 | }) |
| 144 | |
| 145 | enabledAnalyzers = requiredAnalyzers(enabledAnalyzers) |
| 146 | |
| 147 | // Perform basic sanity checks. |
| 148 | // (Ideally we would do this only once.) |
| 149 | if err := analysis.Validate(enabledAnalyzers); err != nil { |
| 150 | return nil, fmt.Errorf("invalid analyzer configuration: %v", err) |
| 151 | } |
| 152 | |
| 153 | stableNames := make(map[*analysis.Analyzer]string) |
| 154 | |
| 155 | var facty []*analysis.Analyzer // facty subset of enabled + transitive requirements |
| 156 | for _, a := range enabledAnalyzers { |
| 157 | // TODO(adonovan): reject duplicate stable names (very unlikely). |
| 158 | stableNames[a] = stableName(a) |
| 159 | |
| 160 | // Register fact types of all required analyzers. |
| 161 | if len(a.FactTypes) > 0 { |
| 162 | facty = append(facty, a) |
| 163 | for _, f := range a.FactTypes { |
| 164 | gob.Register(f) // <2us |
| 165 | } |
| 166 | } |
| 167 | } |
| 168 | facty = requiredAnalyzers(facty) |
| 169 | |
| 170 | batch, release := s.acquireTypeChecking() |
| 171 | defer release() |
no test coverage detected