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 strict configuration file setting #5226

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@
[Martin Redington](https://github.com/mildm8nnered)
[#5215](https://github.com/realm/SwiftLint/issues/5215)

* Adds a `strict` configuration file setting, equivalent to the `--strict`
command line option.
[Martin Redington](https://github.com/mildm8nnered)
[#5226](https://github.com/realm/SwiftLint/issues/5226)

#### Bug Fixes

* Respect grapheme clusters in counting the number of characters in the `collection_alignment` rule.
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,9 @@ excluded: # case-sensitive paths to ignore during linting. Takes precedence over
# If true, SwiftLint will not fail if no lintable files are found.
allow_zero_lintable_files: false

# If true, SwiftLint will treat all warnings as errors.
strict: false

# configurable rules can be customized from this configuration file
# binary rules can set their severity level
force_cast: warning # implicitly
Expand Down
3 changes: 2 additions & 1 deletion Source/SwiftLintCore/Extensions/Configuration+Merging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ extension Configuration {
warningThreshold: mergedWarningTreshold(with: childConfiguration),
reporter: reporter,
cachePath: cachePath,
allowZeroLintableFiles: childConfiguration.allowZeroLintableFiles
allowZeroLintableFiles: childConfiguration.allowZeroLintableFiles,
strict: childConfiguration.strict
)
}

Expand Down
4 changes: 3 additions & 1 deletion Source/SwiftLintCore/Extensions/Configuration+Parsing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ extension Configuration {
case indentation = "indentation"
case analyzerRules = "analyzer_rules"
case allowZeroLintableFiles = "allow_zero_lintable_files"
case strict = "strict"
case childConfig = "child_config"
case parentConfig = "parent_config"
case remoteConfigTimeout = "remote_timeout"
Expand Down Expand Up @@ -88,7 +89,8 @@ extension Configuration {
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) },
allowZeroLintableFiles: dict[Key.allowZeroLintableFiles.rawValue] as? Bool ?? false
allowZeroLintableFiles: dict[Key.allowZeroLintableFiles.rawValue] as? Bool ?? false,
strict: dict[Key.strict.rawValue] as? Bool ?? false
)
}

Expand Down
19 changes: 15 additions & 4 deletions Source/SwiftLintCore/Models/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ public struct Configuration {
/// Allow or disallow SwiftLint to exit successfully when passed only ignored or unlintable files.
public let allowZeroLintableFiles: Bool

/// Treat warnings as errors
public let strict: Bool

/// This value is `true` iff the `--config` parameter was used to specify (a) configuration file(s)
/// In particular, this means that the value is also `true` if the `--config` parameter
/// was used to explicitly specify the default `.swiftlint.yml` as the configuration file
Expand Down Expand Up @@ -69,7 +72,8 @@ public struct Configuration {
warningThreshold: Int?,
reporter: String,
cachePath: String?,
allowZeroLintableFiles: Bool
allowZeroLintableFiles: Bool,
strict: Bool
) {
self.rulesWrapper = rulesWrapper
self.fileGraph = fileGraph
Expand All @@ -80,6 +84,7 @@ public struct Configuration {
self.reporter = reporter
self.cachePath = cachePath
self.allowZeroLintableFiles = allowZeroLintableFiles
self.strict = strict
}

/// Creates a Configuration by copying an existing configuration.
Expand All @@ -96,6 +101,7 @@ public struct Configuration {
basedOnCustomConfigurationFiles = configuration.basedOnCustomConfigurationFiles
cachePath = configuration.cachePath
allowZeroLintableFiles = configuration.allowZeroLintableFiles
strict = configuration.strict
}

/// Creates a `Configuration` by specifying its properties directly,
Expand All @@ -117,6 +123,7 @@ public struct Configuration {
/// - parameter cachePath: The location of the persisted cache to use whith this configuration.
/// - parameter pinnedVersion: The SwiftLint version defined in this configuration.
/// - parameter allowZeroLintableFiles: Allow SwiftLint to exit successfully when passed ignored or unlintable files
/// - parameter strict: Treat warnings as errors
@_spi(TestHelper)
public init(
rulesMode: RulesMode = .default(disabled: [], optIn: []),
Expand All @@ -130,7 +137,8 @@ public struct Configuration {
reporter: String? = nil,
cachePath: String? = nil,
pinnedVersion: String? = nil,
allowZeroLintableFiles: Bool = false
allowZeroLintableFiles: Bool = false,
strict: Bool = false
) {
if let pinnedVersion, pinnedVersion != Version.current.value {
queuedPrintError(
Expand All @@ -155,7 +163,8 @@ public struct Configuration {
warningThreshold: warningThreshold,
reporter: reporter ?? XcodeReporter.identifier,
cachePath: cachePath,
allowZeroLintableFiles: allowZeroLintableFiles
allowZeroLintableFiles: allowZeroLintableFiles,
strict: strict
)
}

Expand Down Expand Up @@ -259,6 +268,7 @@ extension Configuration: Hashable {
hasher.combine(warningThreshold)
hasher.combine(reporter)
hasher.combine(allowZeroLintableFiles)
hasher.combine(strict)
hasher.combine(basedOnCustomConfigurationFiles)
hasher.combine(cachePath)
hasher.combine(rules.map { type(of: $0).description.identifier })
Expand All @@ -275,7 +285,8 @@ extension Configuration: Hashable {
lhs.cachePath == rhs.cachePath &&
lhs.rules == rhs.rules &&
lhs.fileGraph == rhs.fileGraph &&
lhs.allowZeroLintableFiles == rhs.allowZeroLintableFiles
lhs.allowZeroLintableFiles == rhs.allowZeroLintableFiles &&
lhs.strict == rhs.strict
}
}

Expand Down
23 changes: 18 additions & 5 deletions Source/swiftlint/Helpers/LintOrAnalyzeCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,22 @@ struct LintOrAnalyzeCommand {
let start = Date()
let (violationsBeforeLeniency, currentRuleTimes) = linter
.styleViolationsAndRuleTimes(using: builder.storage)
currentViolations = applyLeniency(options: options, violations: violationsBeforeLeniency)
currentViolations = applyLeniency(
options: options,
strict: builder.configuration.strict,
violations: violationsBeforeLeniency
)
visitorMutationQueue.sync {
builder.fileBenchmark.record(file: linter.file, from: start)
currentRuleTimes.forEach { builder.ruleBenchmark.record(id: $0, time: $1) }
builder.violations += currentViolations
}
} else {
currentViolations = applyLeniency(options: options,
violations: linter.styleViolations(using: builder.storage))
currentViolations = applyLeniency(
options: options,
strict: builder.configuration.strict,
violations: linter.styleViolations(using: builder.storage)
)
visitorMutationQueue.sync {
builder.violations += currentViolations
}
Expand Down Expand Up @@ -139,8 +146,14 @@ struct LintOrAnalyzeCommand {
reason: "Number of warnings exceeded threshold of \(threshold).")
}

private static func applyLeniency(options: LintOrAnalyzeOptions, violations: [StyleViolation]) -> [StyleViolation] {
switch (options.lenient, options.strict) {
private static func applyLeniency(
options: LintOrAnalyzeOptions,
strict: Bool,
violations: [StyleViolation]
) -> [StyleViolation] {
let strict = (strict && !options.lenient) || options.strict

switch (options.lenient, strict) {
case (false, false):
return violations

Expand Down
9 changes: 8 additions & 1 deletion Tests/SwiftLintFrameworkTests/ConfigurationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class ConfigurationTests: SwiftLintTestCase {
XCTAssertEqual(config.reporter, "xcode")
XCTAssertEqual(reporterFrom(identifier: config.reporter).identifier, "xcode")
XCTAssertFalse(config.allowZeroLintableFiles)
XCTAssertFalse(config.strict)
}

func testInitWithRelativePathAndRootPath() {
Expand All @@ -69,6 +70,7 @@ class ConfigurationTests: SwiftLintTestCase {
XCTAssertEqual(config.indentation, expectedConfig.indentation)
XCTAssertEqual(config.reporter, expectedConfig.reporter)
XCTAssertTrue(config.allowZeroLintableFiles)
XCTAssertTrue(config.strict)
}

func testEnableAllRulesConfiguration() throws {
Expand Down Expand Up @@ -100,7 +102,7 @@ class ConfigurationTests: SwiftLintTestCase {

let config = try Configuration(dict: ["only_rules": only, "custom_rules": customRules])
guard let resultingCustomRules = config.rules.first(where: { $0 is CustomRules }) as? CustomRules
else {
else {
XCTFail("Custom rules are expected to be present")
return
}
Expand Down Expand Up @@ -421,6 +423,11 @@ class ConfigurationTests: SwiftLintTestCase {
let configuration = try Configuration(dict: ["allow_zero_lintable_files": true])
XCTAssertTrue(configuration.allowZeroLintableFiles)
}

func testStrict() throws {
let configuration = try Configuration(dict: ["strict": true])
XCTAssertTrue(configuration.strict)
}
}

// MARK: - ExcludeByPrefix option tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ excluded:
line_length: 10000000000
reporter: "json"
allow_zero_lintable_files: true
strict: true