Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add coverage statistics #5907

Open
wants to merge 62 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
6f737e4
Initial implementation
mildm8nnered Dec 22, 2024
3943171
Improved rule counts
mildm8nnered Dec 22, 2024
f7f2d47
Started to add tests
mildm8nnered Dec 22, 2024
15a73b8
Added report_coverage configuration file option
mildm8nnered Dec 22, 2024
8db3dbb
Added unit tests
mildm8nnered Dec 22, 2024
5fdab5c
SwiftLint fixes
mildm8nnered Dec 22, 2024
2ecd7a3
Unit test fixes
mildm8nnered Dec 22, 2024
5eb613a
More tidyup
mildm8nnered Dec 23, 2024
107bd40
Try and account for custom rules as well
mildm8nnered Dec 23, 2024
e86d70f
Added disable all step
mildm8nnered Dec 23, 2024
eea708e
Added documentation
mildm8nnered Dec 23, 2024
fa33541
tweak
mildm8nnered Dec 23, 2024
ab0d2cc
Tweaks
mildm8nnered Dec 23, 2024
753aae4
Use the linters rules, not the top level configuration
mildm8nnered Dec 23, 2024
529e447
Improved custom rule coverage
mildm8nnered Dec 23, 2024
43595af
Always enable coverage (so we can use the CI speed benchmarks)
mildm8nnered Dec 23, 2024
3a45293
Linter fixes
mildm8nnered Dec 23, 2024
28a4c92
Improvements
mildm8nnered Dec 23, 2024
30f9b67
Disable region caching
mildm8nnered Dec 23, 2024
55c7689
Remove cached regions temporarily
mildm8nnered Dec 23, 2024
e2615be
Tidyup
mildm8nnered Dec 24, 2024
7c22f59
Tweaks
mildm8nnered Dec 24, 2024
c466e6f
Refactor
mildm8nnered Dec 24, 2024
e3257a3
Cleanup
mildm8nnered Dec 24, 2024
4baf30d
Sigh
mildm8nnered Dec 24, 2024
4ad17d4
Improved custom_rules handling
mildm8nnered Dec 24, 2024
9eff008
Removed old caching
mildm8nnered Dec 24, 2024
ae883a7
Added regionsCaching
mildm8nnered Dec 24, 2024
589a54e
Refactoring
mildm8nnered Dec 24, 2024
51872e6
refactor
mildm8nnered Dec 24, 2024
8a4b35e
That was a struggle
mildm8nnered Dec 24, 2024
82107af
Refactoring
mildm8nnered Dec 24, 2024
4791dce
Tweaked tests more
mildm8nnered Dec 24, 2024
9d2d922
More cleanup
mildm8nnered Dec 24, 2024
a341746
Refactored
mildm8nnered Dec 24, 2024
560afad
Refactor
mildm8nnered Dec 24, 2024
c1ab5c0
More refactoring
mildm8nnered Dec 24, 2024
72b3b68
More tweaking
mildm8nnered Dec 24, 2024
0aaa28d
Refactoring
mildm8nnered Dec 24, 2024
1eb1e70
Refactored tests
mildm8nnered Dec 25, 2024
f0a9095
Refactored tests
mildm8nnered Dec 25, 2024
1c085f6
Handle special case where multiple identifiers are specified for a si…
mildm8nnered Dec 25, 2024
dbc77a9
But broken
mildm8nnered Dec 25, 2024
c1f8a0b
More refactoring
mildm8nnered Dec 25, 2024
e47179a
Fixed some more cases
mildm8nnered Dec 25, 2024
547bb43
Refactor
mildm8nnered Dec 25, 2024
27cdc5b
Rewrote the documentation
mildm8nnered Dec 26, 2024
0826600
Removed some blank lines
mildm8nnered Dec 26, 2024
01c31f3
added report_coverage
mildm8nnered Dec 26, 2024
b39123d
Added more docs
mildm8nnered Dec 26, 2024
34f4f8c
More unit test refactoring
mildm8nnered Dec 26, 2024
1955d07
Autocorrects
mildm8nnered Dec 26, 2024
21a2b8f
More refactoring
mildm8nnered Dec 26, 2024
138e16e
Renaming
mildm8nnered Dec 26, 2024
0cc259f
Use default values
mildm8nnered Dec 26, 2024
38cad95
More test refactoring
mildm8nnered Dec 26, 2024
9ce3867
Linter fixes
mildm8nnered Dec 26, 2024
58fe846
Fixed nesting test
mildm8nnered Dec 26, 2024
21b1c2b
blank -> empty
mildm8nnered Dec 27, 2024
88549ff
added
mildm8nnered Dec 27, 2024
6c122f7
Slight refactor
mildm8nnered Dec 27, 2024
61d61b5
tweaked
mildm8nnered Dec 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@

#### Experimental

* None.
* Adds a new `--report-coverage` command line option for the `lint` and `analyze` subcommands, and an
equivalent `report_coverage` configuration file setting. Coverage is measured against enabled
rules (reflecting disablement of enabled rules via `swiftlint:disable`), and also against all linter
or analyzer rules (reflecting the actual usage of Swiftlint versus its potential).
[Martin Redington](https://github.com/mildm8nnered)
[#5907](https://github.com/realm/SwiftLint/issues/5907)

#### Enhancements

Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,9 @@ write_baseline: Baseline.json
# If true, SwiftLint will check for updates after linting or analyzing.
check_for_updates: true

# If true, SwiftLint will report coverage statistics after linting or analyzing.
report_coverage: true

# configurable rules can be customized from this configuration file
# binary rules can set their severity level
force_cast: warning # implicitly
Expand Down
7 changes: 7 additions & 0 deletions Source/SwiftLintCore/Extensions/SwiftLintFile+Cache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ private let commandsCache = Cache { file -> [Command] in
return CommandVisitor(locationConverter: file.locationConverter)
.walk(file: file, handler: \.commands)
}
private let regionsCache = Cache { file -> [Region] in
file.regions()
}
private let syntaxMapCache = Cache { file in
responseCache.get(file).map { SwiftLintSyntaxMap(value: SyntaxMap(sourceKitResponse: $0)) }
}
Expand Down Expand Up @@ -168,6 +171,8 @@ extension SwiftLintFile {

public var invalidCommands: [Command] { commandsCache.get(self).filter { !$0.isValid } }

public var regions: [Region] { regionsCache.get(self) }

public var syntaxTokensByLines: [[SwiftLintSyntaxToken]] {
guard let syntaxTokensByLines = syntaxTokensByLinesCache.get(self) else {
if let handler = assertHandler {
Expand Down Expand Up @@ -204,6 +209,7 @@ extension SwiftLintFile {
foldedSyntaxTreeCache.invalidate(self)
locationConverterCache.invalidate(self)
commandsCache.invalidate(self)
regionsCache.invalidate(self)
linesWithTokensCache.invalidate(self)
}

Expand All @@ -219,6 +225,7 @@ extension SwiftLintFile {
foldedSyntaxTreeCache.clear()
locationConverterCache.clear()
commandsCache.clear()
regionsCache.clear()
linesWithTokensCache.clear()
}
}
Expand Down
2 changes: 1 addition & 1 deletion Source/SwiftLintCore/Extensions/SwiftLintFile+Regex.swift
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ extension SwiftLintFile {
}

public func ruleEnabled(violatingRanges: [NSRange], for rule: some Rule) -> [NSRange] {
let fileRegions = regions()
let fileRegions = regions
if fileRegions.isEmpty { return violatingRanges }
return violatingRanges.filter { range in
let region = fileRegions.first {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public extension SwiftSyntaxCorrectableRule {
}

let locationConverter = file.locationConverter
let disabledRegions = file.regions()
let disabledRegions = file.regions
.filter { $0.areRulesDisabled(ruleIDs: Self.description.allIdentifiers) }
.compactMap { $0.toSourceRange(locationConverter: locationConverter) }

Expand Down Expand Up @@ -91,7 +91,7 @@ open class ViolationsSyntaxRewriter<Configuration: RuleConfiguration>: SyntaxRew
public lazy var locationConverter = file.locationConverter
/// The regions in the traversed file that are disabled by a command.
public lazy var disabledRegions = {
file.regions()
file.regions
.filter { $0.areRulesDisabled(ruleIDs: Configuration.Parent.description.allIdentifiers) }
.compactMap { $0.toSourceRange(locationConverter: locationConverter) }
}()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ extension Configuration {
excludedPaths: mergedIncludedAndExcluded.excludedPaths,
indentation: childConfiguration.indentation,
warningThreshold: mergedWarningTreshold(with: childConfiguration),
reportCoverage: childConfiguration.reportCoverage,
reporter: reporter,
cachePath: cachePath,
allowZeroLintableFiles: childConfiguration.allowZeroLintableFiles,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extension Configuration {
case excluded = "excluded"
case included = "included"
case optInRules = "opt_in_rules"
case reportCoverage = "report_coverage"
case reporter = "reporter"
case swiftlintVersion = "swiftlint_version"
case warningThreshold = "warning_threshold"
Expand Down Expand Up @@ -99,6 +100,7 @@ extension Configuration {
excludedPaths: defaultStringArray(dict[Key.excluded.rawValue]),
indentation: Self.getIndentationLogIfInvalid(from: dict),
warningThreshold: dict[Key.warningThreshold.rawValue] as? Int,
reportCoverage: dict[Key.reportCoverage.rawValue] as? Bool ?? false,
reporter: dict[Key.reporter.rawValue] as? String ?? XcodeReporter.identifier,
cachePath: cachePath ?? dict[Key.cachePath.rawValue] as? String,
pinnedVersion: dict[Key.swiftlintVersion.rawValue].map { ($0 as? String) ?? String(describing: $0) },
Expand Down
15 changes: 13 additions & 2 deletions Source/SwiftLintFramework/Configuration/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ public struct Configuration {
/// The threshold for the number of warnings to tolerate before treating the lint as having failed.
public let warningThreshold: Int?

/// Report coverage statistics when linting or analyzing.
public let reportCoverage: Bool

/// The identifier for the `Reporter` to use to report style violations.
public let reporter: String?

Expand All @@ -47,7 +50,7 @@ public struct Configuration {
/// The path to write a baseline to.
public let writeBaseline: String?

/// Check for updates.
/// Check for updates after linting or analyzing.`
public let checkForUpdates: Bool

/// This value is `true` iff the `--config` parameter was used to specify (a) configuration file(s)
Expand Down Expand Up @@ -82,6 +85,7 @@ public struct Configuration {
excludedPaths: [String],
indentation: IndentationStyle,
warningThreshold: Int?,
reportCoverage: Bool,
reporter: String?,
cachePath: String?,
allowZeroLintableFiles: Bool,
Expand All @@ -97,6 +101,7 @@ public struct Configuration {
self.excludedPaths = excludedPaths
self.indentation = indentation
self.warningThreshold = warningThreshold
self.reportCoverage = reportCoverage
self.reporter = reporter
self.cachePath = cachePath
self.allowZeroLintableFiles = allowZeroLintableFiles
Expand All @@ -117,6 +122,7 @@ public struct Configuration {
excludedPaths = configuration.excludedPaths
indentation = configuration.indentation
warningThreshold = configuration.warningThreshold
reportCoverage = configuration.reportCoverage
reporter = configuration.reporter
basedOnCustomConfigurationFiles = configuration.basedOnCustomConfigurationFiles
cachePath = configuration.cachePath
Expand All @@ -143,6 +149,7 @@ public struct Configuration {
/// - parameter indentation: The style to use when indenting Swift source code.
/// - parameter warningThreshold: The threshold for the number of warnings to tolerate before treating the
/// lint as having failed.
/// - parameter reportCoverage: Report coverage data after linting or analyzing.
/// - parameter reporter: The identifier for the `Reporter` to use to report style violations.
/// - parameter cachePath: The location of the persisted cache to use with this configuration.
/// - parameter pinnedVersion: The SwiftLint version defined in this configuration.
Expand All @@ -152,7 +159,7 @@ public struct Configuration {
/// - parameter lenient: Treat errors as warnings.
/// - parameter baseline: The path to read a baseline from.
/// - parameter writeBaseline: The path to write a baseline to.
/// - parameter checkForUpdates: Check for updates to SwiftLint.
/// - parameter checkForUpdates: Check for updates to SwiftLint after linting or analyzing.
package init(
rulesMode: RulesMode = .defaultConfiguration(disabled: [], optIn: []),
allRulesWrapped: [ConfigurationRuleWrapper]? = nil,
Expand All @@ -162,6 +169,7 @@ public struct Configuration {
excludedPaths: [String] = [],
indentation: IndentationStyle = .default,
warningThreshold: Int? = nil,
reportCoverage: Bool = false,
reporter: String? = nil,
cachePath: String? = nil,
pinnedVersion: String? = nil,
Expand Down Expand Up @@ -193,6 +201,7 @@ public struct Configuration {
excludedPaths: excludedPaths,
indentation: indentation,
warningThreshold: warningThreshold,
reportCoverage: reportCoverage,
reporter: reporter,
cachePath: cachePath,
allowZeroLintableFiles: allowZeroLintableFiles,
Expand Down Expand Up @@ -310,6 +319,7 @@ extension Configuration: Hashable {
hasher.combine(excludedPaths)
hasher.combine(indentation)
hasher.combine(warningThreshold)
hasher.combine(reportCoverage)
hasher.combine(reporter)
hasher.combine(allowZeroLintableFiles)
hasher.combine(strict)
Expand All @@ -328,6 +338,7 @@ extension Configuration: Hashable {
lhs.excludedPaths == rhs.excludedPaths &&
lhs.indentation == rhs.indentation &&
lhs.warningThreshold == rhs.warningThreshold &&
lhs.reportCoverage == rhs.reportCoverage &&
lhs.reporter == rhs.reporter &&
lhs.basedOnCustomConfigurationFiles == rhs.basedOnCustomConfigurationFiles &&
lhs.cachePath == rhs.cachePath &&
Expand Down
Loading