From ca405156f34f3c4a8fd79ee3a3b70f08da4ff008 Mon Sep 17 00:00:00 2001 From: Jeremy David Giesbrecht Date: Thu, 3 Aug 2017 15:55:22 -0600 Subject: [PATCH 1/7] Channelled merge flags from command line to configuration. --- .../Models/Configuration.swift | 37 ++++++++++++++++++- .../Commands/AutoCorrectCommand.swift | 14 +++++-- Source/swiftlint/Commands/LintCommand.swift | 14 +++++-- Source/swiftlint/Commands/RulesCommand.swift | 12 ++++-- .../Configuration+CommandLine.swift | 12 ++++-- Source/swiftlint/Helpers/CommonOptions.swift | 14 +++++++ 6 files changed, 87 insertions(+), 16 deletions(-) diff --git a/Source/SwiftLintFramework/Models/Configuration.swift b/Source/SwiftLintFramework/Models/Configuration.swift index df13cbb791..39ec5d2909 100644 --- a/Source/SwiftLintFramework/Models/Configuration.swift +++ b/Source/SwiftLintFramework/Models/Configuration.swift @@ -27,6 +27,9 @@ public struct Configuration: Equatable { public var warningThreshold: Int? // warning threshold public var rootPath: String? // the root path to search for nested configurations public var configurationPath: String? // if successfully loaded from a path + public var defaults: Ref? // --config-defaults + public var overrides: Ref? // --config-overrides + public var ignoreNested: Bool = false // --ignore-nested-configs public let cachePath: String? // MARK: Rules Properties @@ -136,8 +139,28 @@ public struct Configuration: Equatable { rootPath = configuration.rootPath } - public init(path: String = Configuration.fileName, rootPath: String? = nil, - optional: Bool = true, quiet: Bool = false, enableAllRules: Bool = false, cachePath: String? = nil) { + // swiftlint:disable:next function_body_length + public init(path: String = Configuration.fileName, rootPath: String? = nil, optional: Bool = true, + defaults: String? = nil, overrides: String? = nil, ignoreNested: Bool = false, + quiet: Bool = false, enableAllRules: Bool = false, cachePath: String? = nil) { + + defer { + if let defaultsPath = defaults { + // The defaults must inherit all but the path + // (i.e. quiet, enableAllRules & cachePath) + // because the root will not be merged into the defaults + // if merging is prevented by --ignore-nested-configs. + self.defaults = Ref(Configuration(path: defaultsPath, optional: false, + overrides: overrides, ignoreNested: ignoreNested, + quiet: quiet, enableAllRules: enableAllRules, + cachePath: cachePath)) + } + if let overridesPath = overrides { + self.overrides = Ref(Configuration(path: overridesPath, optional: false)) + } + self.ignoreNested = ignoreNested + } + let fullPath: String if let rootPath = rootPath, rootPath.isDirectory() { fullPath = path.bridge().absolutePathRepresentation(rootDirectory: rootPath) @@ -242,3 +265,13 @@ private extension String { return false } } + +public class Ref { + // Indirection to allow one configuration to store another as a property + + public let value: T + + public init(_ value: T) { + self.value = value + } +} diff --git a/Source/swiftlint/Commands/AutoCorrectCommand.swift b/Source/swiftlint/Commands/AutoCorrectCommand.swift index 902ac375ef..0a03ad5ecb 100644 --- a/Source/swiftlint/Commands/AutoCorrectCommand.swift +++ b/Source/swiftlint/Commands/AutoCorrectCommand.swift @@ -45,6 +45,9 @@ struct AutoCorrectCommand: CommandProtocol { struct AutoCorrectOptions: OptionsProtocol { let path: String let configurationFile: String + let configurationDefaults: String? + let configurationOverrides: String? + let ignoreNestedConfigurations: Bool let useScriptInputFiles: Bool let quiet: Bool let format: Bool @@ -53,10 +56,10 @@ struct AutoCorrectOptions: OptionsProtocol { let useTabs: Bool // swiftlint:disable line_length - static func create(_ path: String) -> (_ configurationFile: String) -> (_ useScriptInputFiles: Bool) -> (_ quiet: Bool) -> (_ format: Bool) -> (_ cachePath: String) -> (_ ignoreCache: Bool) -> (_ useTabs: Bool) -> AutoCorrectOptions { - return { configurationFile in { useScriptInputFiles in { quiet in { format in { cachePath in { ignoreCache in { useTabs in - self.init(path: path, configurationFile: configurationFile, useScriptInputFiles: useScriptInputFiles, quiet: quiet, format: format, cachePath: cachePath, ignoreCache: ignoreCache, useTabs: useTabs) - }}}}}}} + static func create(_ path: String) -> (_ configurationFile: String) -> (_ configurationDefaults: String?) -> (_ configurationOverrides: String?) -> (_ ignoreNestedConfigurations: Bool) -> (_ useScriptInputFiles: Bool) -> (_ quiet: Bool) -> (_ format: Bool) -> (_ cachePath: String) -> (_ ignoreCache: Bool) -> (_ useTabs: Bool) -> AutoCorrectOptions { + return { configurationFile in { configurationDefaults in { configurationOverrides in { ignoreNestedConfigurations in { useScriptInputFiles in { quiet in { format in { cachePath in { ignoreCache in { useTabs in + self.init(path: path, configurationFile: configurationFile, configurationDefaults: configurationDefaults, configurationOverrides: configurationOverrides, ignoreNestedConfigurations: ignoreNestedConfigurations, useScriptInputFiles: useScriptInputFiles, quiet: quiet, format: format, cachePath: cachePath, ignoreCache: ignoreCache, useTabs: useTabs) + }}}}}}}}}} } static func evaluate(_ mode: CommandMode) -> Result>> { @@ -64,6 +67,9 @@ struct AutoCorrectOptions: OptionsProtocol { return create <*> mode <| pathOption(action: "correct") <*> mode <| configOption + <*> mode <| configDefaultsOption + <*> mode <| configOverridesOption + <*> mode <| ignoreNestedConfigsOption <*> mode <| useScriptInputFilesOption <*> mode <| quietOption(action: "correcting") <*> mode <| Option(key: "format", diff --git a/Source/swiftlint/Commands/LintCommand.swift b/Source/swiftlint/Commands/LintCommand.swift index 2ce34c0a0a..47731ce683 100644 --- a/Source/swiftlint/Commands/LintCommand.swift +++ b/Source/swiftlint/Commands/LintCommand.swift @@ -128,6 +128,9 @@ struct LintOptions: OptionsProtocol { let path: String let useSTDIN: Bool let configurationFile: String + let configurationDefaults: String? + let configurationOverrides: String? + let ignoreNestedConfigurations: Bool let strict: Bool let lenient: Bool let useScriptInputFiles: Bool @@ -139,10 +142,10 @@ struct LintOptions: OptionsProtocol { let enableAllRules: Bool // swiftlint:disable line_length - static func create(_ path: String) -> (_ useSTDIN: Bool) -> (_ configurationFile: String) -> (_ strict: Bool) -> (_ lenient: Bool) -> (_ useScriptInputFiles: Bool) -> (_ benchmark: Bool) -> (_ reporter: String) -> (_ quiet: Bool) -> (_ cachePath: String) -> (_ ignoreCache: Bool) -> (_ enableAllRules: Bool) -> LintOptions { - return { useSTDIN in { configurationFile in { strict in { lenient in { useScriptInputFiles in { benchmark in { reporter in { quiet in { cachePath in { ignoreCache in { enableAllRules in - self.init(path: path, useSTDIN: useSTDIN, configurationFile: configurationFile, strict: strict, lenient: lenient, useScriptInputFiles: useScriptInputFiles, benchmark: benchmark, reporter: reporter, quiet: quiet, cachePath: cachePath, ignoreCache: ignoreCache, enableAllRules: enableAllRules) - }}}}}}}}}}} + static func create(_ path: String) -> (_ useSTDIN: Bool) -> (_ configurationFile: String) -> (_ configurationDefaults: String?) -> (_ configurationOverrides: String?) -> (_ ignoreNestedConfigurations: Bool) -> (_ strict: Bool) -> (_ lenient: Bool) -> (_ useScriptInputFiles: Bool) -> (_ benchmark: Bool) -> (_ reporter: String) -> (_ quiet: Bool) -> (_ cachePath: String) -> (_ ignoreCache: Bool) -> (_ enableAllRules: Bool) -> LintOptions { + return { useSTDIN in { configurationFile in { configurationDefaults in { configurationOverrides in { ignoreNestedConfigurations in { strict in { lenient in { useScriptInputFiles in { benchmark in { reporter in { quiet in { cachePath in { ignoreCache in { enableAllRules in + self.init(path: path, useSTDIN: useSTDIN, configurationFile: configurationFile, configurationDefaults: configurationDefaults, configurationOverrides: configurationOverrides, ignoreNestedConfigurations: ignoreNestedConfigurations, strict: strict, lenient: lenient, useScriptInputFiles: useScriptInputFiles, benchmark: benchmark, reporter: reporter, quiet: quiet, cachePath: cachePath, ignoreCache: ignoreCache, enableAllRules: enableAllRules) + }}}}}}}}}}}}}} } static func evaluate(_ mode: CommandMode) -> Result>> { @@ -152,6 +155,9 @@ struct LintOptions: OptionsProtocol { <*> mode <| Option(key: "use-stdin", defaultValue: false, usage: "lint standard input") <*> mode <| configOption + <*> mode <| configDefaultsOption + <*> mode <| configOverridesOption + <*> mode <| ignoreNestedConfigsOption <*> mode <| Option(key: "strict", defaultValue: false, usage: "fail on warnings") <*> mode <| Option(key: "lenient", defaultValue: false, diff --git a/Source/swiftlint/Commands/RulesCommand.swift b/Source/swiftlint/Commands/RulesCommand.swift index 1e2d17eb8f..9cc09c40f1 100644 --- a/Source/swiftlint/Commands/RulesCommand.swift +++ b/Source/swiftlint/Commands/RulesCommand.swift @@ -78,22 +78,28 @@ struct RulesCommand: CommandProtocol { struct RulesOptions: OptionsProtocol { fileprivate let ruleID: String? let configurationFile: String + let configurationDefaults: String? + let configurationOverrides: String? fileprivate let onlyEnabledRules: Bool fileprivate let onlyDisabledRules: Bool // swiftlint:disable line_length - static func create(_ configurationFile: String) -> (_ ruleID: String) -> (_ onlyEnabledRules: Bool) -> (_ onlyDisabledRules: Bool) -> RulesOptions { - return { ruleID in { onlyEnabledRules in { onlyDisabledRules in + static func create(_ configurationFile: String) -> (_ configurationDefaults: String?) -> (_ configurationOverrides: String?) -> (_ ruleID: String) -> (_ onlyEnabledRules: Bool) -> (_ onlyDisabledRules: Bool) -> RulesOptions { + return { configurationDefaults in { configurationOverrides in { ruleID in { onlyEnabledRules in { onlyDisabledRules in self.init(ruleID: (ruleID.isEmpty ? nil : ruleID), configurationFile: configurationFile, + configurationDefaults: configurationDefaults, + configurationOverrides: configurationOverrides, onlyEnabledRules: onlyEnabledRules, onlyDisabledRules: onlyDisabledRules) - }}} + }}}}} } static func evaluate(_ mode: CommandMode) -> Result>> { return create <*> mode <| configOption + <*> mode <| configDefaultsOption + <*> mode <| configOverridesOption <*> mode <| Argument(defaultValue: "", usage: "the rule identifier to display description for") <*> mode <| Switch(flag: "e", diff --git a/Source/swiftlint/Extensions/Configuration+CommandLine.swift b/Source/swiftlint/Extensions/Configuration+CommandLine.swift index ff0cb1c486..40bc61c789 100644 --- a/Source/swiftlint/Extensions/Configuration+CommandLine.swift +++ b/Source/swiftlint/Extensions/Configuration+CommandLine.swift @@ -124,7 +124,9 @@ extension Configuration { let cachePath = options.cachePath.isEmpty ? nil : options.cachePath let optional = !CommandLine.arguments.contains("--config") self.init(path: options.configurationFile, rootPath: options.path.absolutePathStandardized(), - optional: optional, quiet: options.quiet, + optional: optional, + defaults: options.configurationDefaults, overrides: options.configurationOverrides, + ignoreNested: options.ignoreNestedConfigurations, quiet: options.quiet, enableAllRules: options.enableAllRules, cachePath: cachePath) } @@ -141,13 +143,17 @@ extension Configuration { let cachePath = options.cachePath.isEmpty ? nil : options.cachePath let optional = !CommandLine.arguments.contains("--config") self.init(path: options.configurationFile, rootPath: options.path.absolutePathStandardized(), - optional: optional, quiet: options.quiet, cachePath: cachePath) + optional: optional, + defaults: options.configurationDefaults, overrides: options.configurationOverrides, + ignoreNested: options.ignoreNestedConfigurations, + quiet: options.quiet, cachePath: cachePath) } // MARK: Rules command init(options: RulesOptions) { let optional = !CommandLine.arguments.contains("--config") - self.init(path: options.configurationFile, optional: optional) + self.init(path: options.configurationFile, optional: optional, + defaults: options.configurationDefaults, overrides: options.configurationOverrides) } } diff --git a/Source/swiftlint/Helpers/CommonOptions.swift b/Source/swiftlint/Helpers/CommonOptions.swift index 0f9d14b4b0..cd4f5746b6 100644 --- a/Source/swiftlint/Helpers/CommonOptions.swift +++ b/Source/swiftlint/Helpers/CommonOptions.swift @@ -19,6 +19,20 @@ let configOption = Option(key: "config", defaultValue: Configuration.fileName, usage: "the path to SwiftLint's configuration file") +let configDefaultsOption = Option(key: "config-defaults", + defaultValue: nil, + usage: "the path of an external configuration file " + + "to use as the root of the merge tree") + +let configOverridesOption = Option(key: "config-overrides", + defaultValue: nil, + usage: "the path of an external configuration file " + + "to append to the end of each branch of the merge tree") + +let ignoreNestedConfigsOption = Option(key: "ignore-nested-configs", + defaultValue: false, + usage: "ignores nested configuration files") + let useScriptInputFilesOption = Option(key: "use-script-input-files", defaultValue: false, usage: "read SCRIPT_INPUT_FILE* environment variables " + From be0d05f4a1fbe90d7dd8481a3df1eb7f4e910382 Mon Sep 17 00:00:00 2001 From: Jeremy David Giesbrecht Date: Thu, 3 Aug 2017 18:46:34 -0600 Subject: [PATCH 2/7] Integrated flags into merge logic. --- .../Extensions/Configuration+Merging.swift | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/Source/SwiftLintFramework/Extensions/Configuration+Merging.swift b/Source/SwiftLintFramework/Extensions/Configuration+Merging.swift index d2bf97ff1c..40cd6cafe6 100644 --- a/Source/SwiftLintFramework/Extensions/Configuration+Merging.swift +++ b/Source/SwiftLintFramework/Extensions/Configuration+Merging.swift @@ -18,29 +18,57 @@ extension Configuration { } private func configuration(forPath path: String) -> Configuration { - if path == rootPath { + if ignoreNested { + if let commandLineDefaults = defaults?.value { + // --config-defaults is lowest in the tree + return commandLineDefaults + } else { + // when no --config-defaults, the root directory is lowest in the tree + return self + } + } + + var merged = mergeConfigurationFiles(upTo: path) + if let commandLineDefaults = defaults?.value { + // add --config-defaults underneath + merged = commandLineDefaults.merge(with: merged) + } + if let commandLineOverrides = overrides?.value { + // add --config-overrides on top + merged = merged.merge(with: commandLineOverrides) + } + return merged + } + + private func mergeConfigurationFiles(upTo path: String) -> Configuration { + if path == rootPath || path == "/" { return self } let pathNSString = path.bridge() let configurationSearchPath = pathNSString.appendingPathComponent(Configuration.fileName) + if configurationSearchPath == configurationPath { + // We are the configuration, no need to read from the disk again, just return self + return self + } + + // We are not at the root path, so get the parent configuration + let parent = mergeConfigurationFiles(upTo: path.bridge().deletingLastPathComponent) - // If a configuration exists and it isn't us, load and merge the configurations + // If a configuration exists, load it if configurationSearchPath != configurationPath && FileManager.default.fileExists(atPath: configurationSearchPath) { let fullPath = pathNSString.absolutePathRepresentation() let config = Configuration.getCached(atPath: fullPath) ?? Configuration(path: configurationSearchPath, rootPath: fullPath, optional: false, quiet: true) - return merge(with: config) - } - // If we are not at the root path, continue down the tree - if path != rootPath && path != "/" { - return configuration(forPath: pathNSString.deletingLastPathComponent) - } + // merge the changes specified in this directory on top of the parent + return parent.merge(with: config) - // If nothing else, return self - return self + } else { + // no changes specified in this directory, so just return the parent + return parent + } } private struct HashableRule: Hashable { From ca07552b2dd5ab3944aed4f1e39164c71810ae33 Mon Sep 17 00:00:00 2001 From: Jeremy David Giesbrecht Date: Thu, 3 Aug 2017 19:14:08 -0600 Subject: [PATCH 3/7] Added changelog entry. --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c55768229d..067cc56f94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ [JP Simard](https://github.com/jpsim) [#676](https://github.com/realm/SwiftLint/issues/676) + * Several command line options allow interaction with the merging process. + (See `swiftlint help lint`.) + [Jeremy David Giesbrecht](https://github.com/SDGGiesbrecht) + [##1693](https://github.com/realm/SwiftLint/issues/1693) + ##### Enhancements * Add `xctfail_message` rule to enforce XCTFail From bf51265df11610264a40c8619b7df09c3aa6bd7b Mon Sep 17 00:00:00 2001 From: Jeremy David Giesbrecht Date: Thu, 3 Aug 2017 21:03:55 -0600 Subject: [PATCH 4/7] Added tests. --- .../ConfigurationTests+Nested.swift | 23 +++++++++++++++++++ .../ConfigurationTests+ProjectMock.swift | 8 +++++++ .../Resources/ProjectMock/.swiftlint.yml | 2 ++ .../Resources/defaults.yml | 3 +++ .../Resources/overrides.yml | 2 ++ 5 files changed, 38 insertions(+) create mode 100644 Tests/SwiftLintFrameworkTests/Resources/defaults.yml create mode 100644 Tests/SwiftLintFrameworkTests/Resources/overrides.yml diff --git a/Tests/SwiftLintFrameworkTests/ConfigurationTests+Nested.swift b/Tests/SwiftLintFrameworkTests/ConfigurationTests+Nested.swift index f3b87e44d1..c0c846708f 100644 --- a/Tests/SwiftLintFrameworkTests/ConfigurationTests+Nested.swift +++ b/Tests/SwiftLintFrameworkTests/ConfigurationTests+Nested.swift @@ -94,4 +94,27 @@ extension ConfigurationTests { XCTAssertTrue(mergedConfiguration2.contains(rule: ForceCastRule.self)) XCTAssertTrue(mergedConfiguration2.contains(rule: ForceTryRule.self)) } + + func testDefaults() { + let root = Configuration(path: Configuration.fileName, rootPath: projectMockPathLevel0, + defaults: projectMockDefaults) + let merged = root.configuration(for: File(path: projectMockSwift0)!) + XCTAssert(!merged.contains(rule: ColonRule.self)) // Default applied. + XCTAssert(merged.contains(rule: CommaRule.self)) // Default overridden. + } + + func testOverrides() { + let root = Configuration(path: Configuration.fileName, rootPath: projectMockPathLevel0, + overrides: projectMockOverrides) + let merged = root.configuration(for: File(path: projectMockSwift3)!) + XCTAssert(merged.contains(rule: ForceTryRule.self)) // Override applied. + XCTAssert(!merged.contains(rule: TodoRule.self)) // Unaffected not stomped. + } + + func testIgnoreNested() { + let root = Configuration(path: Configuration.fileName, rootPath: projectMockPathLevel0, + ignoreNested: true) + let merged = root.configuration(for: File(path: projectMockSwift3)!) + XCTAssert(merged.contains(rule: ForceTryRule.self)) // Nested ignored. + } } diff --git a/Tests/SwiftLintFrameworkTests/ConfigurationTests+ProjectMock.swift b/Tests/SwiftLintFrameworkTests/ConfigurationTests+ProjectMock.swift index 247364dcd1..112d85e52d 100644 --- a/Tests/SwiftLintFrameworkTests/ConfigurationTests+ProjectMock.swift +++ b/Tests/SwiftLintFrameworkTests/ConfigurationTests+ProjectMock.swift @@ -74,4 +74,12 @@ extension ConfigurationTests { return Configuration(path: Configuration.fileName, rootPath: projectMockPathLevel3, optional: false, quiet: true) } + + var projectMockDefaults: String { + return bundlePath.stringByAppendingPathComponent("defaults.yml") + } + + var projectMockOverrides: String { + return bundlePath.stringByAppendingPathComponent("overrides.yml") + } } diff --git a/Tests/SwiftLintFrameworkTests/Resources/ProjectMock/.swiftlint.yml b/Tests/SwiftLintFrameworkTests/Resources/ProjectMock/.swiftlint.yml index 268f132e19..d163d3ab98 100644 --- a/Tests/SwiftLintFrameworkTests/Resources/ProjectMock/.swiftlint.yml +++ b/Tests/SwiftLintFrameworkTests/Resources/ProjectMock/.swiftlint.yml @@ -1,5 +1,7 @@ disabled_rules: - force_cast +opt_in_rules: + - comma included: - "everything" excluded: diff --git a/Tests/SwiftLintFrameworkTests/Resources/defaults.yml b/Tests/SwiftLintFrameworkTests/Resources/defaults.yml new file mode 100644 index 0000000000..16f9db87cd --- /dev/null +++ b/Tests/SwiftLintFrameworkTests/Resources/defaults.yml @@ -0,0 +1,3 @@ +disabled_rules: + - comma + - colon diff --git a/Tests/SwiftLintFrameworkTests/Resources/overrides.yml b/Tests/SwiftLintFrameworkTests/Resources/overrides.yml new file mode 100644 index 0000000000..eb7e18e48d --- /dev/null +++ b/Tests/SwiftLintFrameworkTests/Resources/overrides.yml @@ -0,0 +1,2 @@ +opt_in_rules: + - force_try \ No newline at end of file From 3241f8c15ccb7a0f766c83ff745cec953bda0c94 Mon Sep 17 00:00:00 2001 From: Jeremy David Giesbrecht Date: Thu, 3 Aug 2017 21:20:00 -0600 Subject: [PATCH 5/7] Registered resources in Xcode project. --- SwiftLint.xcodeproj/project.pbxproj | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/SwiftLint.xcodeproj/project.pbxproj b/SwiftLint.xcodeproj/project.pbxproj index e3bd281762..04cef8b83d 100644 --- a/SwiftLint.xcodeproj/project.pbxproj +++ b/SwiftLint.xcodeproj/project.pbxproj @@ -56,6 +56,8 @@ 3BCC04D41C502BAB006073C3 /* RuleConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BCC04D31C502BAB006073C3 /* RuleConfigurationTests.swift */; }; 3BD9CD3D1C37175B009A5D25 /* YamlParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BD9CD3C1C37175B009A5D25 /* YamlParser.swift */; }; 3BDB224B1C345B4900473680 /* ProjectMock in Resources */ = {isa = PBXBuildFile; fileRef = 3BDB224A1C345B4900473680 /* ProjectMock */; }; + 3FA6DA941F341F0500522BD1 /* defaults.yml in Resources */ = {isa = PBXBuildFile; fileRef = 3FA6DA921F341ED800522BD1 /* defaults.yml */; }; + 3FA6DA951F341F0500522BD1 /* overrides.yml in Resources */ = {isa = PBXBuildFile; fileRef = 3FA6DA931F341ED800522BD1 /* overrides.yml */; }; 47ACC8981E7DC74E0088EEB2 /* ImplicitlyUnwrappedOptionalConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47ACC8971E7DC74E0088EEB2 /* ImplicitlyUnwrappedOptionalConfiguration.swift */; }; 47ACC89A1E7DCCAD0088EEB2 /* ImplicitlyUnwrappedOptionalConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47ACC8991E7DCCAD0088EEB2 /* ImplicitlyUnwrappedOptionalConfigurationTests.swift */; }; 47ACC89C1E7DCFA00088EEB2 /* ImplicitlyUnwrappedOptionalRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47ACC89B1E7DCFA00088EEB2 /* ImplicitlyUnwrappedOptionalRuleTests.swift */; }; @@ -362,6 +364,8 @@ 3BCC04D31C502BAB006073C3 /* RuleConfigurationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RuleConfigurationTests.swift; sourceTree = ""; }; 3BD9CD3C1C37175B009A5D25 /* YamlParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YamlParser.swift; sourceTree = ""; }; 3BDB224A1C345B4900473680 /* ProjectMock */ = {isa = PBXFileReference; lastKnownFileType = folder; path = ProjectMock; sourceTree = ""; }; + 3FA6DA921F341ED800522BD1 /* defaults.yml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = defaults.yml; sourceTree = ""; }; + 3FA6DA931F341ED800522BD1 /* overrides.yml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = overrides.yml; sourceTree = ""; }; 47ACC8971E7DC74E0088EEB2 /* ImplicitlyUnwrappedOptionalConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImplicitlyUnwrappedOptionalConfiguration.swift; sourceTree = ""; }; 47ACC8991E7DCCAD0088EEB2 /* ImplicitlyUnwrappedOptionalConfigurationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImplicitlyUnwrappedOptionalConfigurationTests.swift; sourceTree = ""; }; 47ACC89B1E7DCFA00088EEB2 /* ImplicitlyUnwrappedOptionalRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImplicitlyUnwrappedOptionalRuleTests.swift; sourceTree = ""; }; @@ -627,6 +631,8 @@ isa = PBXGroup; children = ( 3B12C9BF1C3209AC000B423F /* test.yml */, + 3FA6DA921F341ED800522BD1 /* defaults.yml */, + 3FA6DA931F341ED800522BD1 /* overrides.yml */, 3BDB224A1C345B4900473680 /* ProjectMock */, F9D73F021D0CF15E00222FC4 /* test.txt */, B3935250C8E0DBACFB27E021 /* CannedHTMLReporterOutput.html */, @@ -1227,6 +1233,8 @@ files = ( 3B12C9C11C3209CB000B423F /* test.yml in Resources */, F9D73F031D0CF15E00222FC4 /* test.txt in Resources */, + 3FA6DA941F341F0500522BD1 /* defaults.yml in Resources */, + 3FA6DA951F341F0500522BD1 /* overrides.yml in Resources */, 3BDB224B1C345B4900473680 /* ProjectMock in Resources */, B3935797FF80C7F97953D375 /* CannedHTMLReporterOutput.html in Resources */, B3935371E92E0CF3F7668303 /* CannedJunitReporterOutput.xml in Resources */, From db73aed47286c854afe27dbfb8a4cc505bb36d58 Mon Sep 17 00:00:00 2001 From: Jeremy David Giesbrecht Date: Fri, 4 Aug 2017 15:36:30 -0600 Subject: [PATCH 6/7] Registered new tests for Linux. --- Tests/LinuxMain.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index a72c043f30..7cd7d7ef9b 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -80,7 +80,10 @@ extension ConfigurationTests { ("testLevel3", testLevel3), ("testNestedConfigurationWithCustomRootPath", testNestedConfigurationWithCustomRootPath), ("testMergedWarningThreshold", testMergedWarningThreshold), - ("testNestedWhitelistedRules", testNestedWhitelistedRules) + ("testNestedWhitelistedRules", testNestedWhitelistedRules), + ("testDefaults", testDefaults), + ("testOverrides", testOverrides), + ("testIgnoreNested", testIgnoreNested) ] } From f7f0fffa7bca0d5f6c01dbf03c4f337ac9ee872f Mon Sep 17 00:00:00 2001 From: Jeremy David Giesbrecht Date: Fri, 4 Aug 2017 17:30:57 -0600 Subject: [PATCH 7/7] Fixed configuration comparison bug on Linux. --- Source/SwiftLintFramework/Models/Configuration.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/SwiftLintFramework/Models/Configuration.swift b/Source/SwiftLintFramework/Models/Configuration.swift index 39ec5d2909..d600023643 100644 --- a/Source/SwiftLintFramework/Models/Configuration.swift +++ b/Source/SwiftLintFramework/Models/Configuration.swift @@ -213,7 +213,8 @@ public struct Configuration: Equatable { (lhs.reporter == rhs.reporter) && (lhs.configurationPath == rhs.configurationPath) && (lhs.rootPath == lhs.rootPath) && - (lhs.rules == rhs.rules) + (lhs.rules.sorted(by: { String(describing: $0) < String(describing: $1) }) + == rhs.rules.sorted(by: { String(describing: $0) < String(describing: $1) })) } }