Skip to content

Commit cad7b65

Browse files
committed
Output a warning for unknown config rules
**Summary**: - Helps developers surface any errors and typos in their `.swift-format` config files by showing a warning when running `swift-format` if the configuration includes invalid rules. - The actual check is in `Frontend.swift`. - The dictionary of rules for verification is in `RuleRegistry`, which is made `public` to be able to import it in `swift-format` target. **Motivation**: - Closes #607
1 parent 0ebb3c8 commit cad7b65

File tree

4 files changed

+34
-5
lines changed

4 files changed

+34
-5
lines changed

Sources/SwiftFormatConfiguration/RuleRegistry+Generated.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
// This file is automatically generated with generate-pipeline. Do Not Edit!
1414

15-
enum RuleRegistry {
16-
static let rules: [String: Bool] = [
15+
public enum RuleRegistry {
16+
public static let rules: [String: Bool] = [
1717
"AllPublicDeclarationsHaveDocumentation": false,
1818
"AlwaysUseLowerCamelCase": true,
1919
"AmbiguousTrailingClosureOverload": true,

Sources/generate-pipeline/RuleRegistryGenerator.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ final class RuleRegistryGenerator: FileGenerator {
4040
4141
// This file is automatically generated with generate-pipeline. Do Not Edit!
4242
43-
enum RuleRegistry {
44-
static let rules: [String: Bool] = [
43+
publc enum RuleRegistry {
44+
public static let rules: [String: Bool] = [
4545
4646
"""
4747
)

Sources/swift-format/Frontend/Frontend.swift

+16-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ class Frontend {
181181
// loaded. (Do not try to fall back to a path inferred from the source file path.)
182182
if let configurationFileURL = configurationFileURL {
183183
do {
184-
return try configurationLoader.configuration(at: configurationFileURL)
184+
let configuration = try configurationLoader.configuration(at: configurationFileURL)
185+
self.verifyConfigurationRules(for: configuration)
186+
return configuration
185187
} catch {
186188
diagnosticsEngine.emitError("Unable to read configuration: \(error.localizedDescription)")
187189
return nil
@@ -193,6 +195,7 @@ class Frontend {
193195
if let swiftFileURL = swiftFileURL {
194196
do {
195197
if let configuration = try configurationLoader.configuration(forSwiftFileAt: swiftFileURL) {
198+
self.verifyConfigurationRules(for: configuration)
196199
return configuration
197200
}
198201
// Fall through to the default return at the end of the function.
@@ -208,4 +211,16 @@ class Frontend {
208211
// default configuration.
209212
return Configuration()
210213
}
214+
215+
/// Checks if all the rules in the given configuration are supported by the registry.
216+
/// If there are any rules that are not supported, they are emitted as a warning.
217+
private func verifyConfigurationRules(for configuration: Configuration) -> Void {
218+
// If any rules in the decoded configuration are not supported by the registry,
219+
// emit them into the diagnosticsEngine as warnings.
220+
// That way they will be printed out, but we'll continue execution on the valid rules.
221+
let invalidRules = configuration.rules.filter { !RuleRegistry.rules.keys.contains($0.key) }
222+
if !invalidRules.isEmpty {
223+
diagnosticsEngine.emitWarning("Configuration contains an unsupported rule: \(invalidRules.keys.joined(separator: ", "))", location: nil)
224+
}
225+
}
211226
}

Sources/swift-format/Utilities/DiagnosticsEngine.swift

+14
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,20 @@ final class DiagnosticsEngine {
6565
message: message))
6666
}
6767

68+
/// Emits a generic warning message.
69+
///
70+
/// - Parameters:
71+
/// - message: The message associated with the error.
72+
/// - location: The location in the source code associated with the error, or nil if there is no
73+
/// location associated with the error.
74+
func emitWarning(_ message: String, location: SourceLocation? = nil) {
75+
emit(
76+
Diagnostic(
77+
severity: .warning,
78+
location: location.map(Diagnostic.Location.init),
79+
message: message))
80+
}
81+
6882
/// Emits a finding from the linter and any of its associated notes as diagnostics.
6983
///
7084
/// - Parameter finding: The finding that should be emitted.

0 commit comments

Comments
 (0)