diff --git a/CHANGELOG.md b/CHANGELOG.md index 91f2dd3619..91649e37f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,11 @@ [Marcelo Fabri](https://github.com/marcelofabri) [#2678](https://github.com/realm/SwiftLint/issues/2678) +* Add `unused_capture_list` rule to ensure that all references in a closure + capture list are used. + [Dalton Claybrook](https://github.com/daltonclaybrook) + [#2715](https://github.com/realm/SwiftLint/issues/2715) + #### Bug Fixes * Fix bug where SwiftLint ignores excluded files list in a nested configuration diff --git a/Rules.md b/Rules.md index 55d4429847..80634cddea 100644 --- a/Rules.md +++ b/Rules.md @@ -154,6 +154,7 @@ * [Unneeded Break in Switch](#unneeded-break-in-switch) * [Unneeded Parentheses in Closure Argument](#unneeded-parentheses-in-closure-argument) * [Untyped Error in Catch](#untyped-error-in-catch) +* [Unused Capture List](#unused-capture-list) * [Unused Closure Parameter](#unused-closure-parameter) * [Unused Control Flow Label](#unused-control-flow-label) * [Unused Enumerated](#unused-enumerated) @@ -22910,6 +22911,83 @@ do { +## Unused Capture List + +Identifier | Enabled by default | Supports autocorrection | Kind | Analyzer | Minimum Swift Compiler Version +--- | --- | --- | --- | --- | --- +`unused_capture_list` | Enabled | No | lint | No | 4.2.0 + +Unused reference in a capture list should be removed. + +### Examples + +
+Non Triggering Examples + +```swift +[1, 2].map { [weak self] num in + self?.handle(num) +} +``` + +```swift +let failure: Failure = { [weak self, unowned delegate = self.delegate!] foo in + delegate.handle(foo, self) +} +``` + +```swift +numbers.forEach({ + [weak handler] in + handler?.handle($0) +}) +``` + +```swift +{ [foo] in foo.bar() }() +``` + +```swift +sizes.max().flatMap { [(offset: offset, size: $0)] } ?? [] +``` + +
+
+Triggering Examples + +```swift +[1, 2].map { [↓weak self] num in + print(num) +} +``` + +```swift +let failure: Failure = { [weak self, ↓unowned delegate = self.delegate!] foo in + self?.handle(foo) +} +``` + +```swift +let failure: Failure = { [↓weak self, ↓unowned delegate = self.delegate!] foo in + print(foo) +} +``` + +```swift +numbers.forEach({ + [weak handler] in + print($0) +}) +``` + +```swift +{ [↓foo] in _ }() +``` + +
+ + + ## Unused Closure Parameter Identifier | Enabled by default | Supports autocorrection | Kind | Analyzer | Minimum Swift Compiler Version diff --git a/Source/SwiftLintFramework/Models/MasterRuleList.swift b/Source/SwiftLintFramework/Models/MasterRuleList.swift index 56d3215890..72f0b15059 100644 --- a/Source/SwiftLintFramework/Models/MasterRuleList.swift +++ b/Source/SwiftLintFramework/Models/MasterRuleList.swift @@ -155,6 +155,7 @@ public let masterRuleList = RuleList(rules: [ UnneededBreakInSwitchRule.self, UnneededParenthesesInClosureArgumentRule.self, UntypedErrorInCatchRule.self, + UnusedCaptureListRule.self, UnusedClosureParameterRule.self, UnusedControlFlowLabelRule.self, UnusedEnumeratedRule.self, diff --git a/Source/SwiftLintFramework/Rules/Lint/UnusedCaptureListRule.swift b/Source/SwiftLintFramework/Rules/Lint/UnusedCaptureListRule.swift new file mode 100644 index 0000000000..6292bc996c --- /dev/null +++ b/Source/SwiftLintFramework/Rules/Lint/UnusedCaptureListRule.swift @@ -0,0 +1,142 @@ +import Foundation +import SourceKittenFramework + +public struct UnusedCaptureListRule: ASTRule, ConfigurationProviderRule, AutomaticTestableRule { + public var configuration = SeverityConfiguration(.warning) + + public init() {} + + public static var description = RuleDescription( + identifier: "unused_capture_list", + name: "Unused Capture List", + description: "Unused reference in a capture list should be removed.", + kind: .lint, + minSwiftVersion: .fourDotTwo, + nonTriggeringExamples: [ + """ + [1, 2].map { [weak self] num in + self?.handle(num) + } + """, + """ + let failure: Failure = { [weak self, unowned delegate = self.delegate!] foo in + delegate.handle(foo, self) + } + """, + """ + numbers.forEach({ + [weak handler] in + handler?.handle($0) + }) + """, + "{ [foo] in foo.bar() }()", + "sizes.max().flatMap { [(offset: offset, size: $0)] } ?? []" + ], + triggeringExamples: [ + """ + [1, 2].map { [↓weak self] num in + print(num) + } + """, + """ + let failure: Failure = { [weak self, ↓unowned delegate = self.delegate!] foo in + self?.handle(foo) + } + """, + """ + let failure: Failure = { [↓weak self, ↓unowned delegate = self.delegate!] foo in + print(foo) + } + """, + """ + numbers.forEach({ + [weak handler] in + print($0) + }) + """, + "{ [↓foo] in _ }()" + ] + ) + + private let captureListRegex = regex("^\\{\\s*\\[([^\\]]+)\\].*\\bin\\b") + + public func validate(file: File, kind: SwiftExpressionKind, + dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] { + let contents = file.contents.bridge() + guard kind == .closure, + let offset = dictionary.offset, + let length = dictionary.length, + let closureRange = contents.byteRangeToNSRange(start: offset, length: length), + let match = captureListRegex.firstMatch(in: file.contents, options: [], range: closureRange) + else { return [] } + + let captureListRange = match.range(at: 1) + guard captureListRange.location != NSNotFound, + captureListRange.length > 0 else { return [] } + + let captureList = contents.substring(with: captureListRange) + let references = referencesAndLocationsFromCaptureList(captureList) + + let restOfClosureLocation = captureListRange.location + captureListRange.length + 1 + let restOfClosureLength = closureRange.length - (restOfClosureLocation - closureRange.location) + let restOfClosureRange = NSRange(location: restOfClosureLocation, length: restOfClosureLength) + guard let restOfClosureByteRange = contents + .NSRangeToByteRange(start: restOfClosureRange.location, length: restOfClosureRange.length) + else { return [] } + + let identifiers = identifierStrings(in: file, byteRange: restOfClosureByteRange) + return violations(in: file, references: references, + identifiers: identifiers, captureListRange: captureListRange) + } + + // MARK: - Private + + private func referencesAndLocationsFromCaptureList(_ captureList: String) -> [(String, Int)] { + var locationOffset = 0 + return captureList.components(separatedBy: ",") + .reduce(into: [(String, Int)]()) { referencesAndLocations, item in + let item = item.bridge() + let range = item.rangeOfCharacter(from: CharacterSet.whitespacesAndNewlines.inverted) + guard range.location != NSNotFound else { return } + + let location = range.location + locationOffset + locationOffset += item.length + 1 // 1 for comma + let reference = item.components(separatedBy: "=") + .first? + .trimmingCharacters(in: .whitespacesAndNewlines) + .components(separatedBy: .whitespaces) + .last + if let reference = reference { + referencesAndLocations.append((reference, location)) + } + } + } + + private func identifierStrings(in file: File, byteRange: NSRange) -> Set { + let contents = file.contents.bridge() + let identifiers = file.syntaxMap + .tokens(inByteRange: byteRange) + .compactMap { token -> String? in + guard token.type == SyntaxKind.identifier.rawValue || token.type == SyntaxKind.keyword.rawValue, + let range = contents.byteRangeToNSRange(start: token.offset, length: token.length) + else { return nil } + return contents.substring(with: range) + } + return Set(identifiers) + } + + private func violations(in file: File, references: [(String, Int)], + identifiers: Set, captureListRange: NSRange) -> [StyleViolation] { + return references.compactMap { reference, location -> StyleViolation? in + guard !identifiers.contains(reference) else { return nil } + let offset = captureListRange.location + location + let reason = "Unused reference \(reference) in a capture list should be removed." + return StyleViolation( + ruleDescription: type(of: self).description, + severity: configuration.severity, + location: Location(file: file, characterOffset: offset), + reason: reason + ) + } + } +} diff --git a/SwiftLint.xcodeproj/project.pbxproj b/SwiftLint.xcodeproj/project.pbxproj index 7b923861a0..5655aeeae0 100644 --- a/SwiftLint.xcodeproj/project.pbxproj +++ b/SwiftLint.xcodeproj/project.pbxproj @@ -142,33 +142,32 @@ 750BBD0B214180AF007EC437 /* CollectionAlignmentRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7578C915214173BE0080FEC9 /* CollectionAlignmentRuleTests.swift */; }; 75161FDF213B9D73009DE767 /* CollectionAlignmentConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75161FDD213B9D67009DE767 /* CollectionAlignmentConfiguration.swift */; }; 7551DF6D21382C9A00AA1F4D /* ToggleBoolRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7551DF6C21382C9A00AA1F4D /* ToggleBoolRule.swift */; }; + 7565E5F12262BA0900B0597C /* UnusedCaptureListRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7565E5F02262BA0900B0597C /* UnusedCaptureListRule.swift */; }; 756B585D2138ECD300D1A4E9 /* CollectionAlignmentRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 756B585C2138ECD300D1A4E9 /* CollectionAlignmentRule.swift */; }; 787CDE39208E7D41005F3D2F /* SwitchCaseAlignmentConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787CDE38208E7D41005F3D2F /* SwitchCaseAlignmentConfiguration.swift */; }; 787CDE3B208F9C34005F3D2F /* SwitchCaseAlignmentRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787CDE3A208F9C34005F3D2F /* SwitchCaseAlignmentRuleTests.swift */; }; 78F032461D7C877E00BE709A /* OverriddenSuperCallRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78F032441D7C877800BE709A /* OverriddenSuperCallRule.swift */; }; 78F032481D7D614300BE709A /* OverridenSuperCallConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78F032471D7D614300BE709A /* OverridenSuperCallConfiguration.swift */; }; 7C0C2E7A1D2866CB0076435A /* ExplicitInitRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C0C2E791D2866CB0076435A /* ExplicitInitRule.swift */; }; - 820F451E21073D7200AA056A /* ConditionalReturnsOnNewlineRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 820F451D21073D7200AA056A /* ConditionalReturnsOnNewlineRuleTests.swift */; }; - 82144ACC20F640F200B06695 /* VerticalWhitespaceBetweenCasesRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82144ACB20F640F200B06695 /* VerticalWhitespaceBetweenCasesRule.swift */; }; - 823EDC6221020D850070B7CD /* MultilineLiteralBracketsRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 823EDC6121020D850070B7CD /* MultilineLiteralBracketsRule.swift */; }; - 824AB64D2105C39F004B5A8F /* ConditionalReturnsOnNewlineConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824AB64C2105C39F004B5A8F /* ConditionalReturnsOnNewlineConfiguration.swift */; }; 820F451C2107292500AA056A /* TypeContentsOrderRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 820F451B2107292500AA056A /* TypeContentsOrderRuleTests.swift */; }; 820F451E21073D7200AA056A /* ConditionalReturnsOnNewlineRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 820F451D21073D7200AA056A /* ConditionalReturnsOnNewlineRuleTests.swift */; }; + 82144ACC20F640F200B06695 /* VerticalWhitespaceBetweenCasesRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82144ACB20F640F200B06695 /* VerticalWhitespaceBetweenCasesRule.swift */; }; 821F70B7210720C700E2C84F /* FileTypesOrderRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821F70B6210720C700E2C84F /* FileTypesOrderRuleTests.swift */; }; + 823EDC6221020D850070B7CD /* MultilineLiteralBracketsRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 823EDC6121020D850070B7CD /* MultilineLiteralBracketsRule.swift */; }; 824AB64D2105C39F004B5A8F /* ConditionalReturnsOnNewlineConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 824AB64C2105C39F004B5A8F /* ConditionalReturnsOnNewlineConfiguration.swift */; }; 825F19D11EEFF19700969EF1 /* ObjectLiteralRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 825F19D01EEFF19700969EF1 /* ObjectLiteralRuleTests.swift */; }; 827009FD20FE26B700ECA185 /* FileTypesOrderRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827009FC20FE26B700ECA185 /* FileTypesOrderRule.swift */; }; 827009FF20FE26C500ECA185 /* TypeContentsOrderRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827009FE20FE26C500ECA185 /* TypeContentsOrderRule.swift */; }; 827169B31F488181003FB9AF /* ExplicitEnumRawValueRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827169B21F488181003FB9AF /* ExplicitEnumRawValueRule.swift */; }; 827169B51F48D712003FB9AF /* NoGroupingExtensionRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827169B41F48D712003FB9AF /* NoGroupingExtensionRule.swift */; }; - 82F614F22106014500D23904 /* MultilineParametersBracketsRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F614F12106014500D23904 /* MultilineParametersBracketsRule.swift */; }; - 82F614F42106015100D23904 /* MultilineArgumentsBracketsRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F614F32106015100D23904 /* MultilineArgumentsBracketsRule.swift */; }; - 82FE253F20F604AD00295958 /* VerticalWhitespaceOpeningBracesRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82FE253E20F604AD00295958 /* VerticalWhitespaceOpeningBracesRule.swift */; }; - 82FE254120F604CB00295958 /* VerticalWhitespaceClosingBracesRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82FE254020F604CB00295958 /* VerticalWhitespaceClosingBracesRule.swift */; }; 82DB55FE21008F3E001C62FF /* FileTypesOrderConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DB55FD21008F3E001C62FF /* FileTypesOrderConfiguration.swift */; }; 82DB560021008F54001C62FF /* TypeContentsOrderConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DB55FF21008F54001C62FF /* TypeContentsOrderConfiguration.swift */; }; 82EB7885215BAE790042E0FD /* FileTypesOrderRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82EB7883215BAE780042E0FD /* FileTypesOrderRuleExamples.swift */; }; 82EB7886215BAE790042E0FD /* TypeContentsOrderRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82EB7884215BAE780042E0FD /* TypeContentsOrderRuleExamples.swift */; }; + 82F614F22106014500D23904 /* MultilineParametersBracketsRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F614F12106014500D23904 /* MultilineParametersBracketsRule.swift */; }; + 82F614F42106015100D23904 /* MultilineArgumentsBracketsRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F614F32106015100D23904 /* MultilineArgumentsBracketsRule.swift */; }; + 82FE253F20F604AD00295958 /* VerticalWhitespaceOpeningBracesRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82FE253E20F604AD00295958 /* VerticalWhitespaceOpeningBracesRule.swift */; }; + 82FE254120F604CB00295958 /* VerticalWhitespaceClosingBracesRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82FE254020F604CB00295958 /* VerticalWhitespaceClosingBracesRule.swift */; }; 83894F221B0C928A006214E1 /* RulesCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83894F211B0C928A006214E1 /* RulesCommand.swift */; }; 83D71E281B131ECE000395DE /* RuleDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83D71E261B131EB5000395DE /* RuleDescription.swift */; }; 85DA81321D6B471000951BC4 /* MarkRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 856651A61D6B395F005E6B29 /* MarkRule.swift */; }; @@ -607,6 +606,7 @@ 740DF1AF203F5AFC0081F694 /* EmptyStringRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyStringRule.swift; sourceTree = ""; }; 75161FDD213B9D67009DE767 /* CollectionAlignmentConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionAlignmentConfiguration.swift; sourceTree = ""; }; 7551DF6C21382C9A00AA1F4D /* ToggleBoolRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleBoolRule.swift; sourceTree = ""; }; + 7565E5F02262BA0900B0597C /* UnusedCaptureListRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnusedCaptureListRule.swift; sourceTree = ""; }; 756B585C2138ECD300D1A4E9 /* CollectionAlignmentRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionAlignmentRule.swift; sourceTree = ""; }; 7578C915214173BE0080FEC9 /* CollectionAlignmentRuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionAlignmentRuleTests.swift; sourceTree = ""; }; 787CDE38208E7D41005F3D2F /* SwitchCaseAlignmentConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchCaseAlignmentConfiguration.swift; sourceTree = ""; }; @@ -614,27 +614,25 @@ 78F032441D7C877800BE709A /* OverriddenSuperCallRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OverriddenSuperCallRule.swift; sourceTree = ""; }; 78F032471D7D614300BE709A /* OverridenSuperCallConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OverridenSuperCallConfiguration.swift; sourceTree = ""; }; 7C0C2E791D2866CB0076435A /* ExplicitInitRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExplicitInitRule.swift; sourceTree = ""; }; - 820F451D21073D7200AA056A /* ConditionalReturnsOnNewlineRuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionalReturnsOnNewlineRuleTests.swift; sourceTree = ""; }; - 82144ACB20F640F200B06695 /* VerticalWhitespaceBetweenCasesRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalWhitespaceBetweenCasesRule.swift; sourceTree = ""; }; - 823EDC6121020D850070B7CD /* MultilineLiteralBracketsRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineLiteralBracketsRule.swift; sourceTree = ""; }; - 824AB64C2105C39F004B5A8F /* ConditionalReturnsOnNewlineConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionalReturnsOnNewlineConfiguration.swift; sourceTree = ""; }; 820F451B2107292500AA056A /* TypeContentsOrderRuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypeContentsOrderRuleTests.swift; sourceTree = ""; }; 820F451D21073D7200AA056A /* ConditionalReturnsOnNewlineRuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionalReturnsOnNewlineRuleTests.swift; sourceTree = ""; }; + 82144ACB20F640F200B06695 /* VerticalWhitespaceBetweenCasesRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalWhitespaceBetweenCasesRule.swift; sourceTree = ""; }; 821F70B6210720C700E2C84F /* FileTypesOrderRuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileTypesOrderRuleTests.swift; sourceTree = ""; }; + 823EDC6121020D850070B7CD /* MultilineLiteralBracketsRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineLiteralBracketsRule.swift; sourceTree = ""; }; 824AB64C2105C39F004B5A8F /* ConditionalReturnsOnNewlineConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConditionalReturnsOnNewlineConfiguration.swift; sourceTree = ""; }; 825F19D01EEFF19700969EF1 /* ObjectLiteralRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectLiteralRuleTests.swift; sourceTree = ""; }; 827009FC20FE26B700ECA185 /* FileTypesOrderRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileTypesOrderRule.swift; sourceTree = ""; }; 827009FE20FE26C500ECA185 /* TypeContentsOrderRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypeContentsOrderRule.swift; sourceTree = ""; }; 827169B21F488181003FB9AF /* ExplicitEnumRawValueRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExplicitEnumRawValueRule.swift; sourceTree = ""; }; 827169B41F48D712003FB9AF /* NoGroupingExtensionRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoGroupingExtensionRule.swift; sourceTree = ""; }; - 82F614F12106014500D23904 /* MultilineParametersBracketsRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineParametersBracketsRule.swift; sourceTree = ""; }; - 82F614F32106015100D23904 /* MultilineArgumentsBracketsRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineArgumentsBracketsRule.swift; sourceTree = ""; }; - 82FE253E20F604AD00295958 /* VerticalWhitespaceOpeningBracesRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalWhitespaceOpeningBracesRule.swift; sourceTree = ""; }; - 82FE254020F604CB00295958 /* VerticalWhitespaceClosingBracesRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalWhitespaceClosingBracesRule.swift; sourceTree = ""; }; 82DB55FD21008F3E001C62FF /* FileTypesOrderConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileTypesOrderConfiguration.swift; sourceTree = ""; }; 82DB55FF21008F54001C62FF /* TypeContentsOrderConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypeContentsOrderConfiguration.swift; sourceTree = ""; }; 82EB7883215BAE780042E0FD /* FileTypesOrderRuleExamples.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileTypesOrderRuleExamples.swift; sourceTree = ""; }; 82EB7884215BAE780042E0FD /* TypeContentsOrderRuleExamples.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypeContentsOrderRuleExamples.swift; sourceTree = ""; }; + 82F614F12106014500D23904 /* MultilineParametersBracketsRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineParametersBracketsRule.swift; sourceTree = ""; }; + 82F614F32106015100D23904 /* MultilineArgumentsBracketsRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineArgumentsBracketsRule.swift; sourceTree = ""; }; + 82FE253E20F604AD00295958 /* VerticalWhitespaceOpeningBracesRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalWhitespaceOpeningBracesRule.swift; sourceTree = ""; }; + 82FE254020F604CB00295958 /* VerticalWhitespaceClosingBracesRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalWhitespaceClosingBracesRule.swift; sourceTree = ""; }; 83894F211B0C928A006214E1 /* RulesCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RulesCommand.swift; sourceTree = ""; }; 83D71E261B131EB5000395DE /* RuleDescription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RuleDescription.swift; sourceTree = ""; }; 856651A61D6B395F005E6B29 /* MarkRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkRule.swift; sourceTree = ""; }; @@ -1108,6 +1106,7 @@ D450D1D021EC4A6900E60010 /* StrongIBOutletRule.swift */, D40E041B1F46E3B30043BC4E /* SuperfluousDisableCommandRule.swift */, E88DEA811B0990A700A66CB0 /* TodoRule.swift */, + 7565E5F02262BA0900B0597C /* UnusedCaptureListRule.swift */, D40AD0891E032F9700F48C30 /* UnusedClosureParameterRule.swift */, D4D7320C21E15ED4001C07D9 /* UnusedControlFlowLabelRule.swift */, 8F715B82213B528B00427BD9 /* UnusedImportRule.swift */, @@ -2037,6 +2036,7 @@ D4DAE8BC1DE14E8F00B0AE7A /* NimbleOperatorRule.swift in Sources */, 6CB514E91C760C6900FA02C4 /* Structure+SwiftLint.swift in Sources */, D4C0E46F1E3D973600C560F2 /* ForWhereRule.swift in Sources */, + 7565E5F12262BA0900B0597C /* UnusedCaptureListRule.swift in Sources */, D4EA77CA1F81FACC00C315FB /* LiteralExpressionEndIdentationRule.swift in Sources */, E86396C51BADAC15002C9E88 /* XcodeReporter.swift in Sources */, E889D8C51F1D11A200058332 /* Configuration+LintableFiles.swift in Sources */, diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 4c1c094b61..840c5c489c 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -1339,6 +1339,12 @@ extension UntypedErrorInCatchRuleTests { ] } +extension UnusedCaptureListRuleTests { + static var allTests: [(String, (UnusedCaptureListRuleTests) -> () throws -> Void)] = [ + ("testWithDefaultConfiguration", testWithDefaultConfiguration) + ] +} + extension UnusedClosureParameterRuleTests { static var allTests: [(String, (UnusedClosureParameterRuleTests) -> () throws -> Void)] = [ ("testWithDefaultConfiguration", testWithDefaultConfiguration) @@ -1669,6 +1675,7 @@ XCTMain([ testCase(UnneededBreakInSwitchRuleTests.allTests), testCase(UnneededParenthesesInClosureArgumentRuleTests.allTests), testCase(UntypedErrorInCatchRuleTests.allTests), + testCase(UnusedCaptureListRuleTests.allTests), testCase(UnusedClosureParameterRuleTests.allTests), testCase(UnusedControlFlowLabelRuleTests.allTests), testCase(UnusedEnumeratedRuleTests.allTests), diff --git a/Tests/SwiftLintFrameworkTests/AutomaticRuleTests.generated.swift b/Tests/SwiftLintFrameworkTests/AutomaticRuleTests.generated.swift index c47dcff5bb..ca0dbc1eeb 100644 --- a/Tests/SwiftLintFrameworkTests/AutomaticRuleTests.generated.swift +++ b/Tests/SwiftLintFrameworkTests/AutomaticRuleTests.generated.swift @@ -672,6 +672,12 @@ class UntypedErrorInCatchRuleTests: XCTestCase { } } +class UnusedCaptureListRuleTests: XCTestCase { + func testWithDefaultConfiguration() { + verifyRule(UnusedCaptureListRule.description) + } +} + class UnusedClosureParameterRuleTests: XCTestCase { func testWithDefaultConfiguration() { verifyRule(UnusedClosureParameterRule.description)