mirror of
https://github.com/nicklockwood/SwiftFormat.git
synced 2026-05-17 10:30:35 +00:00
Add unknown-rules option
This commit is contained in:
+19
-1
@@ -324,13 +324,15 @@ func parseCommaDelimitedList(_ string: String) -> [String] {
|
||||
/// Parse a comma-delimited string into an array of rules
|
||||
let allRules = Set(FormatRules.all.map(\.name))
|
||||
let defaultRules = Set(FormatRules.default.map(\.name))
|
||||
func parseRules(_ rules: String) throws -> [String] {
|
||||
func parseRules(_ rules: String, ignoreUnknown: Bool) throws -> [String] {
|
||||
try parseCommaDelimitedList(rules).flatMap { proposedName -> [String] in
|
||||
let lowercaseName = proposedName.lowercased()
|
||||
if let name = allRules.first(where: { $0.lowercased() == lowercaseName }) {
|
||||
return [name]
|
||||
} else if lowercaseName == "all" {
|
||||
return FormatRules.all.compactMap { $0.isDeprecated ? nil : $0.name }
|
||||
} else if ignoreUnknown {
|
||||
return []
|
||||
}
|
||||
if Descriptors.all.contains(where: { $0.argumentName == lowercaseName }) {
|
||||
for rule in FormatRules.all where rule.options.contains(lowercaseName) {
|
||||
@@ -348,6 +350,18 @@ func parseRules(_ rules: String) throws -> [String] {
|
||||
}
|
||||
}
|
||||
|
||||
func curryParseRules(config: [String: String]) -> (String) throws -> [String] {
|
||||
{
|
||||
try parseRules($0, ignoreUnknown: config["unknown-rules"].map {
|
||||
switch $0 {
|
||||
case "ignore": return true
|
||||
case "error": return false
|
||||
default: throw FormatError.options("Unknown value '\($0)' for --unknown-rules option")
|
||||
}
|
||||
} ?? false)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse single file path, disallowing globs or commas
|
||||
func parsePath(_ path: String, for argument: String, in directory: String) throws -> URL {
|
||||
let expandedPath = expandPath(path, in: directory)
|
||||
@@ -369,6 +383,7 @@ func parsePaths(_ paths: String, in directory: String) throws -> [URL] {
|
||||
|
||||
/// Merge two dictionaries of arguments
|
||||
func mergeArguments(_ args: [String: String], into config: [String: String]) throws -> [String: String] {
|
||||
let parseRules = curryParseRules(config: config)
|
||||
var input = config
|
||||
var output = args
|
||||
// Merge excluded urls
|
||||
@@ -661,6 +676,7 @@ private func processOption(_ key: String,
|
||||
|
||||
/// Parse rule names from arguments
|
||||
public func rulesFor(_ args: [String: String], lint: Bool, initial: Set<String>? = nil) throws -> Set<String> {
|
||||
let parseRules = curryParseRules(config: args)
|
||||
var rules = initial ?? allRules
|
||||
|
||||
if let specifiedRules = try args["rules"].map({ try Set(parseRules($0)) }) {
|
||||
@@ -779,6 +795,7 @@ func warningsForArguments(_ args: [String: String], ignoreUnusedOptions: Bool =
|
||||
warnings.append("--\(option.argumentName) option is deprecated. \(message)")
|
||||
}
|
||||
}
|
||||
let parseRules = curryParseRules(config: args)
|
||||
for name in Set(rulesArguments.flatMap { (try? args[$0].map(parseRules) ?? []) ?? [] }) {
|
||||
if let message = FormatRules.byName[name]?.deprecationMessage {
|
||||
warnings.append("\(name) rule is deprecated. \(message)")
|
||||
@@ -837,6 +854,7 @@ let commandLineArguments = [
|
||||
"strict",
|
||||
"verbose",
|
||||
"quiet",
|
||||
"unknown-rules",
|
||||
"reporter",
|
||||
"report",
|
||||
// Misc
|
||||
|
||||
@@ -208,6 +208,7 @@ func printHelp(as type: CLI.OutputType) {
|
||||
--conflict-markers \(stripMarkdown(Descriptors.ignoreConflictMarkers.help))
|
||||
--swift-version \(stripMarkdown(Descriptors.swiftVersion.help))
|
||||
--language-mode \(stripMarkdown(Descriptors.languageMode.help))
|
||||
--unknown-rules How unknown rules are handled: "error" (default) or "ignore"
|
||||
--min-version The minimum SwiftFormat version to be used for these files
|
||||
--cache Path to cache file, or "clear" or "ignore" the default cache
|
||||
--dry-run Run in "dry" mode (without actually changing any files)
|
||||
@@ -492,7 +493,7 @@ func processArguments(_ args: [String], environment: [String: String] = [:], in
|
||||
}
|
||||
|
||||
// Show rule info
|
||||
if let names = try args["rule-info"].map(parseRules) {
|
||||
if let names = try args["rule-info"].map({ try parseRules($0, ignoreUnknown: false) }) {
|
||||
let names = names.isEmpty ? allRules.sorted() : names.sorted()
|
||||
for name in names {
|
||||
try printRuleInfo(for: name, as: .content)
|
||||
|
||||
+25
-15
@@ -660,7 +660,7 @@ class ArgumentsTests: XCTestCase {
|
||||
let args = ["rules": "braces,fileHeader"]
|
||||
let config = ["rules": "consecutiveSpaces,braces"]
|
||||
let result = try mergeArguments(args, into: config)
|
||||
let rules = try parseRules(result["rules"]!)
|
||||
let rules = try parseRules(result["rules"]!, ignoreUnknown: false)
|
||||
XCTAssertEqual(rules, ["braces", "fileHeader"])
|
||||
}
|
||||
|
||||
@@ -668,7 +668,7 @@ class ArgumentsTests: XCTestCase {
|
||||
let args = ["rules": ""]
|
||||
let config = ["rules": "consecutiveSpaces,braces"]
|
||||
let result = try mergeArguments(args, into: config)
|
||||
let rules = try parseRules(result["rules"]!)
|
||||
let rules = try parseRules(result["rules"]!, ignoreUnknown: false)
|
||||
XCTAssertEqual(Set(rules), Set(["braces", "consecutiveSpaces"]))
|
||||
}
|
||||
|
||||
@@ -676,7 +676,7 @@ class ArgumentsTests: XCTestCase {
|
||||
let args = ["enable": "braces,fileHeader"]
|
||||
let config = ["enable": "consecutiveSpaces,braces"]
|
||||
let result = try mergeArguments(args, into: config)
|
||||
let enabled = try parseRules(result["enable"]!)
|
||||
let enabled = try parseRules(result["enable"]!, ignoreUnknown: false)
|
||||
XCTAssertEqual(enabled, ["braces", "consecutiveSpaces", "fileHeader"])
|
||||
}
|
||||
|
||||
@@ -684,7 +684,7 @@ class ArgumentsTests: XCTestCase {
|
||||
let args = ["disable": "braces,fileHeader"]
|
||||
let config = ["disable": "consecutiveSpaces,braces"]
|
||||
let result = try mergeArguments(args, into: config)
|
||||
let disabled = try parseRules(result["disable"]!)
|
||||
let disabled = try parseRules(result["disable"]!, ignoreUnknown: false)
|
||||
XCTAssertEqual(disabled, ["braces", "consecutiveSpaces", "fileHeader"])
|
||||
}
|
||||
|
||||
@@ -692,7 +692,7 @@ class ArgumentsTests: XCTestCase {
|
||||
let args = ["rules": "braces,fileHeader"]
|
||||
let config = ["rules": "consecutiveSpaces", "disable": "braces", "enable": "redundantSelf"]
|
||||
let result = try mergeArguments(args, into: config)
|
||||
let disabled = try parseRules(result["rules"]!)
|
||||
let disabled = try parseRules(result["rules"]!, ignoreUnknown: false)
|
||||
XCTAssertEqual(disabled, ["braces", "fileHeader"])
|
||||
XCTAssertNil(result["enabled"])
|
||||
XCTAssertNil(result["disabled"])
|
||||
@@ -702,11 +702,11 @@ class ArgumentsTests: XCTestCase {
|
||||
let args = ["enable": "braces"]
|
||||
let config = ["rules": "fileHeader", "disable": "consecutiveSpaces,braces"]
|
||||
let result = try mergeArguments(args, into: config)
|
||||
let rules = try parseRules(result["rules"]!)
|
||||
let rules = try parseRules(result["rules"]!, ignoreUnknown: false)
|
||||
XCTAssertEqual(rules, ["fileHeader"])
|
||||
let enabled = try parseRules(result["enable"]!)
|
||||
let enabled = try parseRules(result["enable"]!, ignoreUnknown: false)
|
||||
XCTAssertEqual(enabled, ["braces"])
|
||||
let disabled = try parseRules(result["disable"]!)
|
||||
let disabled = try parseRules(result["disable"]!, ignoreUnknown: false)
|
||||
XCTAssertEqual(disabled, ["consecutiveSpaces"])
|
||||
}
|
||||
|
||||
@@ -714,11 +714,11 @@ class ArgumentsTests: XCTestCase {
|
||||
let args = ["disable": "braces"]
|
||||
let config = ["rules": "braces,fileHeader", "enable": "consecutiveSpaces,braces"]
|
||||
let result = try mergeArguments(args, into: config)
|
||||
let rules = try parseRules(result["rules"]!)
|
||||
let rules = try parseRules(result["rules"]!, ignoreUnknown: false)
|
||||
XCTAssertEqual(rules, ["fileHeader"])
|
||||
let enabled = try parseRules(result["enable"]!)
|
||||
let enabled = try parseRules(result["enable"]!, ignoreUnknown: false)
|
||||
XCTAssertEqual(enabled, ["consecutiveSpaces"])
|
||||
let disabled = try parseRules(result["disable"]!)
|
||||
let disabled = try parseRules(result["disable"]!, ignoreUnknown: false)
|
||||
XCTAssertEqual(disabled, ["braces"])
|
||||
}
|
||||
|
||||
@@ -850,29 +850,39 @@ class ArgumentsTests: XCTestCase {
|
||||
// MARK: parse rules
|
||||
|
||||
func testParseRulesCaseInsensitive() throws {
|
||||
let rules = try parseRules("strongoutlets")
|
||||
let rules = try parseRules("strongoutlets", ignoreUnknown: false)
|
||||
XCTAssertEqual(rules, ["strongOutlets"])
|
||||
}
|
||||
|
||||
func testParseAllRule() throws {
|
||||
let rules = try parseRules("all")
|
||||
let rules = try parseRules("all", ignoreUnknown: false)
|
||||
XCTAssertEqual(rules, FormatRules.all.compactMap {
|
||||
$0.isDeprecated ? nil : $0.name
|
||||
})
|
||||
}
|
||||
|
||||
func testParseInvalidRuleThrows() {
|
||||
XCTAssertThrowsError(try parseRules("strongOutlet")) { error in
|
||||
XCTAssertThrowsError(try parseRules("strongOutlet", ignoreUnknown: false)) { error in
|
||||
XCTAssertEqual("\(error)", "Unknown rule 'strongOutlet'. Did you mean 'strongOutlets'?")
|
||||
}
|
||||
}
|
||||
|
||||
func testParseOptionAsRuleThrows() {
|
||||
XCTAssertThrowsError(try parseRules("import-grouping")) { error in
|
||||
XCTAssertThrowsError(try parseRules("import-grouping", ignoreUnknown: false)) { error in
|
||||
XCTAssert("\(error)".contains("'sortImports'"))
|
||||
}
|
||||
}
|
||||
|
||||
func testSuppressInvalidRuleError() throws {
|
||||
let rules = try parseRules("strongOutlet,isEmpty", ignoreUnknown: true)
|
||||
XCTAssertEqual(rules, ["isEmpty"])
|
||||
}
|
||||
|
||||
func testSuppressOptionAsRuleError() throws {
|
||||
let rules = try parseRules("import-grouping,isEmpty", ignoreUnknown: true)
|
||||
XCTAssertEqual(rules, ["isEmpty"])
|
||||
}
|
||||
|
||||
// MARK: lintonly
|
||||
|
||||
func testLintonlyRulesContain() throws {
|
||||
|
||||
Reference in New Issue
Block a user