diff --git a/CHANGELOG.md b/CHANGELOG.md
index 15ff3eccb3..0d94aa14bd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,10 @@
#### Breaking
-* None.
+* Remove the `weak_computed_property` rule. Please see linked issue for
+ discussion and rationale.
+ [JP Simard](https://github.com/jpsim)
+ [#2712](https://github.com/realm/SwiftLint/issues/2712)
#### Experimental
@@ -10,9 +13,8 @@
#### Enhancements
-
* Add `" - "` delimiter to allow commenting SwiftLint commands without triggering
-`superfluous_disable_command`.
+ `superfluous_disable_command`.
[Kevin Randrup](https://github.com/kevinrandrup)
* Make `testSimulateHomebrewTest()` test opt-in because it may fail on unknown
diff --git a/Rules.md b/Rules.md
index 763e5ab4c4..89da53ffd8 100644
--- a/Rules.md
+++ b/Rules.md
@@ -172,7 +172,6 @@
* [Vertical Whitespace before Closing Braces](#vertical-whitespace-before-closing-braces)
* [Vertical Whitespace after Opening Braces](#vertical-whitespace-after-opening-braces)
* [Void Return](#void-return)
-* [Weak Computed Property](#weak-computed-property)
* [Weak Delegate](#weak-delegate)
* [XCTest Specific Matcher](#xctest-specific-matcher)
* [XCTFail Message](#xctfail-message)
@@ -24890,76 +24889,6 @@ let foo: (ConfigurationTests) -> () throws -> ↓())
-## Weak Computed Property
-
-Identifier | Enabled by default | Supports autocorrection | Kind | Analyzer | Minimum Swift Compiler Version
---- | --- | --- | --- | --- | ---
-`weak_computed_property` | Enabled | Yes | lint | No | 4.1.0
-
-Adding weak to a computed property has no effect.
-
-### Examples
-
-
-Non Triggering Examples
-
-```swift
-class Foo {
- weak var delegate: SomeProtocol?
-}
-```
-
-```swift
-class Foo {
- var delegate: SomeProtocol?
-}
-```
-
-```swift
-class Foo {
- weak var delegate: SomeProtocol? {
- didSet {
- update(with: delegate)
- }
- }
-}
-```
-
-```swift
-class Foo {
- weak var delegate: SomeProtocol? {
- willSet {
- update(with: delegate)
- }
- }
-}
-```
-
-
-
-Triggering Examples
-
-```swift
-class Foo {
- weak var delegate: SomeProtocol? { return bar() }
-}
-```
-
-```swift
-class Foo {
- private weak var _delegate: SomeProtocol?
-
- ↓weak var delegate: SomeProtocol? {
- get { return _delegate }
- set { _delegate = newValue }
- }
-}
-```
-
-
-
-
-
## Weak Delegate
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 102cce0ecb..599018746a 100644
--- a/Source/SwiftLintFramework/Models/MasterRuleList.swift
+++ b/Source/SwiftLintFramework/Models/MasterRuleList.swift
@@ -173,7 +173,6 @@ public let masterRuleList = RuleList(rules: [
VerticalWhitespaceOpeningBracesRule.self,
VerticalWhitespaceRule.self,
VoidReturnRule.self,
- WeakComputedProperyRule.self,
WeakDelegateRule.self,
XCTFailMessageRule.self,
XCTSpecificMatcherRule.self,
diff --git a/Source/SwiftLintFramework/Rules/Lint/WeakComputedProperyRule.swift b/Source/SwiftLintFramework/Rules/Lint/WeakComputedProperyRule.swift
deleted file mode 100644
index 0690364df7..0000000000
--- a/Source/SwiftLintFramework/Rules/Lint/WeakComputedProperyRule.swift
+++ /dev/null
@@ -1,189 +0,0 @@
-import Foundation
-import SourceKittenFramework
-
-public struct WeakComputedProperyRule: SubstitutionCorrectableASTRule, ConfigurationProviderRule,
- AutomaticTestableRule {
- public var configuration = SeverityConfiguration(.warning)
-
- public init() {}
-
- public static let description = RuleDescription(
- identifier: "weak_computed_property",
- name: "Weak Computed Property",
- description: "Adding weak to a computed property has no effect.",
- kind: .lint,
- minSwiftVersion: .fourDotOne,
- nonTriggeringExamples: [
- " weak var delegate: SomeProtocol?",
- " var delegate: SomeProtocol?",
- """
- weak var delegate: SomeProtocol? {
- didSet {
- update(with: delegate)
- }
- }
- """,
- """
- weak var delegate: SomeProtocol? {
- willSet {
- update(with: delegate)
- }
- }
- """
- ].map(wrapExample),
- triggeringExamples: [
- " weak var delegate: SomeProtocol? { return bar() }",
- """
- private weak var _delegate: SomeProtocol?
-
- ↓weak var delegate: SomeProtocol? {
- get { return _delegate }
- set { _delegate = newValue }
- }
- """
- ].map(wrapExample),
- corrections: [
- wrapExample(" ↓weak var delegate: SomeProtocol? { return bar() }"):
- wrapExample(" var delegate: SomeProtocol? { return bar() }"),
- wrapExample("""
- private weak var _delegate: SomeProtocol?
-
- ↓weak var delegate: SomeProtocol? {
- get { return _delegate }
- set { _delegate = newValue }
- }
- """):
- wrapExample("""
- private weak var _delegate: SomeProtocol?
-
- var delegate: SomeProtocol? {
- get { return _delegate }
- set { _delegate = newValue }
- }
- """)
- ]
- )
-
- // MARK: - ASTRule
-
- public func validate(file: File,
- kind: SwiftDeclarationKind,
- dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
- return violationRanges(in: file, kind: kind, dictionary: dictionary).map {
- StyleViolation(ruleDescription: type(of: self).description,
- severity: configuration.severity,
- location: Location(file: file, characterOffset: $0.location))
- }
- }
-
- // MARK: - SubstitutionCorrectableASTRule
-
- public func substitution(for violationRange: NSRange, in file: File) -> (NSRange, String) {
- var rangeToRemove = violationRange
- let contentsNSString = file.contents.bridge()
- if let byteRange = contentsNSString.NSRangeToByteRange(start: violationRange.location,
- length: violationRange.length),
- let nextToken = file.syntaxMap.tokens.first(where: { $0.offset > byteRange.location }),
- let nextTokenLocation = contentsNSString.byteRangeToNSRange(start: nextToken.offset, length: 0) {
- rangeToRemove.length = nextTokenLocation.location - violationRange.location
- }
-
- return (rangeToRemove, "")
- }
-
- public func violationRanges(in file: File,
- kind: SwiftDeclarationKind,
- dictionary: [String: SourceKitRepresentable]) -> [NSRange] {
- guard allowedKinds.contains(kind),
- let bodyOffset = dictionary.bodyOffset,
- let bodyLength = dictionary.bodyLength, bodyLength > 0,
- let weakAttribute = dictionary.swiftAttributes.first(where: { $0.isWeakAttribute }),
- let attributeOffset = weakAttribute.offset,
- let attributeLength = weakAttribute.length, attributeLength > 0,
- case let contents = file.contents.bridge(),
- let attributeRange = contents.byteRangeToNSRange(start: attributeOffset, length: attributeLength),
- let bodyRange = contents.byteRangeToNSRange(start: bodyOffset, length: bodyLength),
- !containsObserverToken(in: bodyRange, file: file, propertyStructure: dictionary) else {
- return []
- }
-
- return [attributeRange]
- }
-
- // MARK: - Private
-
- private let allowedKinds = SwiftDeclarationKind.variableKinds.subtracting([.varParameter])
-
- private func containsObserverToken(in range: NSRange, file: File,
- propertyStructure: [String: SourceKitRepresentable]) -> Bool {
- let tokens = file.rangesAndTokens(matching: "\\b(?:didSet|willSet)\\b", range: range).keywordTokens()
- return tokens.contains(where: { token -> Bool in
- // the last element is the deepest structure
- guard let dict = declarations(forByteOffset: token.offset, structure: file.structure).last,
- propertyStructure.isEqualTo(dict) else {
- return false
- }
-
- return true
- })
- }
-
- private func declarations(forByteOffset byteOffset: Int,
- structure: Structure) -> [[String: SourceKitRepresentable]] {
- var results = [[String: SourceKitRepresentable]]()
-
- func parse(dictionary: [String: SourceKitRepresentable], parentKind: SwiftDeclarationKind?) {
- // Only accepts declarations which contains a body and contains the
- // searched byteOffset
- guard let kindString = dictionary.kind,
- let kind = SwiftDeclarationKind(rawValue: kindString),
- let bodyOffset = dictionary.bodyOffset,
- let bodyLength = dictionary.bodyLength,
- case let byteRange = NSRange(location: bodyOffset, length: bodyLength),
- NSLocationInRange(byteOffset, byteRange) else {
- return
- }
-
- if parentKind != .protocol && allowedKinds.contains(kind) {
- results.append(dictionary)
- }
-
- for dictionary in dictionary.substructure {
- parse(dictionary: dictionary, parentKind: kind)
- }
- }
-
- for dictionary in structure.dictionary.substructure {
- parse(dictionary: dictionary, parentKind: nil)
- }
-
- return results
- }
-}
-
-private extension Dictionary where Key == String, Value == SourceKitRepresentable {
- var isWeakAttribute: Bool {
- return attribute.flatMap(SwiftDeclarationAttributeKind.init) == .weak
- }
-}
-
-private extension Array where Element == (NSRange, [SyntaxToken]) {
- func keywordTokens() -> [SyntaxToken] {
- return compactMap { _, tokens in
- guard let token = tokens.last,
- SyntaxKind(rawValue: token.type) == .keyword else {
- return nil
- }
-
- return token
- }
- }
-}
-
-private func wrapExample(_ text: String) -> String {
- return """
- class Foo {
- \(text)
- }
- """
-}
diff --git a/SwiftLint.xcodeproj/project.pbxproj b/SwiftLint.xcodeproj/project.pbxproj
index f62957d6ef..808f0d024e 100644
--- a/SwiftLint.xcodeproj/project.pbxproj
+++ b/SwiftLint.xcodeproj/project.pbxproj
@@ -248,7 +248,6 @@
D41985EB21FAB63E003BE2B7 /* DeploymentTargetConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41985EA21FAB63E003BE2B7 /* DeploymentTargetConfiguration.swift */; };
D41985ED21FAD033003BE2B7 /* DeploymentTargetConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41985EC21FAD033003BE2B7 /* DeploymentTargetConfigurationTests.swift */; };
D41985EF21FAD5E8003BE2B7 /* DeploymentTargetRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41985EE21FAD5E8003BE2B7 /* DeploymentTargetRuleTests.swift */; };
- D41985F121FC5AF7003BE2B7 /* WeakComputedProperyRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41985F021FC5AF7003BE2B7 /* WeakComputedProperyRule.swift */; };
D41B57781ED8CEE0007B0470 /* ExtensionAccessModifierRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41B57771ED8CEE0007B0470 /* ExtensionAccessModifierRule.swift */; };
D41E7E0B1DF9DABB0065259A /* RedundantStringEnumValueRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41E7E0A1DF9DABB0065259A /* RedundantStringEnumValueRule.swift */; };
D4246D6D1F30D8620097E658 /* PrivateOverFilePrivateRuleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4246D6C1F30D8620097E658 /* PrivateOverFilePrivateRuleConfiguration.swift */; };
@@ -734,7 +733,6 @@
D41985EA21FAB63E003BE2B7 /* DeploymentTargetConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeploymentTargetConfiguration.swift; sourceTree = ""; };
D41985EC21FAD033003BE2B7 /* DeploymentTargetConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeploymentTargetConfigurationTests.swift; sourceTree = ""; };
D41985EE21FAD5E8003BE2B7 /* DeploymentTargetRuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeploymentTargetRuleTests.swift; sourceTree = ""; };
- D41985F021FC5AF7003BE2B7 /* WeakComputedProperyRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakComputedProperyRule.swift; sourceTree = ""; };
D41B57771ED8CEE0007B0470 /* ExtensionAccessModifierRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionAccessModifierRule.swift; sourceTree = ""; };
D41E7E0A1DF9DABB0065259A /* RedundantStringEnumValueRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedundantStringEnumValueRule.swift; sourceTree = ""; };
D4246D6C1F30D8620097E658 /* PrivateOverFilePrivateRuleConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrivateOverFilePrivateRuleConfiguration.swift; sourceTree = ""; };
@@ -1119,7 +1117,6 @@
8F6B3153213CDCD100858E44 /* UnusedPrivateDeclarationRule.swift */,
D4B3409C21F16B110038C79A /* UnusedSetterValueRule.swift */,
D442541E1DB87C3D00492EA4 /* ValidIBInspectableRule.swift */,
- D41985F021FC5AF7003BE2B7 /* WeakComputedProperyRule.swift */,
094384FF1D5D2382009168CF /* WeakDelegateRule.swift */,
1872906F1FC37A9B0016BEA2 /* YodaConditionRule.swift */,
);
@@ -2106,7 +2103,6 @@
D4130D971E16183F00242361 /* IdentifierNameRuleExamples.swift in Sources */,
7250948A1D0859260039B353 /* StatementModeConfiguration.swift in Sources */,
E81619531BFC162C00946723 /* QueuedPrint.swift in Sources */,
- D41985F121FC5AF7003BE2B7 /* WeakComputedProperyRule.swift in Sources */,
E87E4A051BFB927C00FCFE46 /* TrailingSemicolonRule.swift in Sources */,
D4B472411F66486300BD6EF1 /* FallthroughRule.swift in Sources */,
B25DCD0B1F7E9F9E0028A199 /* MultilineArgumentsRuleExamples.swift in Sources */,
diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift
index 29c77911ca..31d263d4bd 100644
--- a/Tests/LinuxMain.swift
+++ b/Tests/LinuxMain.swift
@@ -103,6 +103,7 @@ extension CommandTests {
("testEnablePrevious", testEnablePrevious),
("testEnableThis", testEnableThis),
("testEnableNext", testEnableNext),
+ ("testTrailingCOmment", testTrailingCOmment),
("testActionInverse", testActionInverse),
("testNoModifierCommandExpandsToItself", testNoModifierCommandExpandsToItself),
("testExpandPreviousCommand", testExpandPreviousCommand),
@@ -110,6 +111,7 @@ extension CommandTests {
("testExpandNextCommand", testExpandNextCommand),
("testSuperfluousDisableCommands", testSuperfluousDisableCommands),
("testDisableAllOverridesSuperfluousDisableCommand", testDisableAllOverridesSuperfluousDisableCommand),
+ ("testSuperfluousDisableCommandsIgnoreDelimiter", testSuperfluousDisableCommandsIgnoreDelimiter),
("testInvalidDisableCommands", testInvalidDisableCommands),
("testSuperfluousDisableCommandsDisabled", testSuperfluousDisableCommandsDisabled),
("testSuperfluousDisableCommandsDisabledOnConfiguration", testSuperfluousDisableCommandsDisabledOnConfiguration)
@@ -1454,12 +1456,6 @@ extension VoidReturnRuleTests {
]
}
-extension WeakComputedProperyRuleTests {
- static var allTests: [(String, (WeakComputedProperyRuleTests) -> () throws -> Void)] = [
- ("testWithDefaultConfiguration", testWithDefaultConfiguration)
- ]
-}
-
extension WeakDelegateRuleTests {
static var allTests: [(String, (WeakDelegateRuleTests) -> () throws -> Void)] = [
("testWithDefaultConfiguration", testWithDefaultConfiguration)
@@ -1707,7 +1703,6 @@ XCTMain([
testCase(VerticalWhitespaceOpeningBracesRuleTests.allTests),
testCase(VerticalWhitespaceRuleTests.allTests),
testCase(VoidReturnRuleTests.allTests),
- testCase(WeakComputedProperyRuleTests.allTests),
testCase(WeakDelegateRuleTests.allTests),
testCase(XCTFailMessageRuleTests.allTests),
testCase(XCTSpecificMatcherRuleTests.allTests),
diff --git a/Tests/SwiftLintFrameworkTests/AutomaticRuleTests.generated.swift b/Tests/SwiftLintFrameworkTests/AutomaticRuleTests.generated.swift
index adb224e013..d7dfa476e3 100644
--- a/Tests/SwiftLintFrameworkTests/AutomaticRuleTests.generated.swift
+++ b/Tests/SwiftLintFrameworkTests/AutomaticRuleTests.generated.swift
@@ -768,12 +768,6 @@ class VoidReturnRuleTests: XCTestCase {
}
}
-class WeakComputedProperyRuleTests: XCTestCase {
- func testWithDefaultConfiguration() {
- verifyRule(WeakComputedProperyRule.description)
- }
-}
-
class WeakDelegateRuleTests: XCTestCase {
func testWithDefaultConfiguration() {
verifyRule(WeakDelegateRule.description)