Skip to content

Commit

Permalink
Remove Swift 2 support
Browse files Browse the repository at this point in the history
Also removes `missing_docs` and `valid_docs` rules.

Fixes realm#1453.
  • Loading branch information
marcelofabri committed Apr 23, 2017
1 parent 80b0c96 commit d73ee8d
Show file tree
Hide file tree
Showing 26 changed files with 125 additions and 910 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

##### Breaking

* None.
* Remove support for Swift 2.
[Marcelo Fabri](https://github.com/marcelofabri)
[#1387](https://github.com/realm/SwiftLint/issues/1453)

* Remove `missing_docs` and `valid_docs` rules since
they were already disabled.
[Marcelo Fabri](https://github.com/marcelofabri)
[#1387](https://github.com/realm/SwiftLint/issues/1453)

##### Enhancements

Expand Down
9 changes: 0 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ XCODEFLAGS=-workspace 'SwiftLint.xcworkspace' \
DSTROOT=$(TEMPORARY_FOLDER) \
OTHER_LDFLAGS=-Wl,-headerpad_max_install_names

SWIFT_2_XCODEFLAGS=-workspace 'SwiftLint.xcworkspace' \
-scheme 'swiftlint with Swift 2.3' \
DSTROOT=$(TEMPORARY_FOLDER) \
OTHER_LDFLAGS=-Wl,-headerpad_max_install_names

BUILT_BUNDLE=$(TEMPORARY_FOLDER)/Applications/swiftlint.app
SWIFTLINTFRAMEWORK_BUNDLE=$(BUILT_BUNDLE)/Contents/Frameworks/SwiftLintFramework.framework
SWIFTLINT_EXECUTABLE=$(BUILT_BUNDLE)/Contents/MacOS/swiftlint
Expand Down Expand Up @@ -42,7 +37,6 @@ bootstrap:
script/bootstrap

test: clean bootstrap
$(BUILD_TOOL) $(SWIFT_2_XCODEFLAGS) test
$(BUILD_TOOL) $(XCODEFLAGS) test

clean:
Expand All @@ -51,9 +45,6 @@ clean:
$(BUILD_TOOL) $(XCODEFLAGS) -configuration Debug clean
$(BUILD_TOOL) $(XCODEFLAGS) -configuration Release clean
$(BUILD_TOOL) $(XCODEFLAGS) -configuration Test clean
$(BUILD_TOOL) $(SWIFT_2_XCODEFLAGS) -configuration Debug clean
$(BUILD_TOOL) $(SWIFT_2_XCODEFLAGS) -configuration Release clean
$(BUILD_TOOL) $(SWIFT_2_XCODEFLAGS) -configuration Test clean

install: uninstall package
sudo installer -pkg SwiftLint.pkg -target /
Expand Down
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,7 @@ You should always run SwiftLint with the same toolchain you use to compile your
code.

You may want to override SwiftLint's default Swift toolchain if you have
multiple toolchains or Xcodes installed, or if you're using legacy Swift
versions (e.g. Swift 2.3 with Xcode 8).
multiple toolchains or Xcodes installed.

Here's the order in which SwiftLint determines which Swift toolchain to use:

Expand Down Expand Up @@ -188,7 +187,7 @@ Guidelines on when to implement a rule as opt-in:
* A rule that can have many false positives (e.g. `empty_count`)
* A rule that is too slow
* A rule that is not general consensus or is only useful in some cases
(e.g. `force_unwrapping`, `missing_docs`)
(e.g. `force_unwrapping`)

### Disable rules in code

Expand Down Expand Up @@ -249,7 +248,6 @@ disabled_rules: # rule identifiers to exclude from running
- control_statement
opt_in_rules: # some rules are only opt-in
- empty_count
- missing_docs
# Find all the available rules by running:
# swiftlint rules
included: # paths to include during linting. `--path` is ignored if present.
Expand Down
48 changes: 48 additions & 0 deletions Source/SwiftLintFramework/Extensions/AccessControlLevel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// AccessControlLevel.swift
// SwiftLint
//
// Created by Marcelo Fabri on 23/04/17.
// Copyright © 2017 Realm. All rights reserved.
//

import Foundation

public enum AccessControlLevel: String, CustomStringConvertible {
case `private` = "source.lang.swift.accessibility.private"
case `fileprivate` = "source.lang.swift.accessibility.fileprivate"
case `internal` = "source.lang.swift.accessibility.internal"
case `public` = "source.lang.swift.accessibility.public"
case `open` = "source.lang.swift.accessibility.open"

internal init?(description value: String) {
switch value {
case "private": self = .private
case "fileprivate": self = .fileprivate
case "internal": self = .internal
case "public": self = .public
case "open": self = .open
default: return nil
}
}

init?(identifier value: String) {
self.init(rawValue: value)
}

public var description: String {
switch self {
case .private: return "private"
case .fileprivate: return "fileprivate"
case .internal: return "internal"
case .public: return "public"
case .open: return "open"
}
}

// Returns true if is `private` or `fileprivate`
var isPrivate: Bool {
return self == .private || self == .fileprivate
}

}
25 changes: 3 additions & 22 deletions Source/SwiftLintFramework/Extensions/Dictionary+SwiftLint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,7 @@ extension Dictionary where Key: ExpressibleByStringLiteral {
}

if SwiftDeclarationKind(rawValue: kindString) == .varParameter {
switch SwiftVersion.current {
case .two, .twoPointThree:
// with Swift 2.3, a closure parameter is inside another .varParameter and not inside an .argument
let parameters = subDict.enclosedVarParameters + [subDict]
return parameters.filter {
$0.typeName != nil
}
case .three:
return [subDict]
}
return [subDict]
} else if SwiftExpressionKind(rawValue: kindString) == .argument {
return subDict.enclosedVarParameters
}
Expand All @@ -114,19 +105,9 @@ extension Dictionary where Key: ExpressibleByStringLiteral {

var enclosedArguments: [[String: SourceKitRepresentable]] {
return substructure.flatMap { subDict -> [[String: SourceKitRepresentable]] in
guard let kindString = subDict.kind else {
return []
}

switch SwiftVersion.current {
case .two, .twoPointThree:
guard SwiftDeclarationKind(rawValue: kindString) == .varParameter else {
return []
}
case .three:
guard SwiftExpressionKind(rawValue: kindString) == .argument else {
guard let kindString = subDict.kind,
SwiftExpressionKind(rawValue: kindString) == .argument else {
return []
}
}

return [subDict]
Expand Down
2 changes: 0 additions & 2 deletions Source/SwiftLintFramework/Models/MasterRuleList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ public let masterRuleList = RuleList(rules:
LegacyNSGeometryFunctionsRule.self,
LineLengthRule.self,
MarkRule.self,
MissingDocsRule.self,
NestingRule.self,
NimbleOperatorRule.self,
NotificationCenterDetachmentRule.self,
Expand Down Expand Up @@ -150,7 +149,6 @@ public let masterRuleList = RuleList(rules:
UnusedClosureParameterRule.self,
UnusedEnumeratedRule.self,
UnusedOptionalBindingRule.self,
ValidDocsRule.self,
ValidIBInspectableRule.self,
VerticalParameterAlignmentRule.self,
VerticalWhitespaceRule.self,
Expand Down
18 changes: 1 addition & 17 deletions Source/SwiftLintFramework/Models/SwiftVersion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,18 @@
//

import Foundation
import SourceKittenFramework

enum SwiftVersion {
case two
case twoPointThree
case three

static let current: SwiftVersion = {
// Allow forcing the Swift version, useful in cases where SourceKit isn't available
if let envVersion = ProcessInfo.processInfo.environment["SWIFTLINT_SWIFT_VERSION"] {
switch envVersion {
case "2": return .two
case "2.3": return .twoPointThree
default: return .three
}
}
let file = File(contents: "#sourceLocation()")
let kinds = file.syntaxMap.tokens.flatMap { SyntaxKind(rawValue: $0.type) }
if kinds == [.identifier] {
let docStructureDescription = File(contents: "/// A\nclass A {}").structure.description
if docStructureDescription.contains("source.decl.attribute.__raw_doc_comment") {
return .two
}
return .twoPointThree
} else if kinds == [.keyword] {
return .three
}

fatalError("Unexpected Swift version")
return .three
}()
}
4 changes: 2 additions & 2 deletions Source/SwiftLintFramework/Rules/AttributesRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public struct AttributesRule: ASTRule, OptInRule, ConfigurationProviderRule {
name: "Attributes",
description: "Attributes should be on their own lines in functions and types, " +
"but on the same line as variables and imports.",
nonTriggeringExamples: AttributesRuleExamples.swift3NonTriggeringExamples,
triggeringExamples: AttributesRuleExamples.swift3TriggeringExamples
nonTriggeringExamples: AttributesRuleExamples.nonTriggeringExamples,
triggeringExamples: AttributesRuleExamples.triggeringExamples
)

public func validate(file: File) -> [StyleViolation] {
Expand Down
31 changes: 4 additions & 27 deletions Source/SwiftLintFramework/Rules/AttributesRulesExamples.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

internal struct AttributesRuleExamples {

private static let commonNonTriggeringExamples = [
static let nonTriggeringExamples = [
"@objc var x: String",
"@objc private var x: String",
"@nonobjc var x: String",
Expand Down Expand Up @@ -39,27 +39,15 @@ internal struct AttributesRuleExamples {

// attribute with allowed empty new line above
"extension Property {\n\n @available(*, unavailable, renamed: \"isOptional\")\n" +
"public var optional: Bool { fatalError() }\n}"
]

static let swift3NonTriggeringExamples = commonNonTriggeringExamples + [
"public var optional: Bool { fatalError() }\n}",
"@GKInspectable var maxSpeed: Float",
"@discardableResult\n func a() -> Int",
"@objc\n @discardableResult\n func a() -> Int",
"func increase(f: @autoclosure () -> Int) -> Int",
"func foo(completionHandler: @escaping () -> Void)"
]

static let swift2NonTriggeringExamples = commonNonTriggeringExamples + [
"@warn_unused_result\n func a() -> Int",
"@objc\n @warn_unused_result\n func a() -> Int",
"func increase(@autoclosure f: () -> Int ) -> Int",
"func foo(@noescape x: Int -> Int)",
"@noreturn\n func exit(_: Int)",
"func exit(_: Int) -> @noreturn Int"
]

static let commonTriggeringExamples = [
static let triggeringExamples = [
"@objc\n ↓var x: String",
"@objc\n\n ↓var x: String",
"@objc\n private ↓var x: String",
Expand Down Expand Up @@ -87,21 +75,10 @@ internal struct AttributesRuleExamples {
"@available(iOS 9.0, *) @objc(abc_stackView)\n ↓let stackView: UIStackView",
"@objc(abc_addSomeObject:) @NSManaged\n ↓func addSomeObject(book: SomeObject)",
"@objc(abc_addSomeObject:)\n @NSManaged\n ↓func addSomeObject(book: SomeObject)",
"@available(iOS 9.0, *)\n @objc(ABCThing) ↓class Thing"
]

static let swift3TriggeringExamples = commonTriggeringExamples + [
"@available(iOS 9.0, *)\n @objc(ABCThing) ↓class Thing",
"@GKInspectable\n ↓var maxSpeed: Float",
"@discardableResult ↓func a() -> Int",
"@objc\n @discardableResult ↓func a() -> Int",
"@objc\n\n @discardableResult\n ↓func a() -> Int"
]

static let swift2TriggeringExamples = commonTriggeringExamples + [
"@warn_unused_result ↓func a() -> Int",
"@warn_unused_result(message=\"You should use this\") ↓func a() -> Int",
"@objc\n @warn_unused_result ↓func a() -> Int",
"@objc\n\n @warn_unused_result\n ↓func a() -> Int",
"@noreturn ↓func exit(_: Int)"
]
}
12 changes: 1 addition & 11 deletions Source/SwiftLintFramework/Rules/ExplicitTypeInterfaceRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,6 @@ public struct ExplicitTypeInterfaceRule: ASTRule, OptInRule, ConfigurationProvid
}

private func containsType(dictionary: [String: SourceKitRepresentable]) -> Bool {
if let typeName = dictionary.typeName {
switch SwiftVersion.current {
// on Swift 2.x, `key.typename` returns the `key.name` if there's no explicit type
case .two, .twoPointThree:
return typeName != dictionary.name
case .three:
return true
}
}

return false
return dictionary.typeName != nil
}
}
18 changes: 6 additions & 12 deletions Source/SwiftLintFramework/Rules/IdentifierNameRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ public struct IdentifierNameRule: ASTRule, ConfigurationProviderRule {
"In an exception to the above, variable names may start with a capital letter " +
"when they are declared static and immutable. Variable names should not be too " +
"long or too short.",
nonTriggeringExamples: IdentifierNameRuleExamples.swift3NonTriggeringExamples,
triggeringExamples: IdentifierNameRuleExamples.swift3TriggeringExamples,
nonTriggeringExamples: IdentifierNameRuleExamples.nonTriggeringExamples,
triggeringExamples: IdentifierNameRuleExamples.triggeringExamples,
deprecatedAliases: ["variable_name"]
)

Expand Down Expand Up @@ -88,23 +88,17 @@ public struct IdentifierNameRule: ASTRule, ConfigurationProviderRule {
kind: SwiftDeclarationKind) -> (name: String, offset: Int)? {
guard let name = dictionary.name,
let offset = dictionary.offset,
kinds(for: .current).contains(kind),
kinds.contains(kind),
!name.hasPrefix("$") else {
return nil
}

return (name.nameStrippingLeadingUnderscoreIfPrivate(dictionary), offset)
}

private func kinds(for version: SwiftVersion) -> [SwiftDeclarationKind] {
let common = SwiftDeclarationKind.variableKinds() + SwiftDeclarationKind.functionKinds()
switch version {
case .two, .twoPointThree:
return common
case .three:
return common + [.enumelement]
}
}
private let kinds: [SwiftDeclarationKind] = {
return SwiftDeclarationKind.variableKinds() + SwiftDeclarationKind.functionKinds() + [.enumelement]
}()

private func type(for kind: SwiftDeclarationKind) -> String {
if SwiftDeclarationKind.functionKinds().contains(kind) {
Expand Down
17 changes: 3 additions & 14 deletions Source/SwiftLintFramework/Rules/IdentifierNameRuleExamples.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import Foundation

internal struct IdentifierNameRuleExamples {
private static let commonNonTriggeringExamples = [
static let nonTriggeringExamples = [
"let myLet = 0",
"var myVar = 0",
"private let _myLet = 0",
Expand All @@ -24,13 +24,7 @@ internal struct IdentifierNameRuleExamples {
"override func IsOperator(name: String) -> Bool"
]

static let swift2NonTriggeringExamples = commonNonTriggeringExamples + [
"enum Foo { case MyEnum }"
]

static let swift3NonTriggeringExamples = commonNonTriggeringExamples

private static let commonTriggeringExamples = [
static let triggeringExamples = [
"↓let MyLet = 0",
"↓let _myLet = 0",
"private ↓let myLet_ = 0",
Expand All @@ -40,12 +34,7 @@ internal struct IdentifierNameRuleExamples {
"↓let i = 0",
"↓var id = 0",
"private ↓let _i = 0",
"↓func IsOperator(name: String) -> Bool"
]

static let swift2TriggeringExamples = commonTriggeringExamples

static let swift3TriggeringExamples = commonTriggeringExamples + [
"↓func IsOperator(name: String) -> Bool",
"enum Foo { case ↓MyEnum }"
]
}
Loading

0 comments on commit d73ee8d

Please sign in to comment.