Skip to content

Commit

Permalink
realm#2079 - Implemented subclass rule
Browse files Browse the repository at this point in the history
  • Loading branch information
driver733 committed Mar 2, 2018
1 parent 7e79790 commit 39d2892
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 2 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

#### Enhancements

* Adds `subclass` opt-in rule
to prohibit subclassing.
[Mikhail Yakushin](https://github.com/driver733)
[#2079](https://github.com/realm/SwiftLint/issues/2079)

* Adds `function_body_whitespace_lines` opt-in rule
to prohibit whitespace lines in function bodies.
[Mikhail Yakushin](https://github.com/driver733)
Expand Down
11 changes: 11 additions & 0 deletions Rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
* [Sorted Imports](#sorted-imports)
* [Statement Position](#statement-position)
* [Strict fileprivate](#strict-fileprivate)
* [Subclass](#subclass)
* [Superfluous Disable Command](#superfluous-disable-command)
* [Switch and Case Statement Alignment](#switch-and-case-statement-alignment)
* [Switch Case on Newline](#switch-case-on-newline)
Expand Down Expand Up @@ -12141,6 +12142,16 @@ struct Inter {



## Subclass

Identifier | Enabled by default | Supports autocorrection | Kind
--- | --- | --- | ---
`subclass` | Disabled | No | style

Subclasses are prohibited.



## Superfluous Disable Command

Identifier | Enabled by default | Supports autocorrection | Kind
Expand Down
1 change: 1 addition & 0 deletions Source/SwiftLintFramework/Models/MasterRuleList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public let masterRuleList = RuleList(rules: [
SortedImportsRule.self,
StatementPositionRule.self,
StrictFilePrivateRule.self,
SubClassRule.self,
SuperfluousDisableCommandRule.self,
SwitchCaseAlignmentRule.self,
SwitchCaseOnNewlineRule.self,
Expand Down
46 changes: 46 additions & 0 deletions Source/SwiftLintFramework/Rules/SubClassRule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// SubClassRule.swift
// SwiftLint
//
// Created by Mikhail Yakushin on 03/02/18.
// Copyright © 2018 Realm. All rights reserved.
//

import SourceKittenFramework

public struct SubClassRule: ASTRule, ConfigurationProviderRule, OptInRule {
public var configuration = SeverityLevelsConfiguration(warning: 0, error: 0)

public init() {}

public static let description = RuleDescription(
identifier: "subclass",
name: "Subclass",
description: "Subclasses are prohibited.",
kind: .style
)

public func validate(file: File, kind: SwiftDeclarationKind,
dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
guard SwiftDeclarationKind.functionKinds.contains(kind),
let offset = dictionary.offset,
case let contentsNSString = file.contents.bridge()
else {
return []
}
if contentsNSString.contains("super.") || contentsNSString.contains("super()") {
return [
StyleViolation(
ruleDescription: type(of: self).description,
severity: configuration.params.first!.severity,
location: Location(file: file, byteOffset: offset),
reason: "Subclasses are prohibited."
)
]
} else {
return []
}

}

}
12 changes: 10 additions & 2 deletions SwiftLint.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,11 @@
B89F3BCF1FD5EE1400931E59 /* RequiredEnumCaseRuleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B89F3BC71FD5ED7D00931E59 /* RequiredEnumCaseRuleConfiguration.swift */; };
BB00B4E91F5216090079869F /* MultipleClosuresWithTrailingClosureRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB00B4E71F5216070079869F /* MultipleClosuresWithTrailingClosureRule.swift */; };
BFF028AE1CBCF8A500B38A9D /* TrailingWhitespaceConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF48D2D61CBCCA5F0080BDAE /* TrailingWhitespaceConfiguration.swift */; };
C2E091D98F9EC15D97944DD3 /* SubClassRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E09B21D7086565C82975AD /* SubClassRuleTests.swift */; };
C2E0977960D35B8963751DB1 /* FunctionBodyWhitespaceLinesRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E090541C2D83EA2987D15C /* FunctionBodyWhitespaceLinesRule.swift */; };
C2E099B1FFD283BEA0EBC5B0 /* FunctionBodyCommentsRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E09082757235CF0E6120EA /* FunctionBodyCommentsRuleTests.swift */; };
C2E09A497C757CA47CE801AD /* SubClassRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E0983EFF1CA03CAD386C10 /* SubClassRule.swift */; };
C2E09BF91C6D1C09AFF557F4 /* FunctionBodyCommentsRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E099E6FF20FE33D0EC8488 /* FunctionBodyCommentsRule.swift */; };
C2E0977960D35B8963751DB1 /* FunctionBodyWhitespaceLinesRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2E090541C2D83EA2987D15C /* FunctionBodyWhitespaceLinesRule.swift */; };
C328A2F71E6759AE00A9E4D7 /* ExplicitTypeInterfaceRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C328A2F51E67595500A9E4D7 /* ExplicitTypeInterfaceRule.swift */; };
C3DE5DAC1E7DF9CA00761483 /* FatalErrorMessageRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DE5DAA1E7DF99B00761483 /* FatalErrorMessageRule.swift */; };
C946FECB1EAE67EE007DD778 /* LetVarWhitespaceRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C946FEC91EAE5E20007DD778 /* LetVarWhitespaceRule.swift */; };
Expand Down Expand Up @@ -497,9 +499,11 @@
B89F3BCB1FD5EDA900931E59 /* RequiredEnumCaseRuleTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequiredEnumCaseRuleTestCase.swift; sourceTree = "<group>"; };
BB00B4E71F5216070079869F /* MultipleClosuresWithTrailingClosureRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultipleClosuresWithTrailingClosureRule.swift; sourceTree = "<group>"; };
BF48D2D61CBCCA5F0080BDAE /* TrailingWhitespaceConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrailingWhitespaceConfiguration.swift; sourceTree = "<group>"; };
C2E090541C2D83EA2987D15C /* FunctionBodyWhitespaceLinesRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionBodyWhitespaceLinesRule.swift; sourceTree = "<group>"; };
C2E09082757235CF0E6120EA /* FunctionBodyCommentsRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionBodyCommentsRuleTests.swift; sourceTree = "<group>"; };
C2E0983EFF1CA03CAD386C10 /* SubClassRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubClassRule.swift; sourceTree = "<group>"; };
C2E099E6FF20FE33D0EC8488 /* FunctionBodyCommentsRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionBodyCommentsRule.swift; sourceTree = "<group>"; };
C2E090541C2D83EA2987D15C /* FunctionBodyWhitespaceLinesRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionBodyWhitespaceLinesRule.swift; sourceTree = "<group>"; };
C2E09B21D7086565C82975AD /* SubClassRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubClassRuleTests.swift; sourceTree = "<group>"; };
C328A2F51E67595500A9E4D7 /* ExplicitTypeInterfaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExplicitTypeInterfaceRule.swift; sourceTree = "<group>"; };
C3DE5DAA1E7DF99B00761483 /* FatalErrorMessageRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FatalErrorMessageRule.swift; sourceTree = "<group>"; };
C946FEC91EAE5E20007DD778 /* LetVarWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LetVarWhitespaceRule.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -981,6 +985,7 @@
3B12C9BE1C3209AC000B423F /* Resources */,
D0D1217C19E87B05005E4BAA /* Supporting Files */,
C2E09082757235CF0E6120EA /* FunctionBodyCommentsRuleTests.swift */,
C2E09B21D7086565C82975AD /* SubClassRuleTests.swift */,
);
name = SwiftLintFrameworkTests;
path = Tests/SwiftLintFrameworkTests;
Expand Down Expand Up @@ -1174,6 +1179,7 @@
1872906F1FC37A9B0016BEA2 /* YodaConditionRule.swift */,
C2E099E6FF20FE33D0EC8488 /* FunctionBodyCommentsRule.swift */,
C2E090541C2D83EA2987D15C /* FunctionBodyWhitespaceLinesRule.swift */,
C2E0983EFF1CA03CAD386C10 /* SubClassRule.swift */,
);
path = Rules;
sourceTree = "<group>";
Expand Down Expand Up @@ -1716,6 +1722,7 @@
B3935EE74B1E8E14FBD65E7F /* String+XML.swift in Sources */,
C2E09BF91C6D1C09AFF557F4 /* FunctionBodyCommentsRule.swift in Sources */,
C2E0977960D35B8963751DB1 /* FunctionBodyWhitespaceLinesRule.swift in Sources */,
C2E09A497C757CA47CE801AD /* SubClassRule.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -1771,6 +1778,7 @@
3BCC04D41C502BAB006073C3 /* RuleConfigurationTests.swift in Sources */,
E809EDA31B8A73FB00399043 /* ConfigurationTests.swift in Sources */,
C2E099B1FFD283BEA0EBC5B0 /* FunctionBodyCommentsRuleTests.swift in Sources */,
C2E091D98F9EC15D97944DD3 /* SubClassRuleTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
8 changes: 8 additions & 0 deletions Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,14 @@ extension SourceKitCrashTests {
]
}

extension SubClassRuleTests {
static var allTests: [(String, (SubClassRuleTests) -> () throws -> Void)] = [
("testSubClassRuleSuperDot", testSubClassRuleSuperDot),
("testSubClassRuleSuper", testSubClassRuleSuper),
("testSubClassRuleTestsValid", testSubClassRuleTestsValid)
]
}

extension TodoRuleTests {
static var allTests: [(String, (TodoRuleTests) -> () throws -> Void)] = [
("testTodo", testTodo),
Expand Down
43 changes: 43 additions & 0 deletions Tests/SwiftLintFrameworkTests/SubClassRuleTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// SubClassRuleTests.swift
// SwiftLint
//
// Created by Mikhail Yakushin on 03/02/18.
// Copyright © 2018 Realm. All rights reserved.
//

import SwiftLintFramework
import XCTest

class SubClassRuleTests: XCTestCase {

func testSubClassRuleSuperDot() {
let nonTriggeringExamples =
"class MyType: SuperType {" +
"public init() { super.init() }" +
"}"
XCTAssertNotEqual(violations(nonTriggeringExamples), [])
}

func testSubClassRuleSuper() {
let nonTriggeringExamples =
"class MyType: SuperType {" +
"public init() { super() }" +
"}"
XCTAssertNotEqual(violations(nonTriggeringExamples), [])
}

func testSubClassRuleTestsValid() {
let nonTriggeringExamples =
"class MyType: SuperType {" +
"public init() { this() }" +
"}"
XCTAssertEqual(violations(nonTriggeringExamples), [])
}

private func violations(_ string: String) -> [StyleViolation] {
let config = makeConfig(nil, SubClassRule.description.identifier)!
return SwiftLintFrameworkTests.violations(string, config: config)
}

}

0 comments on commit 39d2892

Please sign in to comment.