From 69bc07b7d2b0e8e2c0868b6f531c0a96e19e13e2 Mon Sep 17 00:00:00 2001 From: JP Simard Date: Sat, 13 Jul 2019 11:35:29 -0700 Subject: [PATCH 1/4] Add UnusedDeclarationRule --- .swiftlint.yml | 2 +- CHANGELOG.md | 10 + Makefile | 2 +- Rules.md | 127 ++++---- .../NSRegularExpression+SwiftLint.swift | 4 +- .../Models/MasterRuleList.swift | 2 +- .../Rules/Lint/UnusedDeclarationRule.swift | 277 ++++++++++++++++++ .../Lint/UnusedPrivateDeclarationRule.swift | 173 ----------- .../UnusedDeclarationConfiguration.swift | 43 +++ SwiftLint.xcodeproj/project.pbxproj | 12 +- Tests/LinuxMain.swift | 14 +- .../AutomaticRuleTests.generated.swift | 12 +- 12 files changed, 425 insertions(+), 253 deletions(-) create mode 100644 Source/SwiftLintFramework/Rules/Lint/UnusedDeclarationRule.swift delete mode 100644 Source/SwiftLintFramework/Rules/Lint/UnusedPrivateDeclarationRule.swift create mode 100644 Source/SwiftLintFramework/Rules/RuleConfigurations/UnusedDeclarationConfiguration.swift diff --git a/.swiftlint.yml b/.swiftlint.yml index 3e5cfb26a7..6c56e188d3 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -4,8 +4,8 @@ included: excluded: - Tests/SwiftLintFrameworkTests/Resources analyzer_rules: + - unused_declaration - unused_import - - unused_private_declaration opt_in_rules: - anyobject_protocol - array_init diff --git a/CHANGELOG.md b/CHANGELOG.md index fa7b41b0e0..fcd8888bb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,16 @@ [Elliott Williams](https://github.com/elliottwilliams) [#2431](https://github.com/realm/SwiftLint/issues/2431) +* Add a new `unused_declaration` analyzer rule to lint for unused declarations. + By default, detects unused `fileprivate`, `private` and `internal` + declarations. Configure the rule with `include_public_and_open: true` to + also detect unused `public` and `open` declarations. + [JP Simard](https://github.com/jpsim) + +* Completely remove the `unused_private_declaration` rule. Please use + `unused_declaration` instead. + [JP Simard](https://github.com/jpsim) + #### Enhancements * None. diff --git a/Makefile b/Makefile index 345ed983ea..ca0accc9b8 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,7 @@ test_tsan: DYLD_INSERT_LIBRARIES=$(TSAN_LIB) $(TSAN_XCTEST) $(TSAN_TEST_BUNDLE) write_xcodebuild_log: bootstrap - xcodebuild -workspace SwiftLint.xcworkspace -scheme swiftlint > xcodebuild.log + xcodebuild -workspace SwiftLint.xcworkspace -scheme swiftlint clean build-for-testing > xcodebuild.log analyze: write_xcodebuild_log swift run -c release swiftlint analyze --strict --compiler-log-path xcodebuild.log diff --git a/Rules.md b/Rules.md index 184cde8794..50462df92e 100644 --- a/Rules.md +++ b/Rules.md @@ -161,10 +161,10 @@ * [Unused Capture List](#unused-capture-list) * [Unused Closure Parameter](#unused-closure-parameter) * [Unused Control Flow Label](#unused-control-flow-label) +* [Unused Declaration](#unused-declaration) * [Unused Enumerated](#unused-enumerated) * [Unused Import](#unused-import) * [Unused Optional Binding](#unused-optional-binding) -* [Unused Private Declaration](#unused-private-declaration) * [Unused Setter Value](#unused-setter-value) * [Valid IBInspectable](#valid-ibinspectable) * [Vertical Parameter Alignment](#vertical-parameter-alignment) @@ -23612,6 +23612,74 @@ default: break +## Unused Declaration + +Identifier | Enabled by default | Supports autocorrection | Kind | Analyzer | Minimum Swift Compiler Version +--- | --- | --- | --- | --- | --- +`unused_declaration` | Disabled | No | lint | Yes | 3.0.0 + +Declarations should be referenced at least once within all files linted. + +### Examples + +
+Non Triggering Examples + +```swift +let kConstant = 0 +_ = kConstant +``` + +```swift +struct Item {} +struct ResponseModel: Codable { + let items: [Item] + + enum CodingKeys: String, CodingKey { + case items = "ResponseItems" + } +} + +_ = ResponseModel(items: [Item()]).items +``` + +```swift +class ResponseModel { + @objc func foo() { + } +} +_ = ResponseModel() +``` + +
+
+Triggering Examples + +```swift +let ↓kConstant = 0 +``` + +```swift +struct ↓ResponseModel: Codable { + let ↓items: [Item] + + enum ↓CodingKeys: String { + case items = "ResponseItems" + } +} +``` + +```swift +class ↓ResponseModel { + func ↓foo() { + } +} +``` + +
+ + + ## Unused Enumerated Identifier | Enabled by default | Supports autocorrection | Kind | Analyzer | Minimum Swift Compiler Version @@ -23885,63 +23953,6 @@ if case .some(let ↓_) = self {} -## Unused Private Declaration - -Identifier | Enabled by default | Supports autocorrection | Kind | Analyzer | Minimum Swift Compiler Version ---- | --- | --- | --- | --- | --- -`unused_private_declaration` | Disabled | No | lint | Yes | 3.0.0 - -Private declarations should be referenced in that file. - -### Examples - -
-Non Triggering Examples - -```swift -private let kConstant = 0 -_ = kConstant -``` - -```swift -struct ResponseModel: Codable { - let items: [Item] - - private enum CodingKeys: String, CodingKey { - case items = "ResponseItems" - } -} -``` - -```swift -class ResponseModel { - @objc private func foo() { - } -} -``` - -
-
-Triggering Examples - -```swift -private let ↓kConstant = 0 -``` - -```swift -struct ResponseModel: Codable { - let items: [Item] - - private enum ↓CodingKeys: String { - case items = "ResponseItems" - } -} -``` - -
- - - ## Unused Setter Value Identifier | Enabled by default | Supports autocorrection | Kind | Analyzer | Minimum Swift Compiler Version diff --git a/Source/SwiftLintFramework/Extensions/NSRegularExpression+SwiftLint.swift b/Source/SwiftLintFramework/Extensions/NSRegularExpression+SwiftLint.swift index 0ac169f803..cc2f556f82 100644 --- a/Source/SwiftLintFramework/Extensions/NSRegularExpression+SwiftLint.swift +++ b/Source/SwiftLintFramework/Extensions/NSRegularExpression+SwiftLint.swift @@ -6,10 +6,10 @@ private let regexCacheLock = NSLock() private struct RegexCacheKey: Hashable { // Disable unused private declaration rule here because even though we don't use these properties // directly, we rely on them for their hashable and equatable behavior. - // swiftlint:disable unused_private_declaration + // swiftlint:disable unused_declaration let pattern: String let options: NSRegularExpression.Options - // swiftlint:enable unused_private_declaration + // swiftlint:enable unused_declaration } extension NSRegularExpression.Options: Hashable { diff --git a/Source/SwiftLintFramework/Models/MasterRuleList.swift b/Source/SwiftLintFramework/Models/MasterRuleList.swift index abcc392f24..9dd94184c2 100644 --- a/Source/SwiftLintFramework/Models/MasterRuleList.swift +++ b/Source/SwiftLintFramework/Models/MasterRuleList.swift @@ -162,10 +162,10 @@ public let masterRuleList = RuleList(rules: [ UnusedCaptureListRule.self, UnusedClosureParameterRule.self, UnusedControlFlowLabelRule.self, + UnusedDeclarationRule.self, UnusedEnumeratedRule.self, UnusedImportRule.self, UnusedOptionalBindingRule.self, - UnusedPrivateDeclarationRule.self, UnusedSetterValueRule.self, ValidIBInspectableRule.self, VerticalParameterAlignmentOnCallRule.self, diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedDeclarationRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedDeclarationRule.swift new file mode 100644 index 0000000000..8617e411a0 --- /dev/null +++ b/Source/SwiftLintFramework/Rules/Lint/UnusedDeclarationRule.swift @@ -0,0 +1,277 @@ +import Foundation +import SourceKittenFramework + +public struct UnusedDeclarationRule: AutomaticTestableRule, ConfigurationProviderRule, AnalyzerRule, CollectingRule { + public struct FileUSRs { + var referenced: Set + var declared: [(usr: String, nameOffset: Int)] + var testCaseUSRs: Set + } + + public typealias FileInfo = FileUSRs + + public var configuration = UnusedDeclarationConfiguration(severity: .error, includePublicAndOpen: false) + + public init() {} + + public static let description = RuleDescription( + identifier: "unused_declaration", + name: "Unused Declaration", + description: "Declarations should be referenced at least once within all files linted.", + kind: .lint, + nonTriggeringExamples: [ + """ + let kConstant = 0 + _ = kConstant + """, + """ + struct Item {} + struct ResponseModel: Codable { + let items: [Item] + + enum CodingKeys: String, CodingKey { + case items = "ResponseItems" + } + } + + _ = ResponseModel(items: [Item()]).items + """, + """ + class ResponseModel { + @objc func foo() { + } + } + _ = ResponseModel() + """ + ], + triggeringExamples: [ + """ + let ↓kConstant = 0 + """, + """ + struct ↓ResponseModel: Codable { + let ↓items: [Item] + + enum ↓CodingKeys: String { + case items = "ResponseItems" + } + } + """, + """ + class ↓ResponseModel { + func ↓foo() { + } + } + """ + ], + requiresFileOnDisk: true + ) + + public func collectInfo(for file: File, compilerArguments: [String]) -> UnusedDeclarationRule.FileUSRs { + guard !compilerArguments.isEmpty else { + queuedPrintError(""" + Attempted to lint file at path '\(file.path ?? "...")' with the \ + \(type(of: self).description.identifier) rule without any compiler arguments. + """) + return FileUSRs(referenced: [], declared: [], testCaseUSRs: []) + } + + let allCursorInfo = file.allCursorInfo(compilerArguments: compilerArguments) + return FileUSRs(referenced: Set(File.referencedUSRs(allCursorInfo: allCursorInfo)), + declared: File.declaredUSRs(allCursorInfo: allCursorInfo, + includePublicAndOpen: configuration.includePublicAndOpen), + testCaseUSRs: File.testCaseUSRs(allCursorInfo: allCursorInfo)) + } + + public func validate(file: File, collectedInfo: [File: UnusedDeclarationRule.FileUSRs], + compilerArguments: [String]) -> [StyleViolation] { + let allReferencedUSRs = collectedInfo.values.reduce(into: Set()) { $0.formUnion($1.referenced) } + let allTestCaseUSRs = collectedInfo.values.reduce(into: Set()) { $0.formUnion($1.testCaseUSRs) } + return violationOffsets(in: file, compilerArguments: compilerArguments, + declaredUSRs: collectedInfo[file]?.declared ?? [], + allReferencedUSRs: allReferencedUSRs, + allTestCaseUSRs: allTestCaseUSRs) + .map { + StyleViolation(ruleDescription: type(of: self).description, + severity: configuration.severity, + location: Location(file: file, byteOffset: $0)) + } + } + + private func violationOffsets(in file: File, compilerArguments: [String], + declaredUSRs: [(usr: String, nameOffset: Int)], + allReferencedUSRs: Set, + allTestCaseUSRs: Set) -> [Int] { + // Unused declarations are: + // 1. all declarations + // 2. minus all references + // 3. minus all XCTestCase subclasses + // 4. minus all XCTest test functions + let unusedDeclarations = declaredUSRs + .filter { !allReferencedUSRs.contains($0.usr) } + .filter { !allTestCaseUSRs.contains($0.usr) } + .filter { declaredUSR in + return !allTestCaseUSRs.contains(where: { testCaseUSR in + return declaredUSR.usr.hasPrefix(testCaseUSR + "(im)test") || + declaredUSR.usr.hasPrefix( + testCaseUSR.replacingOccurrences(of: "@M@", with: "@CM@") + "(im)test" + ) + }) + } + return unusedDeclarations.map { $0.nameOffset } + } +} + +// MARK: - File Extensions + +private extension File { + func allCursorInfo(compilerArguments: [String]) -> [[String: SourceKitRepresentable]] { + guard let path = path, let editorOpen = try? Request.editorOpen(file: self).sendIfNotDisabled() else { + return [] + } + + return syntaxMap.tokens.compactMap { token in + guard let kind = SyntaxKind(rawValue: token.type), !syntaxKindsToSkip.contains(kind) else { + return nil + } + + let offset = Int64(token.offset) + let request = Request.cursorInfo(file: path, offset: offset, arguments: compilerArguments) + guard var cursorInfo = try? request.sendIfNotDisabled() else { + return nil + } + + if let acl = File.aclAtOffset(offset, substructureElement: editorOpen) { + cursorInfo["key.accessibility"] = acl + } + cursorInfo["swiftlint.offset"] = offset + return cursorInfo + } + } + + static func declaredUSRs(allCursorInfo: [[String: SourceKitRepresentable]], includePublicAndOpen: Bool) + -> [(usr: String, nameOffset: Int)] { + return allCursorInfo.compactMap { cursorInfo in + return declaredUSRAndOffset(cursorInfo: cursorInfo, includePublicAndOpen: includePublicAndOpen) + } + } + + static func referencedUSRs(allCursorInfo: [[String: SourceKitRepresentable]]) -> [String] { + return allCursorInfo.compactMap(referencedUSR) + } + + static func testCaseUSRs(allCursorInfo: [[String: SourceKitRepresentable]]) -> Set { + return Set(allCursorInfo.compactMap(testCaseUSR)) + } + + private static func declaredUSRAndOffset(cursorInfo: [String: SourceKitRepresentable], includePublicAndOpen: Bool) + -> (usr: String, nameOffset: Int)? { + if let offset = cursorInfo["swiftlint.offset"] as? Int64, + let usr = cursorInfo["key.usr"] as? String, + let kind = (cursorInfo["key.kind"] as? String).flatMap(SwiftDeclarationKind.init(rawValue:)), + !declarationKindsToSkip.contains(kind), + let acl = (cursorInfo["key.accessibility"] as? String).flatMap(AccessControlLevel.init(rawValue:)), + includePublicAndOpen || [.internal, .private, .fileprivate].contains(acl) { + // Skip declarations marked as @IBOutlet, @IBAction or @objc + // since those might not be referenced in code, but only dynamically (e.g. Interface Builder) + if let annotatedDecl = cursorInfo["key.annotated_decl"] as? String, + ["@IBOutlet", "@IBAction", "@objc", "@IBInspectable"].contains(where: annotatedDecl.contains) { + return nil + } + + // Classes marked as @UIApplicationMain are used by the operating system as the entry point into the app. + if let annotatedDecl = cursorInfo["key.annotated_decl"] as? String, + annotatedDecl.contains("@UIApplicationMain") { + return nil + } + + // Skip declarations that override another. This works for both subclass overrides & + // protocol extension overrides. + if cursorInfo["key.overrides"] != nil { + return nil + } + + // Sometimes default protocol implementations don't have `key.overrides` set but they do have + // `key.related_decls`. + if cursorInfo["key.related_decls"] != nil { + return nil + } + + // Skip CodingKeys as they are used + if kind == .enum, + cursorInfo.name == "CodingKeys", + let annotatedDecl = cursorInfo["key.annotated_decl"] as? String, + annotatedDecl.contains("usr=\"s:s9CodingKeyP\">CodingKey<") { + return nil + } + + return (usr, Int(offset)) + } + + return nil + } + + private static func referencedUSR(cursorInfo: [String: SourceKitRepresentable]) -> String? { + if let usr = cursorInfo["key.usr"] as? String, + let kind = cursorInfo["key.kind"] as? String, + kind.contains("source.lang.swift.ref") { + return usr + } + + return nil + } + + private static func testCaseUSR(cursorInfo: [String: SourceKitRepresentable]) -> String? { + if let kind = (cursorInfo["key.kind"] as? String).flatMap(SwiftDeclarationKind.init(rawValue:)), + kind == .class, + let annotatedDecl = cursorInfo["key.annotated_decl"] as? String, + annotatedDecl.contains("XCTestCase"), + let usr = cursorInfo["key.usr"] as? String { + return usr + } + + return nil + } + + private static func aclAtOffset(_ offset: Int64, substructureElement: [String: SourceKitRepresentable]) -> String? { + if let nameOffset = substructureElement["key.nameoffset"] as? Int64, + nameOffset == offset, + let acl = substructureElement["key.accessibility"] as? String { + return acl + } + if let substructure = substructureElement[SwiftDocKey.substructure.rawValue] as? [SourceKitRepresentable] { + let nestedSubstructure = substructure.compactMap({ $0 as? [String: SourceKitRepresentable] }) + for child in nestedSubstructure { + if let acl = File.aclAtOffset(offset, substructureElement: child) { + return acl + } + } + } + return nil + } +} + +// Skip initializers, deinit, enum cases and subscripts since we can't reliably detect if they're used. +private let declarationKindsToSkip: Set = [ + .functionConstructor, + .functionDestructor, + .enumelement, + .functionSubscript +] + +/// Skip syntax kinds that won't respond to cursor info requests. +private let syntaxKindsToSkip: Set = [ + .attributeBuiltin, + .attributeID, + .comment, + .commentMark, + .commentURL, + .buildconfigID, + .buildconfigKeyword, + .docComment, + .docCommentField, + .keyword, + .number, + .string, + .stringInterpolationAnchor +] diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedPrivateDeclarationRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedPrivateDeclarationRule.swift deleted file mode 100644 index c9ac3f3485..0000000000 --- a/Source/SwiftLintFramework/Rules/Lint/UnusedPrivateDeclarationRule.swift +++ /dev/null @@ -1,173 +0,0 @@ -import Foundation -import SourceKittenFramework - -public struct UnusedPrivateDeclarationRule: AutomaticTestableRule, ConfigurationProviderRule, AnalyzerRule { - public var configuration = SeverityConfiguration(.warning) - - public init() {} - - public static let description = RuleDescription( - identifier: "unused_private_declaration", - name: "Unused Private Declaration", - description: "Private declarations should be referenced in that file.", - kind: .lint, - nonTriggeringExamples: [ - """ - private let kConstant = 0 - _ = kConstant - """, - """ - struct ResponseModel: Codable { - let items: [Item] - - private enum CodingKeys: String, CodingKey { - case items = "ResponseItems" - } - } - """, - """ - class ResponseModel { - @objc private func foo() { - } - } - """ - ], - triggeringExamples: [ - """ - private let ↓kConstant = 0 - """, - """ - struct ResponseModel: Codable { - let items: [Item] - - private enum ↓CodingKeys: String { - case items = "ResponseItems" - } - } - """ - ], - requiresFileOnDisk: true - ) - - public func validate(file: File, compilerArguments: [String]) -> [StyleViolation] { - return violationOffsets(in: file, compilerArguments: compilerArguments).map { - StyleViolation(ruleDescription: type(of: self).description, - severity: configuration.severity, - location: Location(file: file, byteOffset: $0)) - } - } - - private func violationOffsets(in file: File, compilerArguments: [String]) -> [Int] { - guard !compilerArguments.isEmpty else { - queuedPrintError(""" - Attempted to lint file at path '\(file.path ?? "...")' with the \ - \(type(of: self).description.identifier) rule without any compiler arguments. - """) - return [] - } - - let allCursorInfo = file.allCursorInfo(compilerArguments: compilerArguments) - let privateDeclarationUSRs = File.declaredUSRs(allCursorInfo: allCursorInfo, acls: [.private, .fileprivate]) - let referencedUSRs = Set(File.referencedUSRs(allCursorInfo: allCursorInfo)) - let unusedPrivateDeclarations = privateDeclarationUSRs.filter { !referencedUSRs.contains($0.usr) } - return unusedPrivateDeclarations.map { $0.nameOffset } - } -} - -// MARK: - File Extensions - -private extension File { - func allCursorInfo(compilerArguments: [String]) -> [[String: SourceKitRepresentable]] { - guard let path = path, let editorOpen = try? Request.editorOpen(file: self).sendIfNotDisabled() else { - return [] - } - - return syntaxMap.tokens.compactMap { token in - let offset = Int64(token.offset) - var cursorInfo = try? Request.cursorInfo(file: path, offset: offset, - arguments: compilerArguments).sendIfNotDisabled() - if let acl = File.aclAtOffset(offset, substructureElement: editorOpen) { - cursorInfo?["key.accessibility"] = acl - } - cursorInfo?["swiftlint.offset"] = offset - return cursorInfo - } - } - - static func declaredUSRs(allCursorInfo: [[String: SourceKitRepresentable]], - acls: [AccessControlLevel]) -> [(usr: String, nameOffset: Int)] { - return allCursorInfo.compactMap { declaredUSRAndOffset(cursorInfo: $0, acls: acls) } - } - - static func referencedUSRs(allCursorInfo: [[String: SourceKitRepresentable]]) -> [String] { - return allCursorInfo.compactMap(referencedUSR) - } - - private static func declaredUSRAndOffset(cursorInfo: [String: SourceKitRepresentable], - acls: [AccessControlLevel]) -> (usr: String, nameOffset: Int)? { - if let offset = cursorInfo["swiftlint.offset"] as? Int64, - let usr = cursorInfo["key.usr"] as? String, - let kind = (cursorInfo["key.kind"] as? String).flatMap(SwiftDeclarationKind.init(rawValue:)), - !declarationKindsToSkip.contains(kind), - let acl = (cursorInfo["key.accessibility"] as? String).flatMap(AccessControlLevel.init(rawValue:)), - acls.contains(acl) { - // Skip declarations marked as @IBOutlet, @IBAction or @objc - // since those might not be referenced in code, but only dynamically (e.g. Interface Builder) - if let annotatedDecl = cursorInfo["key.annotated_decl"] as? String, - ["@IBOutlet", "@IBAction", "@objc", "@IBInspectable"].contains(where: annotatedDecl.contains) { - return nil - } - // Skip declarations that override another. This works for both subclass overrides & - // protocol extension overrides. - if cursorInfo["key.overrides"] != nil { - return nil - } - - // Skip CodingKeys as they are used - if kind == .enum, - cursorInfo.name == "CodingKeys", - let annotatedDecl = cursorInfo["key.annotated_decl"] as? String, - annotatedDecl.contains("usr=\"s:s9CodingKeyP\">CodingKey<") { - return nil - } - return (usr, Int(offset)) - } - - return nil - } - - private static func referencedUSR(cursorInfo: [String: SourceKitRepresentable]) -> String? { - if let usr = cursorInfo["key.usr"] as? String, - let kind = cursorInfo["key.kind"] as? String, - kind.contains("source.lang.swift.ref") { - return usr - } - - return nil - } - - private static func aclAtOffset(_ offset: Int64, substructureElement: [String: SourceKitRepresentable]) -> String? { - if let nameOffset = substructureElement["key.nameoffset"] as? Int64, - nameOffset == offset, - let acl = substructureElement["key.accessibility"] as? String { - return acl - } - if let substructure = substructureElement[SwiftDocKey.substructure.rawValue] as? [SourceKitRepresentable] { - let nestedSubstructure = substructure.compactMap({ $0 as? [String: SourceKitRepresentable] }) - for child in nestedSubstructure { - if let acl = File.aclAtOffset(offset, substructureElement: child) { - return acl - } - } - } - return nil - } -} - -// Skip initializers, deinit, enum cases and subscripts since we can't reliably detect if they're used. -private let declarationKindsToSkip: Set = [ - .functionConstructor, - .functionDestructor, - .enumelement, - .functionSubscript -] diff --git a/Source/SwiftLintFramework/Rules/RuleConfigurations/UnusedDeclarationConfiguration.swift b/Source/SwiftLintFramework/Rules/RuleConfigurations/UnusedDeclarationConfiguration.swift new file mode 100644 index 0000000000..146e65bc62 --- /dev/null +++ b/Source/SwiftLintFramework/Rules/RuleConfigurations/UnusedDeclarationConfiguration.swift @@ -0,0 +1,43 @@ +private enum ConfigurationKey: String { + case severity = "severity" + case includePublicAndOpen = "include_public_and_open" +} + +public struct UnusedDeclarationConfiguration: RuleConfiguration, Equatable { + private(set) var includePublicAndOpen: Bool + private(set) var severity: ViolationSeverity + + public var consoleDescription: String { + return "\(ConfigurationKey.severity.rawValue): \(severity.rawValue), " + + "\(ConfigurationKey.includePublicAndOpen.rawValue): \(includePublicAndOpen)" + } + + public init(severity: ViolationSeverity, includePublicAndOpen: Bool) { + self.includePublicAndOpen = includePublicAndOpen + self.severity = severity + } + + public mutating func apply(configuration: Any) throws { + guard let configDict = configuration as? [String: Any], !configDict.isEmpty else { + throw ConfigurationError.unknownConfiguration + } + + for (string, value) in configDict { + guard let key = ConfigurationKey(rawValue: string) else { + throw ConfigurationError.unknownConfiguration + } + switch (key, value) { + case (.severity, let stringValue as String): + if let severityValue = ViolationSeverity(rawValue: stringValue) { + severity = severityValue + } else { + throw ConfigurationError.unknownConfiguration + } + case (.includePublicAndOpen, let boolValue as Bool): + includePublicAndOpen = boolValue + default: + throw ConfigurationError.unknownConfiguration + } + } + } +} diff --git a/SwiftLint.xcodeproj/project.pbxproj b/SwiftLint.xcodeproj/project.pbxproj index b7a3624ad5..219f6ff021 100644 --- a/SwiftLint.xcodeproj/project.pbxproj +++ b/SwiftLint.xcodeproj/project.pbxproj @@ -177,11 +177,11 @@ 85DA81321D6B471000951BC4 /* MarkRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 856651A61D6B395F005E6B29 /* MarkRule.swift */; }; 8B01E4FD20A41C8700C9233E /* FunctionParameterCountConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B01E4FB20A4183C00C9233E /* FunctionParameterCountConfiguration.swift */; }; 8B01E50220A4349100C9233E /* FunctionParameterCountRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B01E4FF20A4340A00C9233E /* FunctionParameterCountRuleTests.swift */; }; + 8F0856EB22DA8508001FF4D4 /* UnusedDeclarationRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0856EA22DA8508001FF4D4 /* UnusedDeclarationRule.swift */; }; 8F2CC1CB20A6A070006ED34F /* FileNameConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2CC1CA20A6A070006ED34F /* FileNameConfiguration.swift */; }; 8F2CC1CD20A6A189006ED34F /* FileNameRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2CC1CC20A6A189006ED34F /* FileNameRuleTests.swift */; }; 8F6AA75B211905B8009BA28A /* LintableFilesVisitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F6AA75A211905B8009BA28A /* LintableFilesVisitor.swift */; }; 8F6AA75D21190830009BA28A /* CompilerArgumentsExtractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F6AA75C21190830009BA28A /* CompilerArgumentsExtractor.swift */; }; - 8F6B3154213CDCD100858E44 /* UnusedPrivateDeclarationRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F6B3153213CDCD100858E44 /* UnusedPrivateDeclarationRule.swift */; }; 8F715B83213B528B00427BD9 /* UnusedImportRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F715B82213B528B00427BD9 /* UnusedImportRule.swift */; }; 8F8050821FFE0CBB006F5B93 /* Configuration+IndentationStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F8050811FFE0CBB006F5B93 /* Configuration+IndentationStyle.swift */; }; 8FC8523B2117BDDE0015269B /* ExplicitSelfRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FC8523A2117BDDE0015269B /* ExplicitSelfRule.swift */; }; @@ -189,6 +189,7 @@ 8FD216CC205584AF008ED13F /* CharacterSet+SwiftLint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD216CB205584AF008ED13F /* CharacterSet+SwiftLint.swift */; }; 8FDF482C2122476D00521605 /* AnalyzeCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FDF482B2122476D00521605 /* AnalyzeCommand.swift */; }; 8FDF482E21234BFF00521605 /* LintOrAnalyzeCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FDF482D21234BFF00521605 /* LintOrAnalyzeCommand.swift */; }; + 8FE3CCBC22DBF8D000B8EA87 /* UnusedDeclarationConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FE3CCBB22DBF8D000B8EA87 /* UnusedDeclarationConfiguration.swift */; }; 92CCB2D71E1EEFA300C8E5A3 /* UnusedOptionalBindingRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92CCB2D61E1EEFA300C8E5A3 /* UnusedOptionalBindingRule.swift */; }; 93E0C3CE1D67BD7F007FA25D /* ConditionalReturnsOnNewlineRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93E0C3CD1D67BD7F007FA25D /* ConditionalReturnsOnNewlineRule.swift */; }; A1A6F3F21EE319ED00A9F9E2 /* ObjectLiteralConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1A6F3F11EE319ED00A9F9E2 /* ObjectLiteralConfiguration.swift */; }; @@ -650,11 +651,11 @@ 856651A61D6B395F005E6B29 /* MarkRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkRule.swift; sourceTree = ""; }; 8B01E4FB20A4183C00C9233E /* FunctionParameterCountConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FunctionParameterCountConfiguration.swift; sourceTree = ""; }; 8B01E4FF20A4340A00C9233E /* FunctionParameterCountRuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FunctionParameterCountRuleTests.swift; sourceTree = ""; }; + 8F0856EA22DA8508001FF4D4 /* UnusedDeclarationRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnusedDeclarationRule.swift; sourceTree = ""; }; 8F2CC1CA20A6A070006ED34F /* FileNameConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileNameConfiguration.swift; sourceTree = ""; }; 8F2CC1CC20A6A189006ED34F /* FileNameRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileNameRuleTests.swift; sourceTree = ""; }; 8F6AA75A211905B8009BA28A /* LintableFilesVisitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LintableFilesVisitor.swift; sourceTree = ""; }; 8F6AA75C21190830009BA28A /* CompilerArgumentsExtractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompilerArgumentsExtractor.swift; sourceTree = ""; }; - 8F6B3153213CDCD100858E44 /* UnusedPrivateDeclarationRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnusedPrivateDeclarationRule.swift; sourceTree = ""; }; 8F715B82213B528B00427BD9 /* UnusedImportRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnusedImportRule.swift; sourceTree = ""; }; 8F8050811FFE0CBB006F5B93 /* Configuration+IndentationStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Configuration+IndentationStyle.swift"; sourceTree = ""; }; 8FC8523A2117BDDE0015269B /* ExplicitSelfRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExplicitSelfRule.swift; sourceTree = ""; }; @@ -662,6 +663,7 @@ 8FD216CB205584AF008ED13F /* CharacterSet+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CharacterSet+SwiftLint.swift"; sourceTree = ""; }; 8FDF482B2122476D00521605 /* AnalyzeCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnalyzeCommand.swift; sourceTree = ""; }; 8FDF482D21234BFF00521605 /* LintOrAnalyzeCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LintOrAnalyzeCommand.swift; sourceTree = ""; }; + 8FE3CCBB22DBF8D000B8EA87 /* UnusedDeclarationConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnusedDeclarationConfiguration.swift; sourceTree = ""; }; 92CCB2D61E1EEFA300C8E5A3 /* UnusedOptionalBindingRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnusedOptionalBindingRule.swift; sourceTree = ""; }; 93E0C3CD1D67BD7F007FA25D /* ConditionalReturnsOnNewlineRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConditionalReturnsOnNewlineRule.swift; sourceTree = ""; }; A1A6F3F11EE319ED00A9F9E2 /* ObjectLiteralConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectLiteralConfiguration.swift; sourceTree = ""; }; @@ -1023,6 +1025,7 @@ BF48D2D61CBCCA5F0080BDAE /* TrailingWhitespaceConfiguration.swift */, 82DB55FF21008F54001C62FF /* TypeContentsOrderConfiguration.swift */, CE8178EB1EAC02CD0063186E /* UnusedOptionalBindingConfiguration.swift */, + 8FE3CCBB22DBF8D000B8EA87 /* UnusedDeclarationConfiguration.swift */, 006204DA1E1E48F900FFFBE1 /* VerticalWhitespaceConfiguration.swift */, ); path = RuleConfigurations; @@ -1127,9 +1130,9 @@ 7565E5F02262BA0900B0597C /* UnusedCaptureListRule.swift */, D40AD0891E032F9700F48C30 /* UnusedClosureParameterRule.swift */, D4D7320C21E15ED4001C07D9 /* UnusedControlFlowLabelRule.swift */, + 8F0856EA22DA8508001FF4D4 /* UnusedDeclarationRule.swift */, 8F715B82213B528B00427BD9 /* UnusedImportRule.swift */, D4BED5F72278AECC00D86BCE /* UnownedVariableCaptureRule.swift */, - 8F6B3153213CDCD100858E44 /* UnusedPrivateDeclarationRule.swift */, D4B3409C21F16B110038C79A /* UnusedSetterValueRule.swift */, D442541E1DB87C3D00492EA4 /* ValidIBInspectableRule.swift */, 094384FF1D5D2382009168CF /* WeakDelegateRule.swift */, @@ -1941,7 +1944,6 @@ E86623671F1D377900AAA3A2 /* Configuration+Parsing.swift in Sources */, 3BCC04CD1C4F5694006073C3 /* ConfigurationError.swift in Sources */, D4C4A34E1DEA877200E0E04C /* FileHeaderRule.swift in Sources */, - 8F6B3154213CDCD100858E44 /* UnusedPrivateDeclarationRule.swift in Sources */, 1894D746207D585400BD94CF /* SwiftDeclarationAttributeKind+Swiftlint.swift in Sources */, D4E92D1F2137B4C9002EDD48 /* IdenticalOperandsRule.swift in Sources */, 6250D32A1ED4DFEB00735129 /* MultilineParametersRule.swift in Sources */, @@ -1960,6 +1962,7 @@ 29FC197A21382C07006D208C /* DuplicateImportsRuleExamples.swift in Sources */, 83D71E281B131ECE000395DE /* RuleDescription.swift in Sources */, D4470D571EB69225008A1B2E /* ImplicitReturnRule.swift in Sources */, + 8FE3CCBC22DBF8D000B8EA87 /* UnusedDeclarationConfiguration.swift in Sources */, 3B12C9C51C322032000B423F /* MasterRuleList.swift in Sources */, E812249C1B04FADC001783D2 /* Linter.swift in Sources */, 1F11B3CF1C252F23002E8FA8 /* ClosingBraceRule.swift in Sources */, @@ -2134,6 +2137,7 @@ E88198421BEA929F00333A11 /* NestingRule.swift in Sources */, D46A317F1F1CEDCD00AF914A /* UnneededParenthesesInClosureArgumentRule.swift in Sources */, D4470D591EB6B4D1008A1B2E /* EmptyEnumArgumentsRule.swift in Sources */, + 8F0856EB22DA8508001FF4D4 /* UnusedDeclarationRule.swift in Sources */, 264E080F2248BA2800ADC4C5 /* RuleStorage.swift in Sources */, 627BC48D1F9405160004A6C2 /* QuickDiscouragedFocusedTestRule.swift in Sources */, 3BB47D851C51D80000AE6A10 /* NSRegularExpression+SwiftLint.swift in Sources */, diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 04fa8c8a3f..a59563f45c 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -1390,6 +1390,12 @@ extension UnusedControlFlowLabelRuleTests { ] } +extension UnusedDeclarationRuleTests { + static var allTests: [(String, (UnusedDeclarationRuleTests) -> () throws -> Void)] = [ + ("testWithDefaultConfiguration", testWithDefaultConfiguration) + ] +} + extension UnusedEnumeratedRuleTests { static var allTests: [(String, (UnusedEnumeratedRuleTests) -> () throws -> Void)] = [ ("testWithDefaultConfiguration", testWithDefaultConfiguration) @@ -1409,12 +1415,6 @@ extension UnusedOptionalBindingRuleTests { ] } -extension UnusedPrivateDeclarationRuleTests { - static var allTests: [(String, (UnusedPrivateDeclarationRuleTests) -> () throws -> Void)] = [ - ("testWithDefaultConfiguration", testWithDefaultConfiguration) - ] -} - extension UnusedSetterValueRuleTests { static var allTests: [(String, (UnusedSetterValueRuleTests) -> () throws -> Void)] = [ ("testWithDefaultConfiguration", testWithDefaultConfiguration) @@ -1710,10 +1710,10 @@ XCTMain([ testCase(UnusedCaptureListRuleTests.allTests), testCase(UnusedClosureParameterRuleTests.allTests), testCase(UnusedControlFlowLabelRuleTests.allTests), + testCase(UnusedDeclarationRuleTests.allTests), testCase(UnusedEnumeratedRuleTests.allTests), testCase(UnusedImportRuleTests.allTests), testCase(UnusedOptionalBindingRuleTests.allTests), - testCase(UnusedPrivateDeclarationRuleTests.allTests), testCase(UnusedSetterValueRuleTests.allTests), testCase(ValidIBInspectableRuleTests.allTests), testCase(VerticalParameterAlignmentOnCallRuleTests.allTests), diff --git a/Tests/SwiftLintFrameworkTests/AutomaticRuleTests.generated.swift b/Tests/SwiftLintFrameworkTests/AutomaticRuleTests.generated.swift index 4b58223d7d..06a84e7fd2 100644 --- a/Tests/SwiftLintFrameworkTests/AutomaticRuleTests.generated.swift +++ b/Tests/SwiftLintFrameworkTests/AutomaticRuleTests.generated.swift @@ -714,21 +714,21 @@ class UnusedControlFlowLabelRuleTests: XCTestCase { } } -class UnusedEnumeratedRuleTests: XCTestCase { +class UnusedDeclarationRuleTests: XCTestCase { func testWithDefaultConfiguration() { - verifyRule(UnusedEnumeratedRule.description) + verifyRule(UnusedDeclarationRule.description) } } -class UnusedImportRuleTests: XCTestCase { +class UnusedEnumeratedRuleTests: XCTestCase { func testWithDefaultConfiguration() { - verifyRule(UnusedImportRule.description) + verifyRule(UnusedEnumeratedRule.description) } } -class UnusedPrivateDeclarationRuleTests: XCTestCase { +class UnusedImportRuleTests: XCTestCase { func testWithDefaultConfiguration() { - verifyRule(UnusedPrivateDeclarationRule.description) + verifyRule(UnusedImportRule.description) } } From a57a1ee9218f2137eabd8d8ce0d604c6ff49fc7f Mon Sep 17 00:00:00 2001 From: JP Simard Date: Thu, 18 Jul 2019 15:20:46 -0700 Subject: [PATCH 2/4] Fix invalid Swift program used in triggering examples Which was causing tests to fail on Swift 4.x --- Source/SwiftLintFramework/Rules/Lint/UnusedDeclarationRule.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedDeclarationRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedDeclarationRule.swift index 8617e411a0..8c0277e4da 100644 --- a/Source/SwiftLintFramework/Rules/Lint/UnusedDeclarationRule.swift +++ b/Source/SwiftLintFramework/Rules/Lint/UnusedDeclarationRule.swift @@ -49,6 +49,7 @@ public struct UnusedDeclarationRule: AutomaticTestableRule, ConfigurationProvide let ↓kConstant = 0 """, """ + struct Item {} struct ↓ResponseModel: Codable { let ↓items: [Item] From 9a4a8c7004c71042f17fc4e7fb576473cec1022e Mon Sep 17 00:00:00 2001 From: JP Simard Date: Thu, 18 Jul 2019 15:27:00 -0700 Subject: [PATCH 3/4] Update Rules.md --- Rules.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Rules.md b/Rules.md index 50462df92e..7efbef894f 100644 --- a/Rules.md +++ b/Rules.md @@ -23660,6 +23660,7 @@ let ↓kConstant = 0 ``` ```swift +struct Item {} struct ↓ResponseModel: Codable { let ↓items: [Item] From 6be580ca3c7a15e14f2273e7622f2d13e3e2228a Mon Sep 17 00:00:00 2001 From: JP Simard Date: Thu, 18 Jul 2019 17:48:01 -0700 Subject: [PATCH 4/4] Remove unused declarations and imports --- .../Extensions/Dictionary+SwiftLint.swift | 16 ---------------- .../ConfigurationAliasesTests.swift | 2 -- .../ConfigurationTests+Nested.swift | 1 - .../ConfigurationTests+ProjectMock.swift | 1 - .../CustomRulesTests.swift | 1 - .../CyclomaticComplexityConfigurationTests.swift | 1 - .../CyclomaticComplexityRuleTests.swift | 1 - .../DeploymentTargetConfigurationTests.swift | 1 - .../DisableAllTests.swift | 1 - .../DiscouragedDirectInitRuleTests.swift | 1 - Tests/SwiftLintFrameworkTests/GlobTests.swift | 1 - ...itlyUnwrappedOptionalConfigurationTests.swift | 1 - .../ImplicitlyUnwrappedOptionalRuleTests.swift | 1 - .../LineLengthConfigurationTests.swift | 1 - .../LineLengthRuleTests.swift | 1 - Tests/SwiftLintFrameworkTests/RegionTests.swift | 1 - .../RequiredEnumCaseRuleTestCase.swift | 1 - .../SourceKitCrashTests.swift | 1 - .../UnusedOptionalBindingRuleTests.swift | 1 - .../YamlSwiftLintTests.swift | 1 - 20 files changed, 36 deletions(-) diff --git a/Source/SwiftLintFramework/Extensions/Dictionary+SwiftLint.swift b/Source/SwiftLintFramework/Extensions/Dictionary+SwiftLint.swift index 5ec32cb6c9..df59b7b3e5 100644 --- a/Source/SwiftLintFramework/Extensions/Dictionary+SwiftLint.swift +++ b/Source/SwiftLintFramework/Extensions/Dictionary+SwiftLint.swift @@ -45,22 +45,6 @@ extension Dictionary where Key: ExpressibleByStringLiteral { var typeName: String? { return self["key.typename"] as? String } - /// Column where the token's declaration begins. - var docColumn: Int? { - return (self["key.doc.column"] as? Int64).flatMap({ Int($0) }) - } - /// Line where the token's declaration begins. - var docLine: Int? { - return (self["key.doc.line"] as? Int64).flatMap({ Int($0) }) - } - /// Parsed scope start. - var docType: Int? { - return (self["key.doc.type"] as? Int64).flatMap({ Int($0) }) - } - /// Parsed scope start end. - var usr: Int? { - return (self["key.usr"] as? Int64).flatMap({ Int($0) }) - } /// Documentation length. var docLength: Int? { return (self["key.doclength"] as? Int64).flatMap({ Int($0) }) diff --git a/Tests/SwiftLintFrameworkTests/ConfigurationAliasesTests.swift b/Tests/SwiftLintFrameworkTests/ConfigurationAliasesTests.swift index b5b42b8a4e..d0886ff6a2 100644 --- a/Tests/SwiftLintFrameworkTests/ConfigurationAliasesTests.swift +++ b/Tests/SwiftLintFrameworkTests/ConfigurationAliasesTests.swift @@ -1,5 +1,3 @@ -import Foundation -import SourceKittenFramework @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/ConfigurationTests+Nested.swift b/Tests/SwiftLintFrameworkTests/ConfigurationTests+Nested.swift index 8b0417a289..7a0dd41e65 100644 --- a/Tests/SwiftLintFrameworkTests/ConfigurationTests+Nested.swift +++ b/Tests/SwiftLintFrameworkTests/ConfigurationTests+Nested.swift @@ -1,4 +1,3 @@ -import Foundation import SourceKittenFramework @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/ConfigurationTests+ProjectMock.swift b/Tests/SwiftLintFrameworkTests/ConfigurationTests+ProjectMock.swift index 33d87a7f2e..a4294e4801 100644 --- a/Tests/SwiftLintFrameworkTests/ConfigurationTests+ProjectMock.swift +++ b/Tests/SwiftLintFrameworkTests/ConfigurationTests+ProjectMock.swift @@ -1,4 +1,3 @@ -import Foundation @testable import SwiftLintFramework extension ConfigurationTests { diff --git a/Tests/SwiftLintFrameworkTests/CustomRulesTests.swift b/Tests/SwiftLintFrameworkTests/CustomRulesTests.swift index a15719e40b..2e95683ab7 100644 --- a/Tests/SwiftLintFrameworkTests/CustomRulesTests.swift +++ b/Tests/SwiftLintFrameworkTests/CustomRulesTests.swift @@ -1,4 +1,3 @@ -import Foundation import SourceKittenFramework @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/CyclomaticComplexityConfigurationTests.swift b/Tests/SwiftLintFrameworkTests/CyclomaticComplexityConfigurationTests.swift index 9b2ef1a342..ceac8b10d0 100644 --- a/Tests/SwiftLintFrameworkTests/CyclomaticComplexityConfigurationTests.swift +++ b/Tests/SwiftLintFrameworkTests/CyclomaticComplexityConfigurationTests.swift @@ -1,4 +1,3 @@ -import SourceKittenFramework @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/CyclomaticComplexityRuleTests.swift b/Tests/SwiftLintFrameworkTests/CyclomaticComplexityRuleTests.swift index ab74ad2ace..5fe9d5e2e4 100644 --- a/Tests/SwiftLintFrameworkTests/CyclomaticComplexityRuleTests.swift +++ b/Tests/SwiftLintFrameworkTests/CyclomaticComplexityRuleTests.swift @@ -1,4 +1,3 @@ -import Foundation import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/DeploymentTargetConfigurationTests.swift b/Tests/SwiftLintFrameworkTests/DeploymentTargetConfigurationTests.swift index 9bc76f4ebc..34da0d09aa 100644 --- a/Tests/SwiftLintFrameworkTests/DeploymentTargetConfigurationTests.swift +++ b/Tests/SwiftLintFrameworkTests/DeploymentTargetConfigurationTests.swift @@ -1,4 +1,3 @@ -import SourceKittenFramework @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/DisableAllTests.swift b/Tests/SwiftLintFrameworkTests/DisableAllTests.swift index 31f8e91d54..fc04b79ec7 100644 --- a/Tests/SwiftLintFrameworkTests/DisableAllTests.swift +++ b/Tests/SwiftLintFrameworkTests/DisableAllTests.swift @@ -1,5 +1,4 @@ import Foundation -@testable import SwiftLintFramework import XCTest class DisableAllTests: XCTestCase { diff --git a/Tests/SwiftLintFrameworkTests/DiscouragedDirectInitRuleTests.swift b/Tests/SwiftLintFrameworkTests/DiscouragedDirectInitRuleTests.swift index dbaac94422..3acca1bf7d 100644 --- a/Tests/SwiftLintFrameworkTests/DiscouragedDirectInitRuleTests.swift +++ b/Tests/SwiftLintFrameworkTests/DiscouragedDirectInitRuleTests.swift @@ -1,4 +1,3 @@ -import Foundation import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/GlobTests.swift b/Tests/SwiftLintFrameworkTests/GlobTests.swift index 94ef1c9257..c435d2e1a0 100644 --- a/Tests/SwiftLintFrameworkTests/GlobTests.swift +++ b/Tests/SwiftLintFrameworkTests/GlobTests.swift @@ -1,5 +1,4 @@ import Foundation -import SourceKittenFramework @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/ImplicitlyUnwrappedOptionalConfigurationTests.swift b/Tests/SwiftLintFrameworkTests/ImplicitlyUnwrappedOptionalConfigurationTests.swift index b2a0845578..d4beeffe5c 100644 --- a/Tests/SwiftLintFrameworkTests/ImplicitlyUnwrappedOptionalConfigurationTests.swift +++ b/Tests/SwiftLintFrameworkTests/ImplicitlyUnwrappedOptionalConfigurationTests.swift @@ -1,4 +1,3 @@ -import SourceKittenFramework @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/ImplicitlyUnwrappedOptionalRuleTests.swift b/Tests/SwiftLintFrameworkTests/ImplicitlyUnwrappedOptionalRuleTests.swift index 12accdc972..18624361cf 100644 --- a/Tests/SwiftLintFrameworkTests/ImplicitlyUnwrappedOptionalRuleTests.swift +++ b/Tests/SwiftLintFrameworkTests/ImplicitlyUnwrappedOptionalRuleTests.swift @@ -1,4 +1,3 @@ -import Foundation @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/LineLengthConfigurationTests.swift b/Tests/SwiftLintFrameworkTests/LineLengthConfigurationTests.swift index 8b614af5cc..5e07654327 100644 --- a/Tests/SwiftLintFrameworkTests/LineLengthConfigurationTests.swift +++ b/Tests/SwiftLintFrameworkTests/LineLengthConfigurationTests.swift @@ -1,4 +1,3 @@ -import SourceKittenFramework @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/LineLengthRuleTests.swift b/Tests/SwiftLintFrameworkTests/LineLengthRuleTests.swift index 92b58874ec..c02a78abf1 100644 --- a/Tests/SwiftLintFrameworkTests/LineLengthRuleTests.swift +++ b/Tests/SwiftLintFrameworkTests/LineLengthRuleTests.swift @@ -1,4 +1,3 @@ -import SourceKittenFramework @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/RegionTests.swift b/Tests/SwiftLintFrameworkTests/RegionTests.swift index 46ca4148dc..2399557e82 100644 --- a/Tests/SwiftLintFrameworkTests/RegionTests.swift +++ b/Tests/SwiftLintFrameworkTests/RegionTests.swift @@ -1,4 +1,3 @@ -import Foundation import SourceKittenFramework @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/RequiredEnumCaseRuleTestCase.swift b/Tests/SwiftLintFrameworkTests/RequiredEnumCaseRuleTestCase.swift index cb00d4cdcd..55ae2f4900 100644 --- a/Tests/SwiftLintFrameworkTests/RequiredEnumCaseRuleTestCase.swift +++ b/Tests/SwiftLintFrameworkTests/RequiredEnumCaseRuleTestCase.swift @@ -1,4 +1,3 @@ -import Foundation @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/SourceKitCrashTests.swift b/Tests/SwiftLintFrameworkTests/SourceKitCrashTests.swift index 8a285f9f84..da665fa23c 100644 --- a/Tests/SwiftLintFrameworkTests/SourceKitCrashTests.swift +++ b/Tests/SwiftLintFrameworkTests/SourceKitCrashTests.swift @@ -1,4 +1,3 @@ -import Foundation import SourceKittenFramework @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/UnusedOptionalBindingRuleTests.swift b/Tests/SwiftLintFrameworkTests/UnusedOptionalBindingRuleTests.swift index 1c31a1dddc..01fdd5513e 100644 --- a/Tests/SwiftLintFrameworkTests/UnusedOptionalBindingRuleTests.swift +++ b/Tests/SwiftLintFrameworkTests/UnusedOptionalBindingRuleTests.swift @@ -1,4 +1,3 @@ -import Foundation @testable import SwiftLintFramework import XCTest diff --git a/Tests/SwiftLintFrameworkTests/YamlSwiftLintTests.swift b/Tests/SwiftLintFrameworkTests/YamlSwiftLintTests.swift index 5c3f606210..1f8b43f2d6 100644 --- a/Tests/SwiftLintFrameworkTests/YamlSwiftLintTests.swift +++ b/Tests/SwiftLintFrameworkTests/YamlSwiftLintTests.swift @@ -1,5 +1,4 @@ import Foundation -@testable import SwiftLintFramework import XCTest import Yams