-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Add --strict-baseline flag to fail lint when baselined violations are fixed #6614
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,6 +44,7 @@ package struct LintOrAnalyzeOptions { | |
| let reporter: String? | ||
| let baseline: String? | ||
| let writeBaseline: String? | ||
| let strictBaseline: Bool | ||
| let workingDirectory: String? | ||
| let quiet: Bool | ||
| let output: String? | ||
|
|
@@ -73,6 +74,7 @@ package struct LintOrAnalyzeOptions { | |
| reporter: String?, | ||
| baseline: String?, | ||
| writeBaseline: String?, | ||
| strictBaseline: Bool, | ||
| workingDirectory: String?, | ||
| quiet: Bool, | ||
| output: String?, | ||
|
|
@@ -101,6 +103,7 @@ package struct LintOrAnalyzeOptions { | |
| self.reporter = reporter | ||
| self.baseline = baseline | ||
| self.writeBaseline = writeBaseline | ||
| self.strictBaseline = strictBaseline | ||
| self.workingDirectory = workingDirectory | ||
| self.quiet = quiet | ||
| self.output = output | ||
|
|
@@ -150,6 +153,7 @@ package struct LintOrAnalyzeCommand { | |
| if let baselineOutputPath = options.writeBaseline ?? builder.configuration.writeBaseline { | ||
| try Baseline(violations: builder.unfilteredViolations).write(toPath: baselineOutputPath) | ||
| } | ||
| appendFixedBaselineViolations(builder: builder) | ||
| let numberOfSeriousViolations = try Signposts.record(name: "LintOrAnalyzeCommand.PostProcessViolations") { | ||
| try postProcessViolations(files: files, builder: builder) | ||
| } | ||
|
|
@@ -165,6 +169,7 @@ package struct LintOrAnalyzeCommand { | |
| let options = builder.options | ||
| let visitorMutationQueue = DispatchQueue(label: "io.realm.swiftlint.lintVisitorMutation") | ||
| let baseline = try baseline(options, builder.configuration) | ||
| builder.baseline = baseline | ||
| return try await builder.configuration.visitLintableFiles(options: options, cache: builder.cache, | ||
| storage: builder.storage) { linter in | ||
| let currentViolations: [StyleViolation] | ||
|
|
@@ -234,6 +239,22 @@ package struct LintOrAnalyzeCommand { | |
| return numberOfSeriousViolations | ||
| } | ||
|
|
||
| private static func appendFixedBaselineViolations(builder: LintOrAnalyzeResultBuilder) { | ||
| let options = builder.options | ||
| let configuration = builder.configuration | ||
| guard options.strictBaseline || configuration.strictBaseline, | ||
| let baseline = builder.baseline else { | ||
| return | ||
| } | ||
| let currentBaseline = Baseline(violations: builder.unfilteredViolations) | ||
| let fixedViolations = currentBaseline.compare(baseline).map(createFixedBaselineViolation) | ||
| guard fixedViolations.isNotEmpty else { | ||
| return | ||
| } | ||
| builder.violations += fixedViolations | ||
| builder.report(violations: fixedViolations, realtimeCondition: true) | ||
| } | ||
|
|
||
| private static func baseline(_ options: LintOrAnalyzeOptions, _ configuration: Configuration) throws -> Baseline? { | ||
| if let baselinePath = options.baseline ?? configuration.baseline { | ||
| do { | ||
|
|
@@ -266,6 +287,24 @@ package struct LintOrAnalyzeCommand { | |
| return numberOfWarningViolations >= warningThreshold | ||
| } | ||
|
|
||
| private static func createFixedBaselineViolation(fromBaseline violation: StyleViolation) -> StyleViolation { | ||
| let description = RuleDescription( | ||
| identifier: "fixed_baseline_violation", | ||
| name: "Fixed Baseline", | ||
| description: "A violation recorded in the baseline has been fixed or is no longer detected", | ||
| kind: .lint | ||
| ) | ||
| return StyleViolation( | ||
| ruleDescription: description, | ||
| severity: .error, | ||
| location: violation.location, | ||
| reason: """ | ||
| Violation previously recorded in the baseline for '\(violation.ruleIdentifier)' is no longer \ | ||
| detected. Regenerate the baseline to acknowledge this fix | ||
| """ | ||
| ) | ||
|
Comment on lines
+297
to
+305
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @SimplyDanny is there a more idomatic way to say "baseline is no longer valid"?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. baseline is "stale" perhaps, but that still doesn't feel quite right. |
||
| } | ||
|
|
||
| private static func createThresholdViolation(threshold: Int) -> StyleViolation { | ||
| let description = RuleDescription( | ||
| identifier: "warning_threshold", | ||
|
|
@@ -374,6 +413,7 @@ private class LintOrAnalyzeResultBuilder { | |
| var unfilteredViolations = [StyleViolation]() | ||
| /// The violations to be reported, possibly filtered by a baseline, plus any threshold violations. | ||
| var violations = [StyleViolation]() | ||
| var baseline: Baseline? | ||
| let storage = RuleStorage() | ||
| let configuration: Configuration | ||
| let reporter: any Reporter.Type | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,6 +46,12 @@ struct LintOrAnalyzeArguments: ParsableArguments { | |
| var baseline: String? | ||
| @Option(help: "The path to save detected violations to as a new baseline.") | ||
| var writeBaseline: String? | ||
| @Flag(help: """ | ||
| Fail linting if violations previously recorded in the baseline are no longer \ | ||
| detected. Encourages keeping the baseline up-to-date by regenerating it \ | ||
| once baselined violations have been fixed. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels a little verbose. |
||
| """) | ||
| var strictBaseline = false | ||
| @Option(help: "The working directory to use when running SwiftLint.") | ||
| var workingDirectory: String? | ||
| @Option(help: "The file where violations should be saved. Prints to stdout by default.") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So reporting these as violations is very convenient, but the
fixed_baseline_violation"pseudo-rule" is not really a rule - for example, I can't// swiftlint:disable fixed_baseline_violationat the top of a file (andfixed_baseline_violationisn't easily matched up tostrict_baseline).I wonder if these should be reported as
Issue's instead, something likeIssue.fixedBaselineViolation(violation).print()