By using SourceKit's `index` request to index the entire source file,
we can avoid having to make `cursor-info` requests for every candidate
token in the file, which scales linearly with the number of candiate
tokens.
For the Yams project, this approach improved the total SwiftLint run
time by 4.6x: 7.9 down from 36.8s.
The SourceKit index response doesn't have everything we need to identify
declarations, so we still need to make some `cursor-info` requests,
mostly to detect overrides: protocol conformances and parent class
overrides.
This approach ends up finding more unused declarations because the index
contains more declared USRs than can be found by calling `cursor-info`
on candidate tokens in a file.
---
Remove unused declaration in ArrayInitRule
---
Update package versions
In order for rules to collect arbitrary information about all files
being linted, a shared RuleStorage instance is defined in each command
and passed into the linter.
Linting now requires two "passes": once to call collect and populate the
storage (rules that are non-collecting do nothing here), and again to
call validate. The old Linter factory now creates a Prelinter, which can
collect for a file and produce a Linter that orchestrates all the
traditional validation/collection logic.
This design enforces that a file is only validated once it has been
collected; in turn, the file-visiting loop ensures that all files are
collected before the first is validated, so that the storage is fully
populated.
Use storage-backed correct method
Crash if storage for a rule is accessed prematurely
Key FileInfo by File
Rename Prelinter to Linter and Linter to CollectedLinter
Clean up rule protocols such that rule-facing storage methods are actually called
Make RuleStorage a reference type to solve mutating data races