Skip to content

Commit

Permalink
Add discouraged_init opt-in rule
Browse files Browse the repository at this point in the history
Rule requested by @Noobish1 on issue realm#1306.
  • Loading branch information
ornithocoder committed Aug 1, 2017
1 parent f0f746f commit 8c6a5da
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@
[Marcelo Fabri](https://github.com/marcelofabri)
[#1714](https://github.com/realm/SwiftLint/issues/1714)

* Add `discouraged_init` opt-in rule that discourages direct
initialization of certain classes.
[Ornithologist Coder](https://github.com/ornithocoder)

##### Bug Fixes

* Fix false positive on `redundant_discardable_let` rule when using
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 @@ -24,6 +24,7 @@ public let masterRuleList = RuleList(rules: [
CustomRules.self,
CyclomaticComplexityRule.self,
DiscardedNotificationCenterObserverRule.self,
DiscouragedInitRule.self,
DynamicInlineRule.self,
EmptyCountRule.self,
EmptyEnumArgumentsRule.self,
Expand Down
54 changes: 54 additions & 0 deletions Source/SwiftLintFramework/Rules/DiscouragedInitRule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// DiscourageInitRule.swift
// SwiftLint
//
// Created by Ornithologist Coder on 8/1/17.
// Copyright © 2017 Realm. All rights reserved.
//

import Foundation
import SourceKittenFramework

public struct DiscouragedInitRule: ASTRule, OptInRule, ConfigurationProviderRule {
public var configuration = DiscouragedInitConfiguration()

public init() {}

public static let description = RuleDescription(
identifier: "discouraged_init",
name: "Discouraged Init",
description: "Discouraged direct initialization of class.",
kind: .style,
nonTriggeringExamples: [
"let foo = UIDevice.current",
"let foo = Bundle.main",
"let foo = Bundle(path: \"bar\")",
"let foo = Bundle(identifier: \"bar\")"
],
triggeringExamples: [
"↓UIDevice()",
"↓Bundle()",
"let foo = ↓UIDevice()",
"let foo = ↓Bundle()",
"let foo = bar(bundle: ↓Bundle(), device: ↓UIDevice())"
]
)

public func validate(file: File,
kind: SwiftExpressionKind,
dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
guard
let offset = dictionary.nameOffset,
let name = dictionary.name,
kind == .call,
dictionary.bodyLength == 0,
configuration.discouragedInits.contains(name)
else {
return []
}

return [StyleViolation(ruleDescription: type(of: self).description,
severity: configuration.severity,
location: Location(file: file, byteOffset: offset))]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// DiscouragedInitConfiguration.swift
// SwiftLint
//
// Created by Ornithologist Coder on 8/1/17.
// Copyright © 2017 Realm. All rights reserved.
//

import Foundation
import SourceKittenFramework

public struct DiscouragedInitConfiguration: RuleConfiguration, Equatable {
public var severityConfiguration = SeverityConfiguration(.warning)

public var consoleDescription: String {
return severityConfiguration.consoleDescription
}

public let discouragedInits = [
"Bundle",
"UIDevice"
]

public var severity: ViolationSeverity {
return severityConfiguration.severity
}

// MARK: - RuleConfiguration

public mutating func apply(configuration: Any) throws {
guard let configuration = configuration as? [String: Any] else {
throw ConfigurationError.unknownConfiguration
}

if let severityString = configuration["severity"] as? String {
try severityConfiguration.apply(configuration: severityString)
}
}

// MARK: - Equatable

public static func == (lhs: DiscouragedInitConfiguration, rhs: DiscouragedInitConfiguration) -> Bool {
return lhs.severityConfiguration == rhs.severityConfiguration
}
}
14 changes: 11 additions & 3 deletions SwiftLint.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
57ED827B1CF656E3002B3513 /* JUnitReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57ED82791CF65183002B3513 /* JUnitReporter.swift */; };
621061BF1ED57E640082D51E /* MultilineParametersRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621061BE1ED57E640082D51E /* MultilineParametersRuleExamples.swift */; };
6250D32A1ED4DFEB00735129 /* MultilineParametersRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6238AE411ED4D734006C3601 /* MultilineParametersRule.swift */; };
62622F6B1F2F2E3500D5D099 /* DiscouragedInitRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62622F6A1F2F2E3500D5D099 /* DiscouragedInitRule.swift */; };
62A498561F306A7700D766E4 /* DiscouragedInitConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A498551F306A7700D766E4 /* DiscouragedInitConfiguration.swift */; };
67932E2D1E54AF4B00CB0629 /* CyclomaticComplexityConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67932E2C1E54AF4B00CB0629 /* CyclomaticComplexityConfigurationTests.swift */; };
67EB4DFA1E4CC111004E9ACD /* CyclomaticComplexityConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EB4DF81E4CC101004E9ACD /* CyclomaticComplexityConfiguration.swift */; };
67EB4DFC1E4CD7F5004E9ACD /* CyclomaticComplexityRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EB4DFB1E4CD7F5004E9ACD /* CyclomaticComplexityRuleTests.swift */; };
Expand Down Expand Up @@ -365,6 +367,8 @@
57ED82791CF65183002B3513 /* JUnitReporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JUnitReporter.swift; sourceTree = "<group>"; };
621061BE1ED57E640082D51E /* MultilineParametersRuleExamples.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilineParametersRuleExamples.swift; sourceTree = "<group>"; };
6238AE411ED4D734006C3601 /* MultilineParametersRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultilineParametersRule.swift; sourceTree = "<group>"; };
62622F6A1F2F2E3500D5D099 /* DiscouragedInitRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscouragedInitRule.swift; sourceTree = "<group>"; };
62A498551F306A7700D766E4 /* DiscouragedInitConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscouragedInitConfiguration.swift; sourceTree = "<group>"; };
65454F451B14D73800319A6C /* ControlStatementRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControlStatementRule.swift; sourceTree = "<group>"; };
67932E2C1E54AF4B00CB0629 /* CyclomaticComplexityConfigurationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CyclomaticComplexityConfigurationTests.swift; sourceTree = "<group>"; };
67EB4DF81E4CC101004E9ACD /* CyclomaticComplexityConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CyclomaticComplexityConfiguration.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -629,6 +633,7 @@
D4C4A34A1DEA4FD700E0E04C /* AttributesConfiguration.swift */,
D43B04671E07228D004016AF /* ColonConfiguration.swift */,
67EB4DF81E4CC101004E9ACD /* CyclomaticComplexityConfiguration.swift */,
62A498551F306A7700D766E4 /* DiscouragedInitConfiguration.swift */,
D4C4A3511DEFBBB700E0E04C /* FileHeaderConfiguration.swift */,
29FFC3781F1574FD007E4825 /* FileLengthRuleConfiguration.swift */,
47ACC8971E7DC74E0088EEB2 /* ImplicitlyUnwrappedOptionalConfiguration.swift */,
Expand All @@ -647,8 +652,8 @@
725094881D0855760039B353 /* StatementPositionConfiguration.swift */,
D40F83871DE9179200524C62 /* TrailingCommaConfiguration.swift */,
BF48D2D61CBCCA5F0080BDAE /* TrailingWhitespaceConfiguration.swift */,
006204DA1E1E48F900FFFBE1 /* VerticalWhitespaceConfiguration.swift */,
CE8178EB1EAC02CD0063186E /* UnusedOptionalBindingConfiguration.swift */,
006204DA1E1E48F900FFFBE1 /* VerticalWhitespaceConfiguration.swift */,
);
path = RuleConfigurations;
sourceTree = "<group>";
Expand Down Expand Up @@ -899,8 +904,8 @@
children = (
D47A510F1DB2DD4800A4CC21 /* AttributesRule.swift */,
D48AE2CB1DFB58C5001C6A4A /* AttributesRulesExamples.swift */,
D4B0228D1E0CC608007E5297 /* ClassDelegateProtocolRule.swift */,
D4FD4C841F2A260A00DD8AA8 /* BlockBasedKVORule.swift */,
D4B0228D1E0CC608007E5297 /* ClassDelegateProtocolRule.swift */,
1F11B3CE1C252F23002E8FA8 /* ClosingBraceRule.swift */,
D43B046A1E075905004016AF /* ClosureEndIndentationRule.swift */,
D47079A81DFDBED000027086 /* ClosureParameterPositionRule.swift */,
Expand All @@ -913,6 +918,7 @@
3B1DF0111C5148140011BCED /* CustomRules.swift */,
2E02005E1C54BF680024D09D /* CyclomaticComplexityRule.swift */,
D4DABFD21E29B4A5009617B6 /* DiscardedNotificationCenterObserverRule.swift */,
62622F6A1F2F2E3500D5D099 /* DiscouragedInitRule.swift */,
E315B83B1DFA4BC500621B44 /* DynamicInlineRule.swift */,
E847F0A81BFBBABD00EA9363 /* EmptyCountRule.swift */,
D4470D581EB6B4D1008A1B2E /* EmptyEnumArgumentsRule.swift */,
Expand Down Expand Up @@ -962,8 +968,8 @@
E5A167C81B25A0B000CF2D03 /* OperatorFunctionWhitespaceRule.swift */,
D4FBADCF1E00DA0400669C73 /* OperatorUsageWhitespaceRule.swift */,
78F032441D7C877800BE709A /* OverriddenSuperCallRule.swift */,
1E3C2D701EE36C6F00C8386D /* PrivateOverFilePrivateRule.swift */,
094385021D5D4F78009168CF /* PrivateOutletRule.swift */,
1E3C2D701EE36C6F00C8386D /* PrivateOverFilePrivateRule.swift */,
B2902A0B1D66815600BFCCF7 /* PrivateUnitTestRule.swift */,
009E09271DFEE4C200B588A7 /* ProhibitedSuperRule.swift */,
D47F31141EC918B600E3E1CA /* ProtocolPropertyAccessorsOrderRule.swift */,
Expand Down Expand Up @@ -1442,6 +1448,7 @@
E80746F61ECB722F00548D31 /* CacheDescriptionProvider.swift in Sources */,
094385041D5D4F7C009168CF /* PrivateOutletRule.swift in Sources */,
E88DEA6B1B0983FE00A66CB0 /* StyleViolation.swift in Sources */,
62622F6B1F2F2E3500D5D099 /* DiscouragedInitRule.swift in Sources */,
3BB47D831C514E8100AE6A10 /* RegexConfiguration.swift in Sources */,
D401D9261ED85EF0005DA5D4 /* RuleKind.swift in Sources */,
D4C889711E385B7B00BAE88D /* RedundantDiscardableLetRule.swift in Sources */,
Expand All @@ -1451,6 +1458,7 @@
29FFC37A1F15764D007E4825 /* FileLengthRuleConfiguration.swift in Sources */,
3B5B9FE11C444DA20009AD27 /* Array+SwiftLint.swift in Sources */,
D43B04641E0620AB004016AF /* UnusedEnumeratedRule.swift in Sources */,
62A498561F306A7700D766E4 /* DiscouragedInitConfiguration.swift in Sources */,
C946FECB1EAE67EE007DD778 /* LetVarWhitespaceRule.swift in Sources */,
E881985D1BEA97EB00333A11 /* TrailingWhitespaceRule.swift in Sources */,
E832F10B1B17E2F5003F265F /* NSFileManager+SwiftLint.swift in Sources */,
Expand Down
5 changes: 5 additions & 0 deletions Tests/SwiftLintFrameworkTests/RulesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ class RulesTests: XCTestCase {
verifyRule(DiscardedNotificationCenterObserverRule.description)
}

func testDiscouragedInit() {
verifyRule(DiscouragedInitRule.description)
verifyRule(DiscouragedInitRule.description, ruleConfiguration: ["severity": "error"])
}

func testDynamicInline() {
verifyRule(DynamicInlineRule.description)
}
Expand Down

0 comments on commit 8c6a5da

Please sign in to comment.