diff --git a/.swift-version b/.swift-version
index a3ec5a4bd3d..5186d07068c 100644
--- a/.swift-version
+++ b/.swift-version
@@ -1 +1 @@
-3.2
+4.0
diff --git a/.swiftlint.yml b/.swiftlint.yml
index fe1089899f1..d65fe2b9fac 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -4,39 +4,40 @@ included:
excluded:
- Tests/SwiftLintFrameworkTests/Resources
opt_in_rules:
- - empty_count
- - file_header
- - explicit_init
- - closure_spacing
- - overridden_super_call
- - redundant_nil_coalescing
- - private_outlet
- - nimble_operator
+ - array_init
- attributes
- - operator_usage_whitespace
- closure_end_indentation
- - first_where
- - sorted_imports
- - object_literal
- - number_separator
- - prohibited_super_call
+ - closure_spacing
+ - contains_over_first_not_nil
+ - empty_count
+ - explicit_init
+ - extension_access_modifier
- fatal_error_message
- - vertical_parameter_alignment_on_call
+ - file_header
+ - file_name
+ - first_where
+ - joined_default_parameter
- let_var_whitespace
- - unneeded_parentheses_in_closure_argument
- - extension_access_modifier
- - pattern_matching_keywords
- - array_init
- literal_expression_end_indentation
- - joined_default_parameter
- - contains_over_first_not_nil
+ - nimble_operator
+ - number_separator
+ - object_literal
+ - operator_usage_whitespace
+ - overridden_super_call
- override_in_extension
+ - pattern_matching_keywords
- private_action
+ - private_outlet
+ - prohibited_super_call
- quick_discouraged_call
- quick_discouraged_focused_test
- quick_discouraged_pending_test
+ - redundant_nil_coalescing
- single_test_class
- sorted_first_last
+ - sorted_imports
+ - unneeded_parentheses_in_closure_argument
+ - vertical_parameter_alignment_on_call
- yoda_condition
identifier_name:
@@ -45,6 +46,12 @@ identifier_name:
line_length: 120
number_separator:
minimum_length: 5
+file_name:
+ excluded:
+ - main.swift
+ - LinuxMain.swift
+ - TestHelpers.swift
+ - shim.swift
custom_rules:
rule_id:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 64d35228856..17db282a54f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,9 @@
#### Breaking
+* SwiftLint now requires Swift 4.0 or higher to build.
+ [JP Simard](https://github.com/jpsim)
+
* `fallthrough` rule is now opt-in.
[Marcelo Fabri](https://github.com/marcelofabri)
[#1892](https://github.com/realm/SwiftLint/issues/1892)
@@ -12,6 +15,9 @@
only a `fallthrough`.
[Austin Belknap](https://github.com/dabelknap)
+* Updates the `untyped_error_in_catch` rule to support autocorrection.
+ [Daniel Metzing](https://github.com/dirtydanee)
+
* Add `indented_cases` support to `switch_case_alignment` rule.
[Shai Mishali](https://github.com/freak4pc)
[#2119](https://github.com/realm/SwiftLint/issues/2119)
@@ -34,11 +40,21 @@
[Marcelo Fabri](https://github.com/marcelofabri)
[#2127](https://github.com/realm/SwiftLint/issues/2127)
+* Updates the `closure_end_indentation` rule to support autocorrection.
+ [Eric Horacek](https://github.com/erichoracek)
+
+* Updates the `literal_expression_end_indentation` rule to support
+ autocorrection.
+ [Eric Horacek](https://github.com/erichoracek)
+
* Fixes a case where the `closure_end_indentation` rule wouldn't lint the end
indentation of non-trailing closure parameters.
[Eric Horacek](https://github.com/erichoracek)
[#2121](https://github.com/realm/SwiftLint/issues/2121)]
+* Improves the `mark` rule's autocorrection.
+ [Eric Horacek](https://github.com/erichoracek)
+
* Add `redundant_set_access_control` rule to warn against using redundant
setter ACLs on variable declarations.
[Marcelo Fabri](https://github.com/marcelofabri)
@@ -49,12 +65,39 @@
[Michael Gray](https://github.com/mishagray)
[#2100](https://github.com/realm/SwiftLint/pull/2100)
+* Add a new `ignores_default_parameters` config parameter to the
+ `function_parameter_count` rule to ignore default parameter when calculating
+ parameter count. True by default.
+ [Varun P M](https://github.com/varunpm1)
+ [#2171](https://github.com/realm/SwiftLint/issues/2171)
+
+* Add `empty_xctest_method` opt-in rule which warns against empty
+ XCTest methods.
+ [Ornithologist Coder](https://github.com/ornithocoder)
+ [#2190](https://github.com/realm/SwiftLint/pull/2190)
+
+* Add `function_default_parameter_at_end` opt-in rule to validate that
+ parameters with defaults are located toward the end of the parameter list in a
+ function declaration.
+ [Marcelo Fabri](https://github.com/marcelofabri)
+ [#2176](https://github.com/realm/SwiftLint/issues/2176)
+
+* Add `file_name` opt-in rule validating that file names contain the name of a
+ type or extension declared in the file (if any).
+ [JP Simard](https://github.com/jpsim)
+ [#1420](https://github.com/realm/SwiftLint/issues/1420)
+
#### Bug Fixes
* Update `LowerACLThanParent` rule to not lint extensions.
[Keith Smiley](https://github.com/keith)
[#2164](https://github.com/realm/SwiftLint/pull/2164)
+* Fix operator usage spacing nested generics false positive.
+ [Eric Horacek](https://github.com/erichoracek)
+ [#1341](https://github.com/realm/SwiftLint/issues/1341)
+ [#1897](https://github.com/realm/SwiftLint/issues/1897)
+
* Fix autocorrection for several rules
(`empty_parentheses_with_trailing_closure`, `explicit_init`,
`joined_default_parameter`, `redundant_optional_initialization` and
@@ -62,6 +105,29 @@
[John Szumski](https://github.com/jszumski)
[Marcelo Fabri](https://github.com/marcelofabri)
+* Fix `unneeded_parentheses_in_closure_argument` false negatives when multiple
+ violations are nested.
+ [Marcelo Fabri](https://github.com/marcelofabri)
+ [#2188](https://github.com/realm/SwiftLint/issues/2188)
+
+* Fix false negatives in `implicit_return` rule when using closures as
+ function arguments.
+ [Marcelo Fabri](https://github.com/marcelofabri)
+ [#2187](https://github.com/realm/SwiftLint/issues/2187)
+
+* Fix false positives in `attributes` rule when `@testable` is used.
+ [Marcelo Fabri](https://github.com/marcelofabri)
+ [#2211](https://github.com/realm/SwiftLint/issues/2211)
+
+* Fix false positives in `prohibited_super_call` rule.
+ [Marcelo Fabri](https://github.com/marcelofabri)
+ [#2212](https://github.com/realm/SwiftLint/issues/2212)
+
+* Fix a false positive in `unused_closure_parameter` rule when a parameter
+ is used in a string interpolation.
+ [Marcelo Fabri](https://github.com/marcelofabri)
+ [#2062](https://github.com/realm/SwiftLint/issues/2062)
+
## 0.25.1: Lid Locked
This is the last release to support building with Swift 3.2 and Swift 3.3.
diff --git a/Cartfile.private b/Cartfile.private
index 60c09dcfaa6..34899b9ac7a 100644
--- a/Cartfile.private
+++ b/Cartfile.private
@@ -1,3 +1,3 @@
github "Carthage/Commandant" ~> 0.13.0
-github "jspahrsummers/xcconfigs" "master"
+github "jspahrsummers/xcconfigs" ~> 0.12.0
github "jpsim/Yams" ~> 0.7
diff --git a/Cartfile.resolved b/Cartfile.resolved
index f7e844cfb8f..35820d7ff53 100644
--- a/Cartfile.resolved
+++ b/Cartfile.resolved
@@ -1,7 +1,7 @@
github "Carthage/Commandant" "0.13.0"
github "antitypical/Result" "3.2.4"
-github "drmohundro/SWXMLHash" "4.6.0"
+github "drmohundro/SWXMLHash" "4.7.0"
github "jpsim/SourceKitten" "0.21.0"
github "jpsim/Yams" "0.7.0"
-github "jspahrsummers/xcconfigs" "bb795558a76e5daf3688500055bbcfe243bffa8d"
+github "jspahrsummers/xcconfigs" "0.12"
github "scottrhoyt/SwiftyTextTable" "0.8.0"
diff --git a/Carthage/Checkouts/SWXMLHash b/Carthage/Checkouts/SWXMLHash
index 17d992beb3a..2211b35c2e0 160000
--- a/Carthage/Checkouts/SWXMLHash
+++ b/Carthage/Checkouts/SWXMLHash
@@ -1 +1 @@
-Subproject commit 17d992beb3aaeda403fd35f8d5e70ab1a8124f35
+Subproject commit 2211b35c2e0e8b08493f86ba52b26e530cabb751
diff --git a/Package.swift b/Package.swift
index b246c87a92c..eb3ff3e1237 100644
--- a/Package.swift
+++ b/Package.swift
@@ -38,6 +38,5 @@ let package = Package(
"Resources",
]
)
- ],
- swiftLanguageVersions: [3, 4]
+ ]
)
diff --git a/Rules.md b/Rules.md
index c9c7f791813..1d5f2ff79e7 100644
--- a/Rules.md
+++ b/Rules.md
@@ -28,6 +28,7 @@
* [Empty Parameters](#empty-parameters)
* [Empty Parentheses with Trailing Closure](#empty-parentheses-with-trailing-closure)
* [Empty String](#empty-string)
+* [Empty XCTest Method](#empty-xctest-method)
* [Explicit ACL](#explicit-acl)
* [Explicit Enum Raw Value](#explicit-enum-raw-value)
* [Explicit Init](#explicit-init)
@@ -38,12 +39,14 @@
* [Fatal Error Message](#fatal-error-message)
* [File Header](#file-header)
* [File Line Length](#file-line-length)
+* [File Name](#file-name)
* [First Where](#first-where)
* [For Where](#for-where)
* [Force Cast](#force-cast)
* [Force Try](#force-try)
* [Force Unwrapping](#force-unwrapping)
* [Function Body Length](#function-body-length)
+* [Function Default Parameter at End](#function-default-parameter-at-end)
* [Function Parameter Count](#function-parameter-count)
* [Generic Type Name](#generic-type-name)
* [Identifier Name](#identifier-name)
@@ -427,6 +430,15 @@ private struct DefaultError: Error {}
private let bar = 1
```
+```swift
+import XCTest
+@testable import DeleteMe
+
+@available (iOS 11.0, *)
+class DeleteMeTests: XCTestCase {
+}
+```
+
Triggering Examples
@@ -759,7 +771,7 @@ Closing brace with closing parenthesis should not have any whitespaces in the mi
Identifier | Enabled by default | Supports autocorrection | Kind | Minimum Swift Compiler Version
--- | --- | --- | --- | ---
-`closure_end_indentation` | Disabled | No | style | 3.0.0
+`closure_end_indentation` | Disabled | Yes | style | 3.0.0
Closure end should have the same indentation as the line that started it.
@@ -4193,6 +4205,166 @@ myString↓ != ""
+## Empty XCTest Method
+
+Identifier | Enabled by default | Supports autocorrection | Kind | Minimum Swift Compiler Version
+--- | --- | --- | --- | ---
+`empty_xctest_method` | Disabled | No | lint | 3.0.0
+
+Empty XCTest method should be avoided.
+
+### Examples
+
+
+Non Triggering Examples
+
+```swift
+class TotoTests: XCTestCase {
+ var foobar: Foobar?
+
+ override func setUp() {
+ super.setUp()
+ foobar = Foobar()
+ }
+
+ override func tearDown() {
+ foobar = nil
+ super.tearDown()
+ }
+
+ func testFoo() {
+ XCTAssertTrue(foobar?.foo)
+ }
+
+ func testBar() {
+ // comment...
+
+ XCTAssertFalse(foobar?.bar)
+
+ // comment...
+ }
+}
+```
+
+```swift
+class Foobar {
+ func setUp() {}
+
+ func tearDown() {}
+
+ func testFoo() {}
+}
+```
+
+```swift
+class TotoTests: XCTestCase {
+ func setUp(with object: Foobar) {}
+
+ func tearDown(object: Foobar) {}
+
+ func testFoo(_ foo: Foobar) {}
+
+ func testBar(bar: (String) -> Int) {}
+}
+```
+
+```swift
+class TotoTests: XCTestCase {
+ func testFoo() { XCTAssertTrue(foobar?.foo) }
+
+ func testBar() { XCTAssertFalse(foobar?.bar) }
+}
+```
+
+
+
+Triggering Examples
+
+```swift
+class TotoTests: XCTestCase {
+ override ↓func setUp() {
+ }
+
+ override ↓func tearDown() {
+
+ }
+
+ ↓func testFoo() {
+
+
+ }
+
+ ↓func testBar() {
+
+
+
+ }
+
+ func helperFunction() {
+ }
+}
+```
+
+```swift
+class TotoTests: XCTestCase {
+ override ↓func setUp() {}
+
+ override ↓func tearDown() {}
+
+ ↓func testFoo() {}
+
+ func helperFunction() {}
+}
+```
+
+```swift
+class TotoTests: XCTestCase {
+ override ↓func setUp() {
+ // comment...
+ }
+
+ override ↓func tearDown() {
+ // comment...
+ // comment...
+ }
+
+ ↓func testFoo() {
+ // comment...
+
+ // comment...
+
+ // comment...
+ }
+
+ ↓func testBar() {
+ /*
+ * comment...
+ *
+ * comment...
+ *
+ * comment...
+ */
+ }
+
+ func helperFunction() {
+ }
+}
+```
+
+```swift
+class FooTests: XCTestCase {
+ override ↓func setUp() {}
+}
+
+class BarTests: XCTestCase {
+ ↓func testFoo() {}
+}
+```
+
+
+
+
+
## Explicit ACL
Identifier | Enabled by default | Supports autocorrection | Kind | Minimum Swift Compiler Version
@@ -6086,6 +6258,16 @@ print("swiftlint")
+## File Name
+
+Identifier | Enabled by default | Supports autocorrection | Kind | Minimum Swift Compiler Version
+--- | --- | --- | --- | ---
+`file_name` | Disabled | No | idiomatic | 3.0.0
+
+File name should match a type or extension declared in the file (if any).
+
+
+
## First Where
Identifier | Enabled by default | Supports autocorrection | Kind | Minimum Swift Compiler Version
@@ -6478,6 +6660,70 @@ Functions bodies should not span too many lines.
+## Function Default Parameter at End
+
+Identifier | Enabled by default | Supports autocorrection | Kind | Minimum Swift Compiler Version
+--- | --- | --- | --- | ---
+`function_default_parameter_at_end` | Disabled | No | idiomatic | 3.0.0
+
+Prefer to locate parameters with defaults toward the end of the parameter list.
+
+### Examples
+
+
+Non Triggering Examples
+
+```swift
+func foo(baz: String, bar: Int = 0) {}
+```
+
+```swift
+func foo(x: String, y: Int = 0, z: CGFloat = 0) {}
+```
+
+```swift
+func foo(bar: String, baz: Int = 0, z: () -> Void) {}
+```
+
+```swift
+func foo(bar: String, z: () -> Void, baz: Int = 0) {}
+```
+
+```swift
+func foo(bar: Int = 0) {}
+```
+
+```swift
+func foo() {}
+```
+
+```swift
+class A: B {
+ override func foo(bar: Int = 0, baz: String) {}
+```
+
+```swift
+func foo(bar: Int = 0, completion: @escaping CompletionHandler) {}
+```
+
+```swift
+func foo(a: Int, b: CGFloat = 0) {
+ let block = { (error: Error?) in }
+}
+```
+
+
+
+Triggering Examples
+
+```swift
+↓func foo(bar: Int = 0, baz: String) {}
+```
+
+
+
+
+
## Function Parameter Count
Identifier | Enabled by default | Supports autocorrection | Kind | Minimum Swift Compiler Version
@@ -7132,6 +7378,16 @@ foo.map {
}
```
+```swift
+foo.map({ ↓return $0 + 1})
+```
+
+```swift
+[1, 2].first(where: {
+ ↓return true
+})
+```
+
@@ -8397,7 +8653,7 @@ Lines should not span too many characters.
Identifier | Enabled by default | Supports autocorrection | Kind | Minimum Swift Compiler Version
--- | --- | --- | --- | ---
-`literal_expression_end_indentation` | Disabled | No | style | 3.0.0
+`literal_expression_end_indentation` | Disabled | Yes | style | 3.0.0
Array and dictionary literal end should have the same indentation as the line that started it.
@@ -8671,6 +8927,22 @@ MARK comment should be in valid format. e.g. '// MARK: ...' or '// MARK: - ...'
↓// MARK - bad
```
+```swift
+↓//MARK : bad
+```
+
+```swift
+↓// MARKL:
+```
+
+```swift
+↓// MARKR
+```
+
+```swift
+↓// MARKK -
+```
+
```swift
↓//MARK:- Top-Level bad mark
↓//MARK:- Another bad mark
@@ -10780,6 +11052,11 @@ let foo: Array
```
+```swift
+let model = CustomView, NSAttributedString>()
+
+```
+
```swift
let foo: [String]
@@ -10833,6 +11110,21 @@ let doubleValue = -9e-11
```
+```swift
+let foo = GenericType<(UIViewController) -> Void>()
+
+```
+
+```swift
+let foo = Foo, Baz>()
+
+```
+
+```swift
+let foo = SignalProducer, Error>([ self.signal, next ]).flatten(.concat)
+
+```
+
Triggering Examples
@@ -11793,18 +12085,28 @@ Some methods should not call super
```swift
class VC: UIViewController {
- override func loadView() {
- }
+ override func loadView() {
+ }
}
-
```
```swift
class NSView {
- func updateLayer() {
- self.method1() }
+ func updateLayer() {
+ self.method1()
+ }
}
+```
+```swift
+public class FileProviderExtension: NSFileProviderExtension {
+ override func providePlaceholder(at url: URL, completionHandler: @escaping (Error?) -> Void) {
+ guard let identifier = persistentIdentifierForItem(at: url) else {
+ completionHandler(NSFileProviderError(.noSuchItem))
+ return
+ }
+ }
+}
```
@@ -11813,43 +12115,39 @@ class NSView {
```swift
class VC: UIViewController {
- override func loadView() {↓
- super.loadView()
- }
+ override func loadView() {↓
+ super.loadView()
+ }
}
-
```
```swift
class VC: NSFileProviderExtension {
- override func providePlaceholder(at url: URL,completionHandler: @escaping (Error?) -> Void) {↓
- self.method1()
- super.providePlaceholder(at:url, completionHandler: completionHandler)
- }
+ override func providePlaceholder(at url: URL, completionHandler: @escaping (Error?) -> Void) {↓
+ self.method1()
+ super.providePlaceholder(at:url, completionHandler: completionHandler)
+ }
}
-
```
```swift
class VC: NSView {
- override func updateLayer() {↓
- self.method1()
- super.updateLayer()
- self.method2()
- }
+ override func updateLayer() {↓
+ self.method1()
+ super.updateLayer()
+ self.method2()
+ }
}
-
```
```swift
class VC: NSView {
- override func updateLayer() {↓
- defer {
- super.updateLayer()
- }
- }
+ override func updateLayer() {↓
+ defer {
+ super.updateLayer()
+ }
+ }
}
-
```
@@ -18134,6 +18432,32 @@ foo.map { ($0, $0) }.forEach { ↓(x, y) in }
foo.bar { [weak self] ↓(x, y) in }
```
+```swift
+[].first { ↓(temp) in
+ [].first { ↓(temp) in
+ [].first { ↓(temp) in
+ _ = temp
+ return false
+ }
+ return false
+ }
+ return false
+}
+```
+
+```swift
+[].first { temp in
+ [].first { ↓(temp) in
+ [].first { ↓(temp) in
+ _ = temp
+ return false
+ }
+ return false
+ }
+ return false
+}
+```
+
@@ -18142,7 +18466,7 @@ foo.bar { [weak self] ↓(x, y) in }
Identifier | Enabled by default | Supports autocorrection | Kind | Minimum Swift Compiler Version
--- | --- | --- | --- | ---
-`untyped_error_in_catch` | Disabled | No | idiomatic | 3.0.0
+`untyped_error_in_catch` | Disabled | Yes | idiomatic | 3.0.0
Catch statements should not declare error variables without type casting.
@@ -18320,6 +18644,12 @@ hoge(arg: num) { num in
})(FileManager.default)
```
+```swift
+withPostSideEffect { input in
+ if true { print("\(input)") }
+}
+```
+
Triggering Examples
diff --git a/Source/SwiftLintFramework/Extensions/Configuration+Merging.swift b/Source/SwiftLintFramework/Extensions/Configuration+Merging.swift
index 2337fc7991a..ecbf4316c0d 100644
--- a/Source/SwiftLintFramework/Extensions/Configuration+Merging.swift
+++ b/Source/SwiftLintFramework/Extensions/Configuration+Merging.swift
@@ -46,11 +46,11 @@ extension Configuration {
}
let isDirectory: Bool
- #if os(Linux) && (!swift(>=4.1) || (!swift(>=4.0) && swift(>=3.3)))
- isDirectory = isDirectoryObjC
- #else
- isDirectory = isDirectoryObjC.boolValue
- #endif
+#if os(Linux) && !swift(>=4.1)
+ isDirectory = isDirectoryObjC
+#else
+ isDirectory = isDirectoryObjC.boolValue
+#endif
if isDirectory {
return rootPath
diff --git a/Source/SwiftLintFramework/Extensions/Dictionary+SwiftLint.swift b/Source/SwiftLintFramework/Extensions/Dictionary+SwiftLint.swift
index d77cda667dc..6fd518afb2a 100644
--- a/Source/SwiftLintFramework/Extensions/Dictionary+SwiftLint.swift
+++ b/Source/SwiftLintFramework/Extensions/Dictionary+SwiftLint.swift
@@ -122,11 +122,14 @@ extension Dictionary where Key: ExpressibleByStringLiteral {
}
internal func extractCallsToSuper(methodName: String) -> [String] {
- let superCall = "super.\(methodName)"
+ guard let methodNameWithoutArguments = methodName.split(separator: "(").first else {
+ return []
+ }
+ let superCall = "super.\(methodNameWithoutArguments)"
return substructure.flatMap { elems -> [String] in
- guard let type = elems.kind.flatMap({ SwiftExpressionKind(rawValue: $0) }),
+ guard let type = elems.kind.flatMap(SwiftExpressionKind.init),
let name = elems.name,
- type == .call && superCall.contains(name) else {
+ type == .call && superCall == name else {
return elems.extractCallsToSuper(methodName: methodName)
}
return [name]
diff --git a/Source/SwiftLintFramework/Extensions/NSFileManager+SwiftLint.swift b/Source/SwiftLintFramework/Extensions/FileManager+SwiftLint.swift
similarity index 100%
rename from Source/SwiftLintFramework/Extensions/NSFileManager+SwiftLint.swift
rename to Source/SwiftLintFramework/Extensions/FileManager+SwiftLint.swift
diff --git a/Source/SwiftLintFramework/Extensions/NSRegularExpression+SwiftLint.swift b/Source/SwiftLintFramework/Extensions/NSRegularExpression+SwiftLint.swift
index a38656d7986..1c3ddaea565 100644
--- a/Source/SwiftLintFramework/Extensions/NSRegularExpression+SwiftLint.swift
+++ b/Source/SwiftLintFramework/Extensions/NSRegularExpression+SwiftLint.swift
@@ -1,19 +1,5 @@
import Foundation
-#if os(Linux)
-#if !swift(>=4.0)
-public typealias NSTextCheckingResult = TextCheckingResult
-#endif
-#else
-#if !swift(>=4.0)
-extension NSTextCheckingResult {
- internal func range(at idx: Int) -> NSRange {
- return rangeAt(idx)
- }
-}
-#endif
-#endif
-
private var regexCache = [RegexCacheKey: NSRegularExpression]()
private let regexCacheLock = NSLock()
diff --git a/Source/SwiftLintFramework/Extensions/String+SwiftLint.swift b/Source/SwiftLintFramework/Extensions/String+SwiftLint.swift
index 7fb38c017fe..18681e69c05 100644
--- a/Source/SwiftLintFramework/Extensions/String+SwiftLint.swift
+++ b/Source/SwiftLintFramework/Extensions/String+SwiftLint.swift
@@ -78,11 +78,11 @@ extension String {
internal var isFile: Bool {
var isDirectoryObjC: ObjCBool = false
if FileManager.default.fileExists(atPath: self, isDirectory: &isDirectoryObjC) {
- #if os(Linux) && (!swift(>=4.1) || (!swift(>=4.0) && swift(>=3.3)))
- return !isDirectoryObjC
- #else
- return !isDirectoryObjC.boolValue
- #endif
+#if os(Linux) && !swift(>=4.1)
+ return !isDirectoryObjC
+#else
+ return !isDirectoryObjC.boolValue
+#endif
}
return false
}
diff --git a/Source/SwiftLintFramework/Extensions/SyntaxMap+SwiftLint.swift b/Source/SwiftLintFramework/Extensions/SyntaxMap+SwiftLint.swift
index faf21fc0b53..3c491ee88d6 100644
--- a/Source/SwiftLintFramework/Extensions/SyntaxMap+SwiftLint.swift
+++ b/Source/SwiftLintFramework/Extensions/SyntaxMap+SwiftLint.swift
@@ -12,18 +12,11 @@ extension SyntaxMap {
.intersects(byteRange)
}
- func notIntersect(_ token: SyntaxToken) -> Bool {
- return !intersect(token)
- }
-
guard let startIndex = tokens.index(where: intersect) else {
return []
}
let tokensBeginningIntersect = tokens.lazy.suffix(from: startIndex)
- if let endIndex = tokensBeginningIntersect.index(where: notIntersect) {
- return Array(tokensBeginningIntersect.prefix(upTo: endIndex))
- }
- return Array(tokensBeginningIntersect)
+ return Array(tokensBeginningIntersect.filter(intersect))
}
internal func kinds(inByteRange byteRange: NSRange) -> [SyntaxKind] {
diff --git a/Source/SwiftLintFramework/Extensions/shim.swift b/Source/SwiftLintFramework/Extensions/shim.swift
index 2b6edaa89b4..d7817537fd2 100644
--- a/Source/SwiftLintFramework/Extensions/shim.swift
+++ b/Source/SwiftLintFramework/Extensions/shim.swift
@@ -1,11 +1,11 @@
-#if (!swift(>=4.1) && swift(>=4.0)) || !swift(>=3.3)
+#if !swift(>=4.1)
- extension Sequence {
- func compactMap(
- _ transform: (Self.Element
- ) throws -> ElementOfResult?) rethrows -> [ElementOfResult] {
- return try flatMap(transform)
- }
+extension Sequence {
+ func compactMap(
+ _ transform: (Self.Element
+ ) throws -> ElementOfResult?) rethrows -> [ElementOfResult] {
+ return try flatMap(transform)
}
+}
#endif
diff --git a/Source/SwiftLintFramework/Models/Configuration.swift b/Source/SwiftLintFramework/Models/Configuration.swift
index 86464cf87ca..9d975b78cf8 100644
--- a/Source/SwiftLintFramework/Models/Configuration.swift
+++ b/Source/SwiftLintFramework/Models/Configuration.swift
@@ -253,11 +253,11 @@ private extension String {
func isDirectory() -> Bool {
var isDir: ObjCBool = false
if FileManager.default.fileExists(atPath: self, isDirectory: &isDir) {
- #if os(Linux) && (!swift(>=4.1) || (!swift(>=4.0) && swift(>=3.3)))
- return isDir
- #else
- return isDir.boolValue
- #endif
+#if os(Linux) && !swift(>=4.1)
+ return isDir
+#else
+ return isDir.boolValue
+#endif
}
return false
diff --git a/Source/SwiftLintFramework/Models/MasterRuleList.swift b/Source/SwiftLintFramework/Models/MasterRuleList.swift
index f3329c10de6..47b74b03dce 100644
--- a/Source/SwiftLintFramework/Models/MasterRuleList.swift
+++ b/Source/SwiftLintFramework/Models/MasterRuleList.swift
@@ -29,6 +29,7 @@ public let masterRuleList = RuleList(rules: [
EmptyParametersRule.self,
EmptyParenthesesWithTrailingClosureRule.self,
EmptyStringRule.self,
+ EmptyXCTestMethodRule.self,
ExplicitACLRule.self,
ExplicitEnumRawValueRule.self,
ExplicitInitRule.self,
@@ -39,12 +40,14 @@ public let masterRuleList = RuleList(rules: [
FatalErrorMessageRule.self,
FileHeaderRule.self,
FileLengthRule.self,
+ FileNameRule.self,
FirstWhereRule.self,
ForWhereRule.self,
ForceCastRule.self,
ForceTryRule.self,
ForceUnwrappingRule.self,
FunctionBodyLengthRule.self,
+ FunctionDefaultParameterAtEndRule.self,
FunctionParameterCountRule.self,
GenericTypeNameRule.self,
IdentifierNameRule.self,
diff --git a/Source/SwiftLintFramework/Models/SwiftVersion.swift b/Source/SwiftLintFramework/Models/SwiftVersion.swift
index 7b97a37fa4b..c43583f4f61 100644
--- a/Source/SwiftLintFramework/Models/SwiftVersion.swift
+++ b/Source/SwiftLintFramework/Models/SwiftVersion.swift
@@ -37,6 +37,8 @@ public extension SwiftVersion {
let file = File(contents: """
#if swift(>=4.2.0)
let version = "4.2.0"
+ #elseif swift(>=4.1.2)
+ let version = "4.1.2"
#elseif swift(>=4.1.1)
let version = "4.1.1"
#elseif swift(>=4.1.0)
@@ -51,6 +53,8 @@ public extension SwiftVersion {
let version = "4.0.0"
#elseif swift(>=3.4.0)
let version = "3.4.0"
+ #elseif swift(>=3.3.2)
+ let version = "3.3.2"
#elseif swift(>=3.3.1)
let version = "3.3.1"
#elseif swift(>=3.3.0)
diff --git a/Source/SwiftLintFramework/Rules/AttributesRule.swift b/Source/SwiftLintFramework/Rules/AttributesRule.swift
index 75a3dd202d9..fb05aaeca79 100644
--- a/Source/SwiftLintFramework/Rules/AttributesRule.swift
+++ b/Source/SwiftLintFramework/Rules/AttributesRule.swift
@@ -209,7 +209,7 @@ public struct AttributesRule: ASTRule, OptInRule, ConfigurationProviderRule {
return false
}
- return ["func", "var", "let"].contains(keyword)
+ return ["func", "var", "let", "import"].contains(keyword)
}
guard nonAttributeTokens.isEmpty else {
diff --git a/Source/SwiftLintFramework/Rules/AttributesRulesExamples.swift b/Source/SwiftLintFramework/Rules/AttributesRuleExamples.swift
similarity index 94%
rename from Source/SwiftLintFramework/Rules/AttributesRulesExamples.swift
rename to Source/SwiftLintFramework/Rules/AttributesRuleExamples.swift
index eea45ae3a5e..700092abf38 100644
--- a/Source/SwiftLintFramework/Rules/AttributesRulesExamples.swift
+++ b/Source/SwiftLintFramework/Rules/AttributesRuleExamples.swift
@@ -38,7 +38,15 @@ internal struct AttributesRuleExamples {
"func increase(f: @autoclosure () -> Int) -> Int",
"func foo(completionHandler: @escaping () -> Void)",
"private struct DefaultError: Error {}",
- "@testable import foo\n\nprivate let bar = 1"
+ "@testable import foo\n\nprivate let bar = 1",
+ """
+ import XCTest
+ @testable import DeleteMe
+
+ @available (iOS 11.0, *)
+ class DeleteMeTests: XCTestCase {
+ }
+ """
]
static let triggeringExamples = [
diff --git a/Source/SwiftLintFramework/Rules/ClosureEndIndentationRule.swift b/Source/SwiftLintFramework/Rules/ClosureEndIndentationRule.swift
index b4ad7b043ac..e1fcb0ee46f 100644
--- a/Source/SwiftLintFramework/Rules/ClosureEndIndentationRule.swift
+++ b/Source/SwiftLintFramework/Rules/ClosureEndIndentationRule.swift
@@ -1,65 +1,7 @@
import Foundation
import SourceKittenFramework
-internal struct ClosureEndIndentationRuleExamples {
-
- static let nonTriggeringExamples = [
- "SignalProducer(values: [1, 2, 3])\n" +
- " .startWithNext { number in\n" +
- " print(number)\n" +
- " }\n",
- "[1, 2].map { $0 + 1 }\n",
- "return match(pattern: pattern, with: [.comment]).flatMap { range in\n" +
- " return Command(string: contents, range: range)\n" +
- "}.flatMap { command in\n" +
- " return command.expand()\n" +
- "}\n",
- "foo(foo: bar,\n" +
- " options: baz) { _ in }\n",
- "someReallyLongProperty.chainingWithAnotherProperty\n" +
- " .foo { _ in }",
- "foo(abc, 123)\n" +
- "{ _ in }\n",
- "function(\n" +
- " closure: { x in\n" +
- " print(x)\n" +
- " },\n" +
- " anotherClosure: { y in\n" +
- " print(y)\n" +
- " })",
- "function(parameter: param,\n" +
- " closure: { x in\n" +
- " print(x)\n" +
- "})",
- "function(parameter: param, closure: { x in\n" +
- " print(x)\n" +
- " },\n" +
- " anotherClosure: { y in\n" +
- " print(y)\n" +
- " })"
- ]
-
- static let triggeringExamples = [
- "SignalProducer(values: [1, 2, 3])\n" +
- " .startWithNext { number in\n" +
- " print(number)\n" +
- "↓}\n",
- "return match(pattern: pattern, with: [.comment]).flatMap { range in\n" +
- " return Command(string: contents, range: range)\n" +
- " ↓}.flatMap { command in\n" +
- " return command.expand()\n" +
- "↓}\n",
- "function(\n" +
- " closure: { x in\n" +
- " print(x)\n" +
- "↓},\n" +
- " anotherClosure: { y in\n" +
- " print(y)\n" +
- "↓})"
- ]
-}
-
-public struct ClosureEndIndentationRule: ASTRule, OptInRule, ConfigurationProviderRule {
+public struct ClosureEndIndentationRule: Rule, OptInRule, ConfigurationProviderRule {
public var configuration = SeverityConfiguration(.warning)
public init() {}
@@ -70,19 +12,139 @@ public struct ClosureEndIndentationRule: ASTRule, OptInRule, ConfigurationProvid
description: "Closure end should have the same indentation as the line that started it.",
kind: .style,
nonTriggeringExamples: ClosureEndIndentationRuleExamples.nonTriggeringExamples,
- triggeringExamples: ClosureEndIndentationRuleExamples.triggeringExamples
+ triggeringExamples: ClosureEndIndentationRuleExamples.triggeringExamples,
+ corrections: ClosureEndIndentationRuleExamples.corrections
)
- private static let notWhitespace = regex("[^\\s]")
+ fileprivate static let notWhitespace = regex("[^\\s]")
+
+ public func validate(file: File) -> [StyleViolation] {
+ return violations(in: file).map { violation in
+ return styleViolation(for: violation, in: file)
+ }
+ }
+
+ private func styleViolation(for violation: Violation, in file: File) -> StyleViolation {
+ let reason = "Closure end should have the same indentation as the line that started it. " +
+ "Expected \(violation.indentationRanges.expected.length), " +
+ "got \(violation.indentationRanges.actual.length)."
+
+ return StyleViolation(ruleDescription: type(of: self).description,
+ severity: configuration.severity,
+ location: Location(file: file, byteOffset: violation.endOffset),
+ reason: reason)
+ }
+
+}
+
+extension ClosureEndIndentationRule: CorrectableRule {
+ public func correct(file: File) -> [Correction] {
+ let allViolations = violations(in: file).reversed().filter {
+ !file.ruleEnabled(violatingRanges: [$0.range], for: self).isEmpty
+ }
+
+ guard !allViolations.isEmpty else {
+ return []
+ }
- public func validate(file: File, kind: SwiftExpressionKind,
- dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
+ var correctedContents = file.contents
+ var correctedLocations: [Int] = []
+
+ let actualLookup = actualViolationLookup(for: allViolations)
+
+ for violation in allViolations {
+ let expected = actualLookup(violation).indentationRanges.expected
+ let actual = violation.indentationRanges.actual
+ if correct(contents: &correctedContents, expected: expected, actual: actual) {
+ correctedLocations.append(actual.location)
+ }
+ }
+
+ var corrections = correctedLocations.map {
+ return Correction(ruleDescription: type(of: self).description,
+ location: Location(file: file, characterOffset: $0))
+ }
+
+ file.write(correctedContents)
+
+ // Re-correct to catch cascading indentation from the first round.
+ corrections += correct(file: file)
+
+ return corrections
+ }
+
+ private func correct(contents: inout String, expected: NSRange, actual: NSRange) -> Bool {
+ guard let actualIndices = contents.nsrangeToIndexRange(actual) else {
+ return false
+ }
+
+ let regex = ClosureEndIndentationRule.notWhitespace
+ if regex.firstMatch(in: contents, options: [], range: actual) != nil {
+ var correction = "\n"
+ correction.append(contents.substring(from: expected.location, length: expected.length))
+ contents.insert(contentsOf: correction, at: actualIndices.upperBound)
+ } else {
+ let correction = contents.substring(from: expected.location, length: expected.length)
+ contents = contents.replacingCharacters(in: actualIndices, with: correction)
+ }
+
+ return true
+ }
+
+ private func actualViolationLookup(for violations: [Violation]) -> (Violation) -> Violation {
+ let lookup = violations.reduce(into: [NSRange: Violation](), { result, violation in
+ result[violation.indentationRanges.actual] = violation
+ })
+
+ func actualViolation(for violation: Violation) -> Violation {
+ guard let actual = lookup[violation.indentationRanges.expected] else { return violation }
+ return actualViolation(for: actual)
+ }
+
+ return actualViolation
+ }
+}
+
+extension ClosureEndIndentationRule {
+
+ fileprivate struct Violation {
+ var location: Location
+ var indentationRanges: (expected: NSRange, actual: NSRange)
+ var endOffset: Int
+ var range: NSRange
+ }
+
+ fileprivate func violations(in file: File) -> [Violation] {
+ return violations(in: file, dictionary: file.structure.dictionary)
+ }
+
+ private func violations(in file: File,
+ dictionary: [String: SourceKitRepresentable]) -> [Violation] {
+ return dictionary.substructure.flatMap { subDict -> [Violation] in
+ var subViolations = violations(in: file, dictionary: subDict)
+
+ if let kindString = subDict.kind,
+ let kind = SwiftExpressionKind(rawValue: kindString) {
+ subViolations += violations(in: file, of: kind, dictionary: subDict)
+ }
+
+ return subViolations
+ }
+ }
+
+ private func violations(in file: File, of kind: SwiftExpressionKind,
+ dictionary: [String: SourceKitRepresentable]) -> [Violation] {
guard kind == .call else {
return []
}
- return validateArguments(in: file, dictionary: dictionary) +
- validateCall(in: file, dictionary: dictionary)
+ var violations = validateArguments(in: file, dictionary: dictionary)
+
+ if let callViolation = validateCall(in: file, dictionary: dictionary) {
+ violations.append(callViolation)
+ }
+
+ return violations
}
private func hasTrailingClosure(in file: File,
@@ -99,7 +161,7 @@ public struct ClosureEndIndentationRule: ASTRule, OptInRule, ConfigurationProvid
}
private func validateCall(in file: File,
- dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
+ dictionary: [String: SourceKitRepresentable]) -> Violation? {
let contents = file.contents.bridge()
guard let offset = dictionary.offset,
let length = dictionary.length,
@@ -116,7 +178,7 @@ public struct ClosureEndIndentationRule: ASTRule, OptInRule, ConfigurationProvid
let (bodyOffsetLine, _) = contents.lineAndCharacter(forByteOffset: nameEndPosition),
startLine != endLine, bodyOffsetLine != endLine,
!containsSingleLineClosure(dictionary: dictionary, endPosition: endOffset, file: file) else {
- return []
+ return nil
}
let range = file.lines[startLine - 1].range
@@ -125,21 +187,23 @@ public struct ClosureEndIndentationRule: ASTRule, OptInRule, ConfigurationProvid
guard let match = regex.firstMatch(in: file.contents, options: [], range: range)?.range,
case let expected = match.location - range.location,
expected != actual else {
- return []
+ return nil
}
- let reason = "Closure end should have the same indentation as the line that started it. " +
- "Expected \(expected), got \(actual)."
- return [
- StyleViolation(ruleDescription: type(of: self).description,
- severity: configuration.severity,
- location: Location(file: file, byteOffset: endOffset),
- reason: reason)
- ]
+ var expectedRange = range
+ expectedRange.length = expected
+
+ var actualRange = file.lines[endLine - 1].range
+ actualRange.length = actual
+
+ return Violation(location: Location(file: file, byteOffset: endOffset),
+ indentationRanges: (expected: expectedRange, actual: actualRange),
+ endOffset: endOffset,
+ range: NSRange(location: offset, length: length))
}
- func validateArguments(in file: File,
- dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
+ private func validateArguments(in file: File,
+ dictionary: [String: SourceKitRepresentable]) -> [Violation] {
guard isFirstArgumentOnNewline(dictionary, file: file) else {
return []
}
@@ -150,7 +214,7 @@ public struct ClosureEndIndentationRule: ASTRule, OptInRule, ConfigurationProvid
closureArguments.removeLast()
}
- let argumentViolations = closureArguments.flatMap { dictionary in
+ let argumentViolations = closureArguments.compactMap { dictionary in
return validateClosureArgument(in: file, dictionary: dictionary)
}
@@ -158,7 +222,7 @@ public struct ClosureEndIndentationRule: ASTRule, OptInRule, ConfigurationProvid
}
private func validateClosureArgument(in file: File,
- dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
+ dictionary: [String: SourceKitRepresentable]) -> Violation? {
let contents = file.contents.bridge()
guard let offset = dictionary.offset,
let length = dictionary.length,
@@ -175,7 +239,7 @@ public struct ClosureEndIndentationRule: ASTRule, OptInRule, ConfigurationProvid
let (bodyOffsetLine, _) = contents.lineAndCharacter(forByteOffset: nameEndPosition),
startLine != endLine, bodyOffsetLine != endLine,
!isSingleLineClosure(dictionary: dictionary, endPosition: endOffset, file: file) else {
- return []
+ return nil
}
let range = file.lines[startLine - 1].range
@@ -184,17 +248,19 @@ public struct ClosureEndIndentationRule: ASTRule, OptInRule, ConfigurationProvid
guard let match = regex.firstMatch(in: file.contents, options: [], range: range)?.range,
case let expected = match.location - range.location,
expected != actual else {
- return []
+ return nil
}
- let reason = "Closure end should have the same indentation as the line that started it. " +
- "Expected \(expected), got \(actual)."
- return [
- StyleViolation(ruleDescription: type(of: self).description,
- severity: configuration.severity,
- location: Location(file: file, byteOffset: endOffset),
- reason: reason)
- ]
+ var expectedRange = range
+ expectedRange.length = expected
+
+ var actualRange = file.lines[endLine - 1].range
+ actualRange.length = actual
+
+ return Violation(location: Location(file: file, byteOffset: endOffset),
+ indentationRanges: (expected: expectedRange, actual: actualRange),
+ endOffset: endOffset,
+ range: NSRange(location: offset, length: length))
}
private func startOffset(forDictionary dictionary: [String: SourceKitRepresentable], file: File) -> Int? {
diff --git a/Source/SwiftLintFramework/Rules/DiscouragedOptionalCollectionRuleExamples.swift b/Source/SwiftLintFramework/Rules/DiscouragedOptionalCollectionExamples.swift
similarity index 100%
rename from Source/SwiftLintFramework/Rules/DiscouragedOptionalCollectionRuleExamples.swift
rename to Source/SwiftLintFramework/Rules/DiscouragedOptionalCollectionExamples.swift
diff --git a/Source/SwiftLintFramework/Rules/DiscouragedOptionalCollectionRule.swift b/Source/SwiftLintFramework/Rules/DiscouragedOptionalCollectionRule.swift
index 52bed16f7b7..f8849a5258c 100644
--- a/Source/SwiftLintFramework/Rules/DiscouragedOptionalCollectionRule.swift
+++ b/Source/SwiftLintFramework/Rules/DiscouragedOptionalCollectionRule.swift
@@ -99,7 +99,7 @@ private extension String {
let finalIndex = index(range.upperBound, offsetBy: 1, limitedBy: endIndex),
self[range.upperBound] == "?" else { return nil }
- return Range(range.lowerBound..").compactMap { range -> Range? in
@@ -110,7 +110,7 @@ private extension String {
self[initialIndex.. [StyleViolation] {
+ return testClasses(in: file).flatMap { violations(in: file, for: $0) }
+ }
+
+ // MARK: - Private
+
+ private func testClasses(in file: File) -> [[String: SourceKitRepresentable]] {
+ return file.structure.dictionary.substructure.filter { dictionary in
+ guard
+ let kind = dictionary.kind,
+ SwiftDeclarationKind(rawValue: kind) == .class else { return false }
+ return dictionary.inheritedTypes.contains("XCTestCase")
+ }
+ }
+
+ private func violations(in file: File,
+ for dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
+ return dictionary.substructure.compactMap { subDictionary -> StyleViolation? in
+ guard
+ let kind = subDictionary.kind.flatMap(SwiftDeclarationKind.init),
+ SwiftDeclarationKind.functionKinds.contains(kind),
+ let name = subDictionary.name, isXCTestMethod(name),
+ let offset = subDictionary.offset,
+ subDictionary.enclosedVarParameters.isEmpty,
+ subDictionary.substructure.isEmpty else { return nil }
+
+ return StyleViolation(ruleDescription: type(of: self).description,
+ severity: configuration.severity,
+ location: Location(file: file, byteOffset: offset))
+ }
+ }
+
+ private func isXCTestMethod(_ method: String) -> Bool {
+ return method.hasPrefix("test") || method == "setUp()" || method == "tearDown()"
+ }
+}
diff --git a/Source/SwiftLintFramework/Rules/EmptyXCTestMethodRuleExamples.swift b/Source/SwiftLintFramework/Rules/EmptyXCTestMethodRuleExamples.swift
new file mode 100644
index 00000000000..61f756af7b2
--- /dev/null
+++ b/Source/SwiftLintFramework/Rules/EmptyXCTestMethodRuleExamples.swift
@@ -0,0 +1,163 @@
+import Foundation
+
+internal struct EmptyXCTestMethodRuleExamples {
+
+ static let nonTriggeringExamples = [
+
+ // Valid XCTestCase class
+
+ """
+ class TotoTests: XCTestCase {
+ var foobar: Foobar?
+
+ override func setUp() {
+ super.setUp()
+ foobar = Foobar()
+ }
+
+ override func tearDown() {
+ foobar = nil
+ super.tearDown()
+ }
+
+ func testFoo() {
+ XCTAssertTrue(foobar?.foo)
+ }
+
+ func testBar() {
+ // comment...
+
+ XCTAssertFalse(foobar?.bar)
+
+ // comment...
+ }
+ }
+ """,
+
+ // Not an XCTestCase class
+
+ """
+ class Foobar {
+ func setUp() {}
+
+ func tearDown() {}
+
+ func testFoo() {}
+ }
+ """,
+
+ // Methods with parameters
+
+ """
+ class TotoTests: XCTestCase {
+ func setUp(with object: Foobar) {}
+
+ func tearDown(object: Foobar) {}
+
+ func testFoo(_ foo: Foobar) {}
+
+ func testBar(bar: (String) -> Int) {}
+ }
+ """,
+
+ // Asserts in one line
+
+ """
+ class TotoTests: XCTestCase {
+ func testFoo() { XCTAssertTrue(foobar?.foo) }
+
+ func testBar() { XCTAssertFalse(foobar?.bar) }
+ }
+ """
+ ]
+
+ static let triggeringExamples = [
+
+ // XCTestCase class with empty methods
+
+ """
+ class TotoTests: XCTestCase {
+ override ↓func setUp() {
+ }
+
+ override ↓func tearDown() {
+
+ }
+
+ ↓func testFoo() {
+
+
+ }
+
+ ↓func testBar() {
+
+
+
+ }
+
+ func helperFunction() {
+ }
+ }
+ """,
+
+ """
+ class TotoTests: XCTestCase {
+ override ↓func setUp() {}
+
+ override ↓func tearDown() {}
+
+ ↓func testFoo() {}
+
+ func helperFunction() {}
+ }
+ """,
+
+ // XCTestCase class with comments (and blank lines)
+
+ """
+ class TotoTests: XCTestCase {
+ override ↓func setUp() {
+ // comment...
+ }
+
+ override ↓func tearDown() {
+ // comment...
+ // comment...
+ }
+
+ ↓func testFoo() {
+ // comment...
+
+ // comment...
+
+ // comment...
+ }
+
+ ↓func testBar() {
+ /*
+ * comment...
+ *
+ * comment...
+ *
+ * comment...
+ */
+ }
+
+ func helperFunction() {
+ }
+ }
+ """,
+
+ // Two XCTestCase classes on the same file
+
+ """
+ class FooTests: XCTestCase {
+ override ↓func setUp() {}
+ }
+
+ class BarTests: XCTestCase {
+ ↓func testFoo() {}
+ }
+ """
+ ]
+}
diff --git a/Source/SwiftLintFramework/Rules/FileNameRule.swift b/Source/SwiftLintFramework/Rules/FileNameRule.swift
new file mode 100644
index 00000000000..6b61804427d
--- /dev/null
+++ b/Source/SwiftLintFramework/Rules/FileNameRule.swift
@@ -0,0 +1,47 @@
+import Foundation
+import SourceKittenFramework
+
+private let typeAndExtensionKinds = SwiftDeclarationKind.typeKinds + [.extension, .protocol]
+
+private extension Dictionary where Key: ExpressibleByStringLiteral {
+ func recursiveDeclaredTypeNames() -> [String] {
+ let subNames = substructure.flatMap { $0.recursiveDeclaredTypeNames() }
+ if let kind = kind.flatMap(SwiftDeclarationKind.init),
+ typeAndExtensionKinds.contains(kind), let name = name {
+ return [name] + subNames
+ }
+ return subNames
+ }
+}
+
+public struct FileNameRule: ConfigurationProviderRule, OptInRule {
+ public var configuration = FileNameConfiguration(severity: .warning, excluded: ["main.swift", "LinuxMain.swift"])
+
+ public init() {}
+
+ public static let description = RuleDescription(
+ identifier: "file_name",
+ name: "File Name",
+ description: "File name should match a type or extension declared in the file (if any).",
+ kind: .idiomatic
+ )
+
+ public func validate(file: File) -> [StyleViolation] {
+ guard let filePath = file.path,
+ case let fileName = filePath.bridge().lastPathComponent,
+ !configuration.excluded.contains(fileName) else {
+ return []
+ }
+
+ let typeInFileName = fileName.components(separatedBy: CharacterSet(charactersIn: "+.")).first ?? fileName
+
+ let allDeclaredTypeNames = file.structure.dictionary.recursiveDeclaredTypeNames()
+ guard !allDeclaredTypeNames.isEmpty, !allDeclaredTypeNames.contains(typeInFileName) else {
+ return []
+ }
+
+ return [StyleViolation(ruleDescription: type(of: self).description,
+ severity: configuration.severity.severity,
+ location: Location(file: filePath, line: 1))]
+ }
+}
diff --git a/Source/SwiftLintFramework/Rules/FunctionDefaultParameterAtEndRule.swift b/Source/SwiftLintFramework/Rules/FunctionDefaultParameterAtEndRule.swift
new file mode 100644
index 00000000000..094831d84cc
--- /dev/null
+++ b/Source/SwiftLintFramework/Rules/FunctionDefaultParameterAtEndRule.swift
@@ -0,0 +1,95 @@
+import SourceKittenFramework
+
+public struct FunctionDefaultParameterAtEndRule: ASTRule, ConfigurationProviderRule, OptInRule {
+ public var configuration = SeverityConfiguration(.warning)
+
+ public init() {}
+
+ public static let description = RuleDescription(
+ identifier: "function_default_parameter_at_end",
+ name: "Function Default Parameter at End",
+ description: "Prefer to locate parameters with defaults toward the end of the parameter list.",
+ kind: .idiomatic,
+ nonTriggeringExamples: [
+ "func foo(baz: String, bar: Int = 0) {}",
+ "func foo(x: String, y: Int = 0, z: CGFloat = 0) {}",
+ "func foo(bar: String, baz: Int = 0, z: () -> Void) {}",
+ "func foo(bar: String, z: () -> Void, baz: Int = 0) {}",
+ "func foo(bar: Int = 0) {}",
+ "func foo() {}",
+ """
+ class A: B {
+ override func foo(bar: Int = 0, baz: String) {}
+ """,
+ "func foo(bar: Int = 0, completion: @escaping CompletionHandler) {}",
+ """
+ func foo(a: Int, b: CGFloat = 0) {
+ let block = { (error: Error?) in }
+ }
+ """
+ ],
+ triggeringExamples: [
+ "↓func foo(bar: Int = 0, baz: String) {}"
+ ]
+ )
+
+ public func validate(file: File, kind: SwiftDeclarationKind,
+ dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
+ guard SwiftDeclarationKind.functionKinds.contains(kind),
+ let offset = dictionary.offset,
+ let bodyOffset = dictionary.bodyOffset,
+ !dictionary.enclosedSwiftAttributes.contains(.override) else {
+ return []
+ }
+
+ let isNotClosure = { !self.isClosureParameter(dictionary: $0) }
+ let params = dictionary.enclosedVarParameters.filter(isNotClosure).filter { param in
+ guard let paramOffset = param.offset else {
+ return false
+ }
+
+ return paramOffset < bodyOffset
+ }
+
+ guard !params.isEmpty else {
+ return []
+ }
+
+ let containsDefaultValue = { self.isDefaultParameter(file: file, dictionary: $0) }
+ let defaultParams = params.filter(containsDefaultValue)
+ guard !defaultParams.isEmpty else {
+ return []
+ }
+
+ let lastParameters = params.suffix(defaultParams.count)
+ let lastParametersWithDefaultValue = lastParameters.filter(containsDefaultValue)
+
+ guard lastParameters.count != lastParametersWithDefaultValue.count else {
+ return []
+ }
+
+ return [
+ StyleViolation(ruleDescription: type(of: self).description,
+ severity: configuration.severity,
+ location: Location(file: file, byteOffset: offset))
+ ]
+ }
+
+ private func isClosureParameter(dictionary: [String: SourceKitRepresentable]) -> Bool {
+ guard let typeName = dictionary.typeName else {
+ return false
+ }
+
+ return typeName.contains("->") || typeName.contains("@escaping")
+ }
+
+ private func isDefaultParameter(file: File, dictionary: [String: SourceKitRepresentable]) -> Bool {
+ let contents = file.contents.bridge()
+ guard let offset = dictionary.offset, let length = dictionary.length,
+ let range = contents.byteRangeToNSRange(start: offset, length: length) else {
+ return false
+ }
+
+ return regex("=").firstMatch(in: file.contents, options: [], range: range) != nil
+ }
+}
diff --git a/Source/SwiftLintFramework/Rules/FunctionParameterCountRule.swift b/Source/SwiftLintFramework/Rules/FunctionParameterCountRule.swift
index 2f7ff556283..f23648b74c7 100644
--- a/Source/SwiftLintFramework/Rules/FunctionParameterCountRule.swift
+++ b/Source/SwiftLintFramework/Rules/FunctionParameterCountRule.swift
@@ -2,7 +2,7 @@ import Foundation
import SourceKittenFramework
public struct FunctionParameterCountRule: ASTRule, ConfigurationProviderRule {
- public var configuration = SeverityLevelsConfiguration(warning: 5, error: 8)
+ public var configuration = FunctionParameterCountConfiguration(warning: 5, error: 8)
public init() {}
@@ -51,7 +51,7 @@ public struct FunctionParameterCountRule: ASTRule, ConfigurationProviderRule {
return []
}
- let minThreshold = configuration.params.map({ $0.value }).min(by: <)
+ let minThreshold = configuration.severityConfiguration.params.map({ $0.value }).min(by: <)
let allParameterCount = allFunctionParameterCount(structure: dictionary.substructure, offset: nameOffset,
length: length)
@@ -59,12 +59,15 @@ public struct FunctionParameterCountRule: ASTRule, ConfigurationProviderRule {
return []
}
- let parameterCount = allParameterCount -
- defaultFunctionParameterCount(file: file, byteOffset: nameOffset, byteLength: length)
+ var parameterCount = allParameterCount
- for parameter in configuration.params where parameterCount > parameter.value {
+ if configuration.ignoresDefaultParameters {
+ parameterCount -= defaultFunctionParameterCount(file: file, byteOffset: nameOffset, byteLength: length)
+ }
+
+ for parameter in configuration.severityConfiguration.params where parameterCount > parameter.value {
let offset = dictionary.offset ?? 0
- let reason = "Function should have \(configuration.warning) parameters or less: " +
+ let reason = "Function should have \(configuration.severityConfiguration.warning) parameters or less: " +
"it currently has \(parameterCount)"
return [StyleViolation(ruleDescription: type(of: self).description,
severity: parameter.severity,
diff --git a/Source/SwiftLintFramework/Rules/ImplicitReturnRule.swift b/Source/SwiftLintFramework/Rules/ImplicitReturnRule.swift
index d32213dcbad..f12bcb3213c 100644
--- a/Source/SwiftLintFramework/Rules/ImplicitReturnRule.swift
+++ b/Source/SwiftLintFramework/Rules/ImplicitReturnRule.swift
@@ -21,11 +21,28 @@ public struct ImplicitReturnRule: ConfigurationProviderRule, CorrectableRule, Op
],
triggeringExamples: [
"foo.map { value in\n ↓return value + 1\n}",
- "foo.map {\n ↓return $0 + 1\n}"
+ "foo.map {\n ↓return $0 + 1\n}",
+ "foo.map({ ↓return $0 + 1})",
+ """
+ [1, 2].first(where: {
+ ↓return true
+ })
+ """
],
corrections: [
"foo.map { value in\n ↓return value + 1\n}": "foo.map { value in\n value + 1\n}",
- "foo.map {\n ↓return $0 + 1\n}": "foo.map {\n $0 + 1\n}"
+ "foo.map {\n ↓return $0 + 1\n}": "foo.map {\n $0 + 1\n}",
+ "foo.map({ ↓return $0 + 1})": "foo.map({ $0 + 1})",
+ """
+ [1, 2].first(where: {
+ ↓return true
+ })
+ """:
+ """
+ [1, 2].first(where: {
+ true
+ })
+ """
]
)
@@ -66,8 +83,9 @@ public struct ImplicitReturnRule: ConfigurationProviderRule, CorrectableRule, Op
guard kinds == [.keyword, .keyword] || kinds == [.keyword],
let byteRange = contents.NSRangeToByteRange(start: range.location,
length: range.length),
- let outerKind = file.structure.kinds(forByteOffset: byteRange.location).last,
- SwiftExpressionKind(rawValue: outerKind.kind) == .call else {
+ let outerKindString = file.structure.kinds(forByteOffset: byteRange.location).last?.kind,
+ let outerKind = SwiftExpressionKind(rawValue: outerKindString),
+ [.call, .argument].contains(outerKind) else {
return nil
}
diff --git a/Source/SwiftLintFramework/Rules/JoinedDefaultRule.swift b/Source/SwiftLintFramework/Rules/JoinedDefaultParameterRule.swift
similarity index 100%
rename from Source/SwiftLintFramework/Rules/JoinedDefaultRule.swift
rename to Source/SwiftLintFramework/Rules/JoinedDefaultParameterRule.swift
diff --git a/Source/SwiftLintFramework/Rules/LiteralExpressionEndIdentationRule.swift b/Source/SwiftLintFramework/Rules/LiteralExpressionEndIdentationRule.swift
index d13dbaa33aa..f00615010a6 100644
--- a/Source/SwiftLintFramework/Rules/LiteralExpressionEndIdentationRule.swift
+++ b/Source/SwiftLintFramework/Rules/LiteralExpressionEndIdentationRule.swift
@@ -1,7 +1,7 @@
import Foundation
import SourceKittenFramework
-public struct LiteralExpressionEndIdentationRule: ASTRule, ConfigurationProviderRule, OptInRule {
+public struct LiteralExpressionEndIdentationRule: Rule, ConfigurationProviderRule, OptInRule {
public var configuration = SeverityConfiguration(.warning)
public init() {}
@@ -48,17 +48,162 @@ public struct LiteralExpressionEndIdentationRule: ASTRule, ConfigurationProvider
"let x = [\n" +
" key: value\n" +
" ↓]"
+ ],
+ corrections: [
+ "let x = [\n" +
+ " key: value\n" +
+ "↓ ]":
+ "let x = [\n" +
+ " key: value\n" +
+ "]",
+ " let x = [\n" +
+ " 1,\n" +
+ " 2\n" +
+ "↓]":
+ " let x = [\n" +
+ " 1,\n" +
+ " 2\n" +
+ " ]",
+ "let x = [\n" +
+ " 1,\n" +
+ " 2\n" +
+ "↓ ]":
+ "let x = [\n" +
+ " 1,\n" +
+ " 2\n" +
+ "]",
+ "let x = [\n" +
+ " 1,\n" +
+ " 2\n" +
+ "↓ ] + [\n" +
+ " 3,\n" +
+ " 4\n" +
+ "↓ ]":
+ "let x = [\n" +
+ " 1,\n" +
+ " 2\n" +
+ "] + [\n" +
+ " 3,\n" +
+ " 4\n" +
+ "]"
]
)
- private static let notWhitespace = regex("[^\\s]")
+ public func validate(file: File) -> [StyleViolation] {
+ return violations(in: file).map { violation in
+ return styleViolation(for: violation, in: file)
+ }
+ }
- public func validate(file: File, kind: SwiftExpressionKind,
- dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
- guard kind == .dictionary || kind == .array else {
+ private func styleViolation(for violation: Violation, in file: File) -> StyleViolation {
+ let reason = "\(LiteralExpressionEndIdentationRule.description.description) " +
+ "Expected \(violation.indentationRanges.expected.length), " +
+ "got \(violation.indentationRanges.actual.length)."
+
+ return StyleViolation(ruleDescription: type(of: self).description,
+ severity: configuration.severity,
+ location: Location(file: file, byteOffset: violation.endOffset),
+ reason: reason)
+ }
+
+ fileprivate static let notWhitespace = regex("[^\\s]")
+
+}
+
+extension LiteralExpressionEndIdentationRule: CorrectableRule {
+ public func correct(file: File) -> [Correction] {
+ let allViolations = violations(in: file).reversed().filter {
+ !file.ruleEnabled(violatingRanges: [$0.range], for: self).isEmpty
+ }
+
+ guard !allViolations.isEmpty else {
return []
}
+ var correctedContents = file.contents
+ var correctedLocations: [Int] = []
+
+ let actualLookup = actualViolationLookup(for: allViolations)
+
+ for violation in allViolations {
+ let expected = actualLookup(violation).indentationRanges.expected
+ let actual = violation.indentationRanges.actual
+ if correct(contents: &correctedContents, expected: expected, actual: actual) {
+ correctedLocations.append(actual.location)
+ }
+ }
+
+ var corrections = correctedLocations.map {
+ return Correction(ruleDescription: type(of: self).description,
+ location: Location(file: file, characterOffset: $0))
+ }
+
+ file.write(correctedContents)
+
+ // Re-correct to catch cascading indentation from the first round.
+ corrections += correct(file: file)
+
+ return corrections
+ }
+
+ private func correct(contents: inout String, expected: NSRange, actual: NSRange) -> Bool {
+ guard let actualIndices = contents.nsrangeToIndexRange(actual) else {
+ return false
+ }
+
+ let correction = contents.substring(from: expected.location, length: expected.length)
+ contents = contents.replacingCharacters(in: actualIndices, with: correction)
+
+ return true
+ }
+
+ private func actualViolationLookup(for violations: [Violation]) -> (Violation) -> Violation {
+ let lookup = violations.reduce(into: [NSRange: Violation](), { result, violation in
+ result[violation.indentationRanges.actual] = violation
+ })
+
+ func actualViolation(for violation: Violation) -> Violation {
+ guard let actual = lookup[violation.indentationRanges.expected] else { return violation }
+ return actualViolation(for: actual)
+ }
+
+ return actualViolation
+ }
+}
+
+extension LiteralExpressionEndIdentationRule {
+ fileprivate struct Violation {
+ var location: Location
+ var indentationRanges: (expected: NSRange, actual: NSRange)
+ var endOffset: Int
+ var range: NSRange
+ }
+
+ fileprivate func violations(in file: File) -> [Violation] {
+ return violations(in: file, dictionary: file.structure.dictionary)
+ }
+
+ private func violations(in file: File,
+ dictionary: [String: SourceKitRepresentable]) -> [Violation] {
+ return dictionary.substructure.flatMap { subDict -> [Violation] in
+ var subViolations = violations(in: file, dictionary: subDict)
+
+ if let kindString = subDict.kind,
+ let kind = SwiftExpressionKind(rawValue: kindString),
+ let violation = violation(in: file, of: kind, dictionary: subDict) {
+ subViolations.append(violation)
+ }
+
+ return subViolations
+ }
+ }
+
+ private func violation(in file: File, of kind: SwiftExpressionKind,
+ dictionary: [String: SourceKitRepresentable]) -> Violation? {
+ guard kind == .dictionary || kind == .array else {
+ return nil
+ }
+
let elements = dictionary.elements.filter { $0.kind == "source.lang.swift.structure.elem.expr" }
let contents = file.contents.bridge()
@@ -74,7 +219,7 @@ public struct LiteralExpressionEndIdentationRule: ASTRule, ConfigurationProvider
case let endOffset = offset + length - 1,
let (endLine, endPosition) = contents.lineAndCharacter(forByteOffset: endOffset),
lastParamLine != endLine else {
- return []
+ return nil
}
let range = file.lines[startLine - 1].range
@@ -83,16 +228,18 @@ public struct LiteralExpressionEndIdentationRule: ASTRule, ConfigurationProvider
guard let match = regex.firstMatch(in: file.contents, options: [], range: range)?.range,
case let expected = match.location - range.location,
expected != actual else {
- return []
+ return nil
}
- let reason = "\(LiteralExpressionEndIdentationRule.description.description) " +
- "Expected \(expected), got \(actual)."
- return [
- StyleViolation(ruleDescription: type(of: self).description,
- severity: configuration.severity,
- location: Location(file: file, byteOffset: endOffset),
- reason: reason)
- ]
+ var expectedRange = range
+ expectedRange.length = expected
+
+ var actualRange = file.lines[endLine - 1].range
+ actualRange.length = actual
+
+ return Violation(location: Location(file: file, byteOffset: endOffset),
+ indentationRanges: (expected: expectedRange, actual: actualRange),
+ endOffset: endOffset,
+ range: NSRange(location: offset, length: length))
}
}
diff --git a/Source/SwiftLintFramework/Rules/LowerACLThanBodyRule.swift b/Source/SwiftLintFramework/Rules/LowerACLThanParentRule.swift
similarity index 100%
rename from Source/SwiftLintFramework/Rules/LowerACLThanBodyRule.swift
rename to Source/SwiftLintFramework/Rules/LowerACLThanParentRule.swift
diff --git a/Source/SwiftLintFramework/Rules/MarkRule.swift b/Source/SwiftLintFramework/Rules/MarkRule.swift
index 3f46704befb..085550b16d8 100644
--- a/Source/SwiftLintFramework/Rules/MarkRule.swift
+++ b/Source/SwiftLintFramework/Rules/MarkRule.swift
@@ -44,6 +44,10 @@ public struct MarkRule: CorrectableRule, ConfigurationProviderRule {
"↓// MARK bad",
"↓//MARK bad",
"↓// MARK - bad",
+ "↓//MARK : bad",
+ "↓// MARKL:",
+ "↓// MARKR ",
+ "↓// MARKK -",
issue1029Example
],
corrections: [
@@ -54,6 +58,15 @@ public struct MarkRule: CorrectableRule, ConfigurationProviderRule {
"↓//MARK: - comment": "// MARK: - comment",
"↓// MARK:- comment": "// MARK: - comment",
"↓// MARK: -comment": "// MARK: - comment",
+ "↓// MARK: - comment": "// MARK: - comment",
+ "↓// Mark: comment": "// MARK: comment",
+ "↓// Mark: - comment": "// MARK: - comment",
+ "↓// MARK - comment": "// MARK: - comment",
+ "↓// MARK : comment": "// MARK: comment",
+ "↓// MARKL:": "// MARK:",
+ "↓// MARKL: -": "// MARK: -",
+ "↓// MARKK ": "// MARK: ",
+ "↓// MARKK -": "// MARK: -",
issue1029Example: issue1029Correction
]
)
@@ -73,6 +86,10 @@ public struct MarkRule: CorrectableRule, ConfigurationProviderRule {
private let invalidLowercasePattern = "(?:// ?[Mm]ark:)"
private let missingColonPattern = "(?:// ?MARK[^:])"
+ // The below patterns more specifically describe some of the above pattern's failure cases for correction.
+ private let oneOrMoreSpacesBeforeColonPattern = "(?:// ?MARK +:)"
+ private let nonWhitespaceBeforeColonPattern = "(?:// ?MARK\\S+:)"
+ private let nonWhitespaceNorColonBeforeSpacesPattern = "(?:// ?MARK[^\\s:]* +)"
private var pattern: String {
return [
@@ -117,6 +134,25 @@ public struct MarkRule: CorrectableRule, ConfigurationProviderRule {
replaceString: "// MARK: - ",
keepLastChar: true))
+ result.append(contentsOf: correct(file: file,
+ pattern: oneOrMoreSpacesBeforeColonPattern,
+ replaceString: "// MARK:",
+ keepLastChar: false))
+
+ result.append(contentsOf: correct(file: file,
+ pattern: nonWhitespaceBeforeColonPattern,
+ replaceString: "// MARK:",
+ keepLastChar: false))
+
+ result.append(contentsOf: correct(file: file,
+ pattern: nonWhitespaceNorColonBeforeSpacesPattern,
+ replaceString: "// MARK: ",
+ keepLastChar: false))
+
+ result.append(contentsOf: correct(file: file,
+ pattern: invalidLowercasePattern,
+ replaceString: "// MARK:"))
+
return result.unique
}
diff --git a/Source/SwiftLintFramework/Rules/OpeningBraceRule.swift b/Source/SwiftLintFramework/Rules/OpeningBraceRule.swift
index 8640583c7bf..acd84d62d9d 100644
--- a/Source/SwiftLintFramework/Rules/OpeningBraceRule.swift
+++ b/Source/SwiftLintFramework/Rules/OpeningBraceRule.swift
@@ -101,11 +101,8 @@ public struct OpeningBraceRule: CorrectableRule, ConfigurationProviderRule {
guard let indexRange = contents.nsrangeToIndexRange(violatingRange) else {
return contents
}
-#if swift(>=4.0)
+
let capturedString = String(contents[indexRange])
-#else
- let capturedString = contents[indexRange]
-#endif
var adjustedRange = violatingRange
var correctString = " {"
diff --git a/Source/SwiftLintFramework/Rules/OperatorUsageWhitespaceRule.swift b/Source/SwiftLintFramework/Rules/OperatorUsageWhitespaceRule.swift
index 411d227db47..6478e0ffa8c 100644
--- a/Source/SwiftLintFramework/Rules/OperatorUsageWhitespaceRule.swift
+++ b/Source/SwiftLintFramework/Rules/OperatorUsageWhitespaceRule.swift
@@ -19,6 +19,7 @@ public struct OperatorUsageWhitespaceRule: OptInRule, CorrectableRule, Configura
"let foo = !false\n",
"let foo: Int?\n",
"let foo: Array\n",
+ "let model = CustomView, NSAttributedString>()\n",
"let foo: [String]\n",
"let foo = 1 + \n 2\n",
"let range = 1...3\n",
@@ -28,7 +29,10 @@ public struct OperatorUsageWhitespaceRule: OptInRule, CorrectableRule, Configura
"array.removeAtIndex(-200)\n",
"let name = \"image-1\"\n",
"button.setImage(#imageLiteral(resourceName: \"image-1\"), for: .normal)\n",
- "let doubleValue = -9e-11\n"
+ "let doubleValue = -9e-11\n",
+ "let foo = GenericType<(UIViewController) -> Void>()\n",
+ "let foo = Foo, Baz>()\n",
+ "let foo = SignalProducer, Error>([ self.signal, next ]).flatten(.concat)\n"
],
triggeringExamples: [
"let foo = 1↓+2\n",
@@ -96,7 +100,7 @@ public struct OperatorUsageWhitespaceRule: OptInRule, CorrectableRule, Configura
}
let pattern = "(?:\(patterns.joined(separator: "|")))"
- let genericPattern = "<(?:\(oneSpace)|\\S)+?>" // not using dot to avoid matching new line
+ let genericPattern = "<(?:\(oneSpace)|\\S)*>" // not using dot to avoid matching new line
let validRangePattern = leadingVariableOrNumber + zeroSpaces + rangePattern +
zeroSpaces + trailingVariableOrNumber
let excludingPattern = "(?:\(genericPattern)|\(validRangePattern))"
diff --git a/Source/SwiftLintFramework/Rules/ProhibitedSuperRule.swift b/Source/SwiftLintFramework/Rules/ProhibitedSuperRule.swift
index f0c3c60cf7a..c7593786507 100644
--- a/Source/SwiftLintFramework/Rules/ProhibitedSuperRule.swift
+++ b/Source/SwiftLintFramework/Rules/ProhibitedSuperRule.swift
@@ -11,43 +11,64 @@ public struct ProhibitedSuperRule: ConfigurationProviderRule, ASTRule, OptInRule
description: "Some methods should not call super",
kind: .lint,
nonTriggeringExamples: [
- "class VC: UIViewController {\n" +
- "\toverride func loadView() {\n" +
- "\t}\n" +
- "}\n",
- "class NSView {\n" +
- "\tfunc updateLayer() {\n" +
- "\t\tself.method1()" +
- "\t}\n" +
- "}\n"
+ """
+ class VC: UIViewController {
+ override func loadView() {
+ }
+ }
+ """,
+ """
+ class NSView {
+ func updateLayer() {
+ self.method1()
+ }
+ }
+ """,
+ """
+ public class FileProviderExtension: NSFileProviderExtension {
+ override func providePlaceholder(at url: URL, completionHandler: @escaping (Error?) -> Void) {
+ guard let identifier = persistentIdentifierForItem(at: url) else {
+ completionHandler(NSFileProviderError(.noSuchItem))
+ return
+ }
+ }
+ }
+ """
],
triggeringExamples: [
- "class VC: UIViewController {\n" +
- "\toverride func loadView() {↓\n" +
- "\t\tsuper.loadView()\n" +
- "\t}\n" +
- "}\n",
- "class VC: NSFileProviderExtension {\n" +
- "\toverride func providePlaceholder(at url: URL," +
- "completionHandler: @escaping (Error?) -> Void) {↓\n" +
- "\t\tself.method1()\n" +
- "\t\tsuper.providePlaceholder(at:url, completionHandler: completionHandler)\n" +
- "\t}\n" +
- "}\n",
- "class VC: NSView {\n" +
- "\toverride func updateLayer() {↓\n" +
- "\t\tself.method1()\n" +
- "\t\tsuper.updateLayer()\n" +
- "\t\tself.method2()\n" +
- "\t}\n" +
- "}\n",
- "class VC: NSView {\n" +
- "\toverride func updateLayer() {↓\n" +
- "\t\tdefer {\n" +
- "\t\t\tsuper.updateLayer()\n" +
- "\t\t}\n" +
- "\t}\n" +
- "}\n"
+ """
+ class VC: UIViewController {
+ override func loadView() {↓
+ super.loadView()
+ }
+ }
+ """,
+ """
+ class VC: NSFileProviderExtension {
+ override func providePlaceholder(at url: URL, completionHandler: @escaping (Error?) -> Void) {↓
+ self.method1()
+ super.providePlaceholder(at:url, completionHandler: completionHandler)
+ }
+ }
+ """,
+ """
+ class VC: NSView {
+ override func updateLayer() {↓
+ self.method1()
+ super.updateLayer()
+ self.method2()
+ }
+ }
+ """,
+ """
+ class VC: NSView {
+ override func updateLayer() {↓
+ defer {
+ super.updateLayer()
+ }
+ }
+ }
+ """
]
)
diff --git a/Source/SwiftLintFramework/Rules/RuleConfigurations/ClosureEndIndentationRuleExamples.swift b/Source/SwiftLintFramework/Rules/RuleConfigurations/ClosureEndIndentationRuleExamples.swift
new file mode 100644
index 00000000000..57191afd48e
--- /dev/null
+++ b/Source/SwiftLintFramework/Rules/RuleConfigurations/ClosureEndIndentationRuleExamples.swift
@@ -0,0 +1,184 @@
+internal struct ClosureEndIndentationRuleExamples {
+
+ static let nonTriggeringExamples = [
+ "SignalProducer(values: [1, 2, 3])\n" +
+ " .startWithNext { number in\n" +
+ " print(number)\n" +
+ " }\n",
+ "[1, 2].map { $0 + 1 }\n",
+ "return match(pattern: pattern, with: [.comment]).flatMap { range in\n" +
+ " return Command(string: contents, range: range)\n" +
+ "}.flatMap { command in\n" +
+ " return command.expand()\n" +
+ "}\n",
+ "foo(foo: bar,\n" +
+ " options: baz) { _ in }\n",
+ "someReallyLongProperty.chainingWithAnotherProperty\n" +
+ " .foo { _ in }",
+ "foo(abc, 123)\n" +
+ "{ _ in }\n",
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x)\n" +
+ " },\n" +
+ " anotherClosure: { y in\n" +
+ " print(y)\n" +
+ " })",
+ "function(parameter: param,\n" +
+ " closure: { x in\n" +
+ " print(x)\n" +
+ "})",
+ "function(parameter: param, closure: { x in\n" +
+ " print(x)\n" +
+ " },\n" +
+ " anotherClosure: { y in\n" +
+ " print(y)\n" +
+ " })"
+ ]
+
+ static let triggeringExamples = [
+ "SignalProducer(values: [1, 2, 3])\n" +
+ " .startWithNext { number in\n" +
+ " print(number)\n" +
+ "↓}\n",
+ "return match(pattern: pattern, with: [.comment]).flatMap { range in\n" +
+ " return Command(string: contents, range: range)\n" +
+ " ↓}.flatMap { command in\n" +
+ " return command.expand()\n" +
+ "↓}\n",
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x)\n" +
+ "↓},\n" +
+ " anotherClosure: { y in\n" +
+ " print(y)\n" +
+ "↓})"
+ ]
+
+ static let corrections = [
+ "SignalProducer(values: [1, 2, 3])\n" +
+ " .startWithNext { number in\n" +
+ " print(number)\n" +
+ "↓}\n":
+ "SignalProducer(values: [1, 2, 3])\n" +
+ " .startWithNext { number in\n" +
+ " print(number)\n" +
+ " }\n",
+ "SignalProducer(values: [1, 2, 3])\n" +
+ " .startWithNext { number in\n" +
+ " print(number)\n" +
+ "↓}.another { x in\n" +
+ " print(x)\n" +
+ "↓}.yetAnother { y in\n" +
+ " print(y)\n" +
+ "↓})":
+ "SignalProducer(values: [1, 2, 3])\n" +
+ " .startWithNext { number in\n" +
+ " print(number)\n" +
+ " }.another { x in\n" +
+ " print(x)\n" +
+ " }.yetAnother { y in\n" +
+ " print(y)\n" +
+ " })",
+ "return match(pattern: pattern, with: [.comment]).flatMap { range in\n" +
+ " return Command(string: contents, range: range)\n" +
+ "↓ }.flatMap { command in\n" +
+ " return command.expand()\n" +
+ "↓}\n":
+ "return match(pattern: pattern, with: [.comment]).flatMap { range in\n" +
+ " return Command(string: contents, range: range)\n" +
+ "}.flatMap { command in\n" +
+ " return command.expand()\n" +
+ "}\n",
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x)\n" +
+ "↓})":
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x)\n" +
+ " })",
+ "function(\n" +
+ " closure: { x in\n" +
+ "↓ print(x) })":
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x) \n" +
+ " })",
+ "function(\n" +
+ " closure: { x in\n" +
+ "↓ab})":
+ "function(\n" +
+ " closure: { x in\n" +
+ "ab\n" +
+ " })",
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x)\n" +
+ "↓},\n" +
+ " anotherClosure: { y in\n" +
+ " print(y)\n" +
+ " })":
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x)\n" +
+ " },\n" +
+ " anotherClosure: { y in\n" +
+ " print(y)\n" +
+ " })",
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x)\n" +
+ "↓ },\n" +
+ " anotherClosure: { y in\n" +
+ " print(y)\n" +
+ " })":
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x)\n" +
+ " },\n" +
+ " anotherClosure: { y in\n" +
+ " print(y)\n" +
+ " })",
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x)\n" +
+ "↓ab},\n" +
+ " anotherClosure: { y in\n" +
+ " print(y)\n" +
+ " })":
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x)\n" +
+ "ab\n" +
+ " },\n" +
+ " anotherClosure: { y in\n" +
+ " print(y)\n" +
+ " })",
+ "function(\n" +
+ " closure: { x in\n" +
+ "↓ print(x) },\n" +
+ " anotherClosure: { y in\n" +
+ " print(y)\n" +
+ " })":
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x) \n" +
+ " },\n" +
+ " anotherClosure: { y in\n" +
+ " print(y)\n" +
+ " })",
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x)\n" +
+ "↓}, anotherClosure: { y in\n" +
+ " print(y)\n" +
+ "↓})":
+ "function(\n" +
+ " closure: { x in\n" +
+ " print(x)\n" +
+ " }, anotherClosure: { y in\n" +
+ " print(y)\n" +
+ " })"
+ ]
+}
diff --git a/Source/SwiftLintFramework/Rules/RuleConfigurations/FileNameConfiguration.swift b/Source/SwiftLintFramework/Rules/RuleConfigurations/FileNameConfiguration.swift
new file mode 100644
index 00000000000..f8dc51b72ef
--- /dev/null
+++ b/Source/SwiftLintFramework/Rules/RuleConfigurations/FileNameConfiguration.swift
@@ -0,0 +1,32 @@
+public struct FileNameConfiguration: RuleConfiguration, Equatable {
+ public var consoleDescription: String {
+ return "(severity) \(severity.consoleDescription), " +
+ "excluded: \(excluded.sorted())"
+ }
+
+ private(set) public var severity: SeverityConfiguration
+ private(set) public var excluded: Set
+
+ public init(severity: ViolationSeverity, excluded: [String] = []) {
+ self.severity = SeverityConfiguration(severity)
+ self.excluded = Set(excluded)
+ }
+
+ public mutating func apply(configuration: Any) throws {
+ guard let configurationDict = configuration as? [String: Any] else {
+ throw ConfigurationError.unknownConfiguration
+ }
+
+ if let severityConfiguration = configurationDict["severity"] {
+ try severity.apply(configuration: severityConfiguration)
+ }
+ if let excluded = [String].array(of: configurationDict["excluded"]) {
+ self.excluded = Set(excluded)
+ }
+ }
+}
+
+public func == (lhs: FileNameConfiguration, rhs: FileNameConfiguration) -> Bool {
+ return lhs.severity == rhs.severity &&
+ lhs.excluded == rhs.excluded
+}
diff --git a/Source/SwiftLintFramework/Rules/RuleConfigurations/FunctionParameterCountConfiguration.swift b/Source/SwiftLintFramework/Rules/RuleConfigurations/FunctionParameterCountConfiguration.swift
new file mode 100644
index 00000000000..bbd2d532d31
--- /dev/null
+++ b/Source/SwiftLintFramework/Rules/RuleConfigurations/FunctionParameterCountConfiguration.swift
@@ -0,0 +1,55 @@
+import Foundation
+
+private enum ConfigurationKey: String {
+ case warning = "warning"
+ case error = "error"
+ case ignoresDefaultParameters = "ignores_default_parameters"
+}
+
+public struct FunctionParameterCountConfiguration: RuleConfiguration, Equatable {
+ private(set) var ignoresDefaultParameters: Bool
+ private(set) var severityConfiguration: SeverityLevelsConfiguration
+
+ public var consoleDescription: String {
+ return severityConfiguration.consoleDescription +
+ "\(ConfigurationKey.ignoresDefaultParameters.rawValue): \(ignoresDefaultParameters)"
+ }
+
+ public init(warning: Int, error: Int?, ignoresDefaultParameters: Bool = true) {
+ self.ignoresDefaultParameters = ignoresDefaultParameters
+ self.severityConfiguration = SeverityLevelsConfiguration(warning: warning, error: error)
+ }
+
+ public mutating func apply(configuration: Any) throws {
+ if let configurationArray = [Int].array(of: configuration),
+ !configurationArray.isEmpty {
+ let warning = configurationArray[0]
+ let error = (configurationArray.count > 1) ? configurationArray[1] : nil
+ severityConfiguration = SeverityLevelsConfiguration(warning: warning, error: error)
+ } else if let configDict = configuration as? [String: Any], !configDict.isEmpty {
+ for (string, value) in configDict {
+ guard let key = ConfigurationKey(rawValue: string) else {
+ throw ConfigurationError.unknownConfiguration
+ }
+ switch (key, value) {
+ case (.error, let intValue as Int):
+ severityConfiguration.error = intValue
+ case (.warning, let intValue as Int):
+ severityConfiguration.warning = intValue
+ case (.ignoresDefaultParameters, let boolValue as Bool):
+ ignoresDefaultParameters = boolValue
+ default:
+ throw ConfigurationError.unknownConfiguration
+ }
+ }
+ } else {
+ throw ConfigurationError.unknownConfiguration
+ }
+ }
+
+ public static func == (lhs: FunctionParameterCountConfiguration,
+ rhs: FunctionParameterCountConfiguration) -> Bool {
+ return lhs.severityConfiguration == rhs.severityConfiguration &&
+ lhs.ignoresDefaultParameters == rhs.ignoresDefaultParameters
+ }
+}
diff --git a/Source/SwiftLintFramework/Rules/RuleConfigurations/StatementPositionConfiguration.swift b/Source/SwiftLintFramework/Rules/RuleConfigurations/StatementModeConfiguration.swift
similarity index 100%
rename from Source/SwiftLintFramework/Rules/RuleConfigurations/StatementPositionConfiguration.swift
rename to Source/SwiftLintFramework/Rules/RuleConfigurations/StatementModeConfiguration.swift
diff --git a/Source/SwiftLintFramework/Rules/UnneededParenthesesInClosureArgumentRule.swift b/Source/SwiftLintFramework/Rules/UnneededParenthesesInClosureArgumentRule.swift
index daa5ff2b827..54458e4e5bd 100644
--- a/Source/SwiftLintFramework/Rules/UnneededParenthesesInClosureArgumentRule.swift
+++ b/Source/SwiftLintFramework/Rules/UnneededParenthesesInClosureArgumentRule.swift
@@ -22,7 +22,31 @@ public struct UnneededParenthesesInClosureArgumentRule: ConfigurationProviderRul
"call(arg: { ↓(bar, _) in })\n",
"let foo = { ↓(bar) -> Bool in return true }\n",
"foo.map { ($0, $0) }.forEach { ↓(x, y) in }",
- "foo.bar { [weak self] ↓(x, y) in }"
+ "foo.bar { [weak self] ↓(x, y) in }",
+ """
+ [].first { ↓(temp) in
+ [].first { ↓(temp) in
+ [].first { ↓(temp) in
+ _ = temp
+ return false
+ }
+ return false
+ }
+ return false
+ }
+ """,
+ """
+ [].first { temp in
+ [].first { ↓(temp) in
+ [].first { ↓(temp) in
+ _ = temp
+ return false
+ }
+ return false
+ }
+ return false
+ }
+ """
],
corrections: [
"call(arg: { ↓(bar) in })\n": "call(arg: { bar in })\n",
@@ -44,7 +68,7 @@ public struct UnneededParenthesesInClosureArgumentRule: ConfigurationProviderRul
private func violationRanges(file: File) -> [NSRange] {
let capturesPattern = "(?:\\[[^\\]]+\\])?"
- let pattern = "\\{\\s*\(capturesPattern)\\s*(\\([^:}]+\\))\\s*(in|->)"
+ let pattern = "\\{\\s*\(capturesPattern)\\s*(\\([^:}]+?\\))\\s*(in|->)"
let contents = file.contents.bridge()
let range = NSRange(location: 0, length: contents.length)
return regex(pattern).matches(in: file.contents, options: [], range: range).compactMap { match -> NSRange? in
diff --git a/Source/SwiftLintFramework/Rules/UntypedErrorInCatchRule.swift b/Source/SwiftLintFramework/Rules/UntypedErrorInCatchRule.swift
index 62b6f66b347..6521e2644ea 100644
--- a/Source/SwiftLintFramework/Rules/UntypedErrorInCatchRule.swift
+++ b/Source/SwiftLintFramework/Rules/UntypedErrorInCatchRule.swift
@@ -49,17 +49,44 @@ public struct UntypedErrorInCatchRule: OptInRule, ConfigurationProviderRule {
"do {\n try foo() \n} ↓catch let e {}",
"do {\n try foo() \n} ↓catch(let error) {}",
"do {\n try foo() \n} ↓catch (let error) {}"
+ ],
+ corrections: [
+ "do {\n try foo() \n} ↓catch let error {}": "do {\n try foo() \n} catch {}",
+ "do {\n try foo() \n} ↓catch(let error) {}": "do {\n try foo() \n} catch {}",
+ "do {\n try foo() \n} ↓catch (let error) {}": "do {\n try foo() \n} catch {}"
])
public func validate(file: File) -> [StyleViolation] {
- let matches = file.match(pattern: type(of: self).regularExpression,
- with: [.keyword, .keyword, .identifier])
-
- return matches.map {
+ return violationRanges(in: file).map {
return StyleViolation(ruleDescription: type(of: self).description,
severity: configuration.severity,
location: Location(file: file, characterOffset: $0.location),
reason: configuration.consoleDescription)
}
}
+
+ fileprivate func violationRanges(in file: File) -> [NSRange] {
+ return file.match(pattern: type(of: self).regularExpression,
+ with: [.keyword, .keyword, .identifier])
+ }
+}
+
+extension UntypedErrorInCatchRule: CorrectableRule {
+ public func correct(file: File) -> [Correction] {
+ let violations = violationRanges(in: file)
+ let matches = file.ruleEnabled(violatingRanges: violations, for: self)
+ if matches.isEmpty { return [] }
+
+ var contents = file.contents.bridge()
+ let description = type(of: self).description
+ var corrections = [Correction]()
+
+ for range in matches.reversed() where contents.substring(with: range).contains("let error") {
+ contents = contents.replacingCharacters(in: range, with: "catch {").bridge()
+ let location = Location(file: file, characterOffset: range.location)
+ corrections.append(Correction(ruleDescription: description, location: location))
+ }
+ file.write(contents.bridge())
+ return corrections
+ }
}
diff --git a/Source/SwiftLintFramework/Rules/UnusedClosureParameterRule.swift b/Source/SwiftLintFramework/Rules/UnusedClosureParameterRule.swift
index 3836d46078c..84de4fb5acc 100644
--- a/Source/SwiftLintFramework/Rules/UnusedClosureParameterRule.swift
+++ b/Source/SwiftLintFramework/Rules/UnusedClosureParameterRule.swift
@@ -38,6 +38,11 @@ public struct UnusedClosureParameterRule: ASTRule, ConfigurationProviderRule, Co
({ (manager: FileManager) in
print(manager)
})(FileManager.default)
+ """,
+ """
+ withPostSideEffect { input in
+ if true { print("\\(input)") }
+ }
"""
],
triggeringExamples: [
@@ -130,15 +135,18 @@ public struct UnusedClosureParameterRule: ASTRule, ConfigurationProviderRule, Co
length: range.length),
// if it's the parameter declaration itself, we should skip
byteRange.location > paramOffset,
- case let tokens = file.syntaxMap.tokens(inByteRange: byteRange),
- // a parameter usage should be only one token
- tokens.count == 1 else {
- continue
+ case let tokens = file.syntaxMap.tokens(inByteRange: byteRange) else {
+ continue
}
+ let token = tokens.first(where: { token -> Bool in
+ return SyntaxKind(rawValue: token.type) == .identifier &&
+ token.offset == byteRange.location &&
+ token.length == byteRange.length
+ })
+
// found a usage, there's no violation!
- if let token = tokens.first, SyntaxKind(rawValue: token.type) == .identifier,
- token.offset == byteRange.location, token.length == byteRange.length {
+ guard token == nil else {
return nil
}
}
diff --git a/Source/swiftlint/Extensions/shim.swift b/Source/swiftlint/Extensions/shim.swift
index 2b6edaa89b4..d7817537fd2 100644
--- a/Source/swiftlint/Extensions/shim.swift
+++ b/Source/swiftlint/Extensions/shim.swift
@@ -1,11 +1,11 @@
-#if (!swift(>=4.1) && swift(>=4.0)) || !swift(>=3.3)
+#if !swift(>=4.1)
- extension Sequence {
- func compactMap(
- _ transform: (Self.Element
- ) throws -> ElementOfResult?) rethrows -> [ElementOfResult] {
- return try flatMap(transform)
- }
+extension Sequence {
+ func compactMap(
+ _ transform: (Self.Element
+ ) throws -> ElementOfResult?) rethrows -> [ElementOfResult] {
+ return try flatMap(transform)
}
+}
#endif
diff --git a/SwiftLint.xcodeproj/project.pbxproj b/SwiftLint.xcodeproj/project.pbxproj
index c629e2c30aa..d79cbf81e82 100644
--- a/SwiftLint.xcodeproj/project.pbxproj
+++ b/SwiftLint.xcodeproj/project.pbxproj
@@ -41,10 +41,11 @@
2E5761AA1C573B83003271AF /* FunctionParameterCountRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E5761A91C573B83003271AF /* FunctionParameterCountRule.swift */; };
31F1B6CC1F60BF4500A57456 /* SwitchCaseAlignmentRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31F1B6CB1F60BF4500A57456 /* SwitchCaseAlignmentRule.swift */; };
37B3FA8B1DFD45A700AD30D2 /* Dictionary+SwiftLint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B3FA8A1DFD45A700AD30D2 /* Dictionary+SwiftLint.swift */; };
+ 3A915E5B20A1543700519F3A /* ClosureEndIndentationRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A915E5920A1543000519F3A /* ClosureEndIndentationRuleExamples.swift */; };
3B034B6E1E0BE549005D49A9 /* LineLengthConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B034B6C1E0BE544005D49A9 /* LineLengthConfiguration.swift */; };
3B0B14541C505D6300BE82F7 /* SeverityConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B0B14531C505D6300BE82F7 /* SeverityConfiguration.swift */; };
3B12C9C11C3209CB000B423F /* test.yml in Resources */ = {isa = PBXBuildFile; fileRef = 3B12C9BF1C3209AC000B423F /* test.yml */; };
- 3B12C9C31C320A53000B423F /* Yaml+SwiftLintTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B12C9C21C320A53000B423F /* Yaml+SwiftLintTests.swift */; };
+ 3B12C9C31C320A53000B423F /* YamlSwiftLintTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B12C9C21C320A53000B423F /* YamlSwiftLintTests.swift */; };
3B12C9C51C322032000B423F /* MasterRuleList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B12C9C41C322032000B423F /* MasterRuleList.swift */; };
3B12C9C71C3361CB000B423F /* RuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B12C9C61C3361CB000B423F /* RuleTests.swift */; };
3B1DF0121C5148140011BCED /* CustomRules.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1DF0111C5148140011BCED /* CustomRules.swift */; };
@@ -87,16 +88,18 @@
62622F6B1F2F2E3500D5D099 /* DiscouragedDirectInitRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62622F6A1F2F2E3500D5D099 /* DiscouragedDirectInitRule.swift */; };
62640152201552FD005B9C4A /* DiscouragedOptionalBooleanRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62640150201552E0005B9C4A /* DiscouragedOptionalBooleanRule.swift */; };
6264015520155556005B9C4A /* DiscouragedOptionalBooleanRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6264015320155533005B9C4A /* DiscouragedOptionalBooleanRuleExamples.swift */; };
+ 626B01B620A173F100D2C42F /* EmptyXCTestMethodRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 626B01B420A1735900D2C42F /* EmptyXCTestMethodRuleExamples.swift */; };
626C16E21F948EBC00BB7475 /* QuickDiscouragedFocusedTestRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 626C16E01F948E1C00BB7475 /* QuickDiscouragedFocusedTestRuleExamples.swift */; };
626D02971F31CBCC0054788D /* XCTFailMessageRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 626D02961F31CBCC0054788D /* XCTFailMessageRule.swift */; };
627BC48D1F9405160004A6C2 /* QuickDiscouragedFocusedTestRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E54FED1F93AD57005B367B /* QuickDiscouragedFocusedTestRule.swift */; };
629ADD062006302D0009E362 /* DiscouragedOptionalCollectionRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 629ADD052006302D0009E362 /* DiscouragedOptionalCollectionRule.swift */; };
629C60D91F43906700B4AF92 /* SingleTestClassRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 629C60D81F43906700B4AF92 /* SingleTestClassRule.swift */; };
+ 62A3E95D209E084000547A86 /* EmptyXCTestMethodRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A3E95B209E078000547A86 /* EmptyXCTestMethodRule.swift */; };
62A498561F306A7700D766E4 /* DiscouragedDirectInitConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A498551F306A7700D766E4 /* DiscouragedDirectInitConfiguration.swift */; };
- 62A6E7931F3317E3003A0479 /* JoinedDefaultRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A6E7911F3317E3003A0479 /* JoinedDefaultRule.swift */; };
+ 62A6E7931F3317E3003A0479 /* JoinedDefaultParameterRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A6E7911F3317E3003A0479 /* JoinedDefaultParameterRule.swift */; };
62DADC481FFF0423002B6319 /* PrefixedTopLevelConstantRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62DADC471FFF0423002B6319 /* PrefixedTopLevelConstantRule.swift */; };
62DEA1661FB21A9E00BCCCC6 /* PrivateActionRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62DEA1651FB21A9E00BCCCC6 /* PrivateActionRule.swift */; };
- 62FE5D32200CABDD00F68793 /* DiscouragedOptionalCollectionRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FE5D30200CAB6E00F68793 /* DiscouragedOptionalCollectionRuleExamples.swift */; };
+ 62FE5D32200CABDD00F68793 /* DiscouragedOptionalCollectionExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FE5D30200CAB6E00F68793 /* DiscouragedOptionalCollectionExamples.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 */; };
@@ -114,7 +117,7 @@
6CCFCF2D1CFEF731003239EB /* SourceKittenFramework.framework in Embed Frameworks into SwiftLintFramework.framework */ = {isa = PBXBuildFile; fileRef = E876BFBD1B07828500114ED5 /* SourceKittenFramework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
6CCFCF2E1CFEF73A003239EB /* SWXMLHash.framework in Embed Frameworks into SwiftLintFramework.framework */ = {isa = PBXBuildFile; fileRef = E8C0DFCC1AD349DB007EE3D4 /* SWXMLHash.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
6CCFCF2F1CFEF73E003239EB /* SwiftyTextTable.framework in Embed Frameworks into SwiftLintFramework.framework */ = {isa = PBXBuildFile; fileRef = 3BBF2F9C1C640A0F006CD775 /* SwiftyTextTable.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
- 7250948A1D0859260039B353 /* StatementPositionConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 725094881D0855760039B353 /* StatementPositionConfiguration.swift */; };
+ 7250948A1D0859260039B353 /* StatementModeConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 725094881D0855760039B353 /* StatementModeConfiguration.swift */; };
72EA17B61FD31F10009D5CE6 /* ExplicitACLRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72EA17B51FD31F10009D5CE6 /* ExplicitACLRule.swift */; };
740DF1B1203F62BB0081F694 /* EmptyStringRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 740DF1AF203F5AFC0081F694 /* EmptyStringRule.swift */; };
787CDE39208E7D41005F3D2F /* SwitchCaseAlignmentConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787CDE38208E7D41005F3D2F /* SwitchCaseAlignmentConfiguration.swift */; };
@@ -128,6 +131,10 @@
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 */; };
+ 8B01E4FD20A41C8700C9233E /* FunctionParameterCountConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B01E4FB20A4183C00C9233E /* FunctionParameterCountConfiguration.swift */; };
+ 8B01E50220A4349100C9233E /* FunctionParameterCountRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B01E4FF20A4340A00C9233E /* FunctionParameterCountRuleTests.swift */; };
+ 8F2CC1CB20A6A070006ED34F /* FileNameConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2CC1CA20A6A070006ED34F /* FileNameConfiguration.swift */; };
+ 8F2CC1CD20A6A189006ED34F /* FileNameRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2CC1CC20A6A189006ED34F /* FileNameRuleTests.swift */; };
8F8050821FFE0CBB006F5B93 /* Configuration+IndentationStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F8050811FFE0CBB006F5B93 /* Configuration+IndentationStyle.swift */; };
8FC9F5111F4B8E48006826C1 /* IsDisjointRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FC9F5101F4B8E48006826C1 /* IsDisjointRule.swift */; };
8FD216CC205584AF008ED13F /* CharacterSet+SwiftLint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FD216CB205584AF008ED13F /* CharacterSet+SwiftLint.swift */; };
@@ -155,7 +162,7 @@
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 */; };
- C26330382073DAC500D7B4FD /* LowerACLThanBodyRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C26330352073DAA200D7B4FD /* LowerACLThanBodyRule.swift */; };
+ C26330382073DAC500D7B4FD /* LowerACLThanParentRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C26330352073DAA200D7B4FD /* LowerACLThanParentRule.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 */; };
@@ -211,7 +218,7 @@
D47EF4821F69E34D0012C4CA /* ColonRule+Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47EF4811F69E34D0012C4CA /* ColonRule+Dictionary.swift */; };
D47EF4841F69E3D60012C4CA /* ColonRule+Type.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47EF4831F69E3D60012C4CA /* ColonRule+Type.swift */; };
D47F31151EC918B600E3E1CA /* ProtocolPropertyAccessorsOrderRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F31141EC918B600E3E1CA /* ProtocolPropertyAccessorsOrderRule.swift */; };
- D48AE2CC1DFB58C5001C6A4A /* AttributesRulesExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = D48AE2CB1DFB58C5001C6A4A /* AttributesRulesExamples.swift */; };
+ D48AE2CC1DFB58C5001C6A4A /* AttributesRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = D48AE2CB1DFB58C5001C6A4A /* AttributesRuleExamples.swift */; };
D48B51211F4F5DEF0068AB98 /* RuleList+Documentation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D48B51201F4F5DEF0068AB98 /* RuleList+Documentation.swift */; };
D48B51231F4F5E4B0068AB98 /* DocumentationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D48B51221F4F5E4B0068AB98 /* DocumentationTests.swift */; };
D49896F12026B36C00814A83 /* RedundantSetAccessControlRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49896F02026B36C00814A83 /* RedundantSetAccessControlRule.swift */; };
@@ -234,6 +241,7 @@
D4C4A3521DEFBBB700E0E04C /* FileHeaderConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C4A3511DEFBBB700E0E04C /* FileHeaderConfiguration.swift */; };
D4C889711E385B7B00BAE88D /* RedundantDiscardableLetRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C889701E385B7B00BAE88D /* RedundantDiscardableLetRule.swift */; };
D4CA758F1E2DEEA500A40E8A /* NumberSeparatorRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CA758E1E2DEEA500A40E8A /* NumberSeparatorRuleTests.swift */; };
+ D4CFC5D2209EC95A00668488 /* FunctionDefaultParameterAtEndRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CFC5D1209EC95A00668488 /* FunctionDefaultParameterAtEndRule.swift */; };
D4D1B9BB1EAC2C910028BE6A /* AccessControlLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D1B9B91EAC2C870028BE6A /* AccessControlLevel.swift */; };
D4D5A5FF1E1F3A1C00D15E0C /* ShorthandOperatorRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D5A5FE1E1F3A1C00D15E0C /* ShorthandOperatorRule.swift */; };
D4DA1DF41E17511D0037413D /* CompilerProtocolInitRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DA1DF31E17511D0037413D /* CompilerProtocolInitRule.swift */; };
@@ -272,8 +280,9 @@
E81ADD741ED6052F000CD451 /* CommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E81ADD731ED6052F000CD451 /* CommandTests.swift */; };
E81FB3E41C6D507B00DC988F /* CommonOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E81FB3E31C6D507B00DC988F /* CommonOptions.swift */; };
E82367E01ED3BD1E0040A88E /* Configuration+Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = E82367DF1ED3BD1E0040A88E /* Configuration+Cache.swift */; };
- E832F10B1B17E2F5003F265F /* NSFileManager+SwiftLint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E832F10A1B17E2F5003F265F /* NSFileManager+SwiftLint.swift */; };
+ E832F10B1B17E2F5003F265F /* FileManager+SwiftLint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E832F10A1B17E2F5003F265F /* FileManager+SwiftLint.swift */; };
E832F10D1B17E725003F265F /* IntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E832F10C1B17E725003F265F /* IntegrationTests.swift */; };
+ E83530C61ED6328A00FBAF79 /* FileNameRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E83530C51ED6328A00FBAF79 /* FileNameRule.swift */; };
E83A0B351A5D382B0041A60A /* VersionCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E83A0B341A5D382B0041A60A /* VersionCommand.swift */; };
E847F0A91BFBBABD00EA9363 /* EmptyCountRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E847F0A81BFBBABD00EA9363 /* EmptyCountRule.swift */; };
E84E07471C13F95300F11122 /* AutoCorrectCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E84E07461C13F95300F11122 /* AutoCorrectCommand.swift */; };
@@ -412,10 +421,11 @@
2E5761A91C573B83003271AF /* FunctionParameterCountRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionParameterCountRule.swift; sourceTree = ""; };
31F1B6CB1F60BF4500A57456 /* SwitchCaseAlignmentRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwitchCaseAlignmentRule.swift; sourceTree = ""; };
37B3FA8A1DFD45A700AD30D2 /* Dictionary+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Dictionary+SwiftLint.swift"; sourceTree = ""; };
+ 3A915E5920A1543000519F3A /* ClosureEndIndentationRuleExamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ClosureEndIndentationRuleExamples.swift; path = RuleConfigurations/ClosureEndIndentationRuleExamples.swift; sourceTree = ""; };
3B034B6C1E0BE544005D49A9 /* LineLengthConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineLengthConfiguration.swift; sourceTree = ""; };
3B0B14531C505D6300BE82F7 /* SeverityConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeverityConfiguration.swift; sourceTree = ""; };
3B12C9BF1C3209AC000B423F /* test.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = test.yml; sourceTree = ""; };
- 3B12C9C21C320A53000B423F /* Yaml+SwiftLintTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Yaml+SwiftLintTests.swift"; sourceTree = ""; };
+ 3B12C9C21C320A53000B423F /* YamlSwiftLintTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YamlSwiftLintTests.swift; sourceTree = ""; };
3B12C9C41C322032000B423F /* MasterRuleList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MasterRuleList.swift; sourceTree = ""; };
3B12C9C61C3361CB000B423F /* RuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RuleTests.swift; sourceTree = ""; };
3B1DF0111C5148140011BCED /* CustomRules.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomRules.swift; sourceTree = ""; };
@@ -459,17 +469,19 @@
62622F6A1F2F2E3500D5D099 /* DiscouragedDirectInitRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscouragedDirectInitRule.swift; sourceTree = ""; };
62640150201552E0005B9C4A /* DiscouragedOptionalBooleanRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscouragedOptionalBooleanRule.swift; sourceTree = ""; };
6264015320155533005B9C4A /* DiscouragedOptionalBooleanRuleExamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscouragedOptionalBooleanRuleExamples.swift; sourceTree = ""; };
+ 626B01B420A1735900D2C42F /* EmptyXCTestMethodRuleExamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyXCTestMethodRuleExamples.swift; sourceTree = ""; };
626C16E01F948E1C00BB7475 /* QuickDiscouragedFocusedTestRuleExamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickDiscouragedFocusedTestRuleExamples.swift; sourceTree = ""; };
626D02961F31CBCC0054788D /* XCTFailMessageRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTFailMessageRule.swift; sourceTree = ""; };
629ADD052006302D0009E362 /* DiscouragedOptionalCollectionRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscouragedOptionalCollectionRule.swift; sourceTree = ""; };
629C60D81F43906700B4AF92 /* SingleTestClassRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleTestClassRule.swift; sourceTree = ""; };
+ 62A3E95B209E078000547A86 /* EmptyXCTestMethodRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyXCTestMethodRule.swift; sourceTree = ""; };
62A498551F306A7700D766E4 /* DiscouragedDirectInitConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscouragedDirectInitConfiguration.swift; sourceTree = ""; };
- 62A6E7911F3317E3003A0479 /* JoinedDefaultRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinedDefaultRule.swift; sourceTree = ""; };
+ 62A6E7911F3317E3003A0479 /* JoinedDefaultParameterRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinedDefaultParameterRule.swift; sourceTree = ""; };
62AF35D71F30B183009B11EE /* DiscouragedDirectInitRuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscouragedDirectInitRuleTests.swift; sourceTree = ""; };
62DADC471FFF0423002B6319 /* PrefixedTopLevelConstantRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefixedTopLevelConstantRule.swift; sourceTree = ""; };
62DEA1651FB21A9E00BCCCC6 /* PrivateActionRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrivateActionRule.swift; sourceTree = ""; };
62E54FED1F93AD57005B367B /* QuickDiscouragedFocusedTestRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickDiscouragedFocusedTestRule.swift; sourceTree = ""; };
- 62FE5D30200CAB6E00F68793 /* DiscouragedOptionalCollectionRuleExamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscouragedOptionalCollectionRuleExamples.swift; sourceTree = ""; };
+ 62FE5D30200CAB6E00F68793 /* DiscouragedOptionalCollectionExamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscouragedOptionalCollectionExamples.swift; sourceTree = ""; };
65454F451B14D73800319A6C /* ControlStatementRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ControlStatementRule.swift; sourceTree = ""; };
67932E2C1E54AF4B00CB0629 /* CyclomaticComplexityConfigurationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CyclomaticComplexityConfigurationTests.swift; sourceTree = ""; };
67EB4DF81E4CC101004E9ACD /* CyclomaticComplexityConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CyclomaticComplexityConfiguration.swift; sourceTree = ""; };
@@ -484,7 +496,7 @@
6CB514E81C760C6900FA02C4 /* Structure+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Structure+SwiftLint.swift"; sourceTree = ""; };
6CC4259A1C77046200AEA885 /* SyntaxMap+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SyntaxMap+SwiftLint.swift"; sourceTree = ""; };
6CC898A61EA0E1EF003DC0E2 /* CannedEmojiReporterOutputNonObjC.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CannedEmojiReporterOutputNonObjC.txt; sourceTree = ""; };
- 725094881D0855760039B353 /* StatementPositionConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatementPositionConfiguration.swift; sourceTree = ""; };
+ 725094881D0855760039B353 /* StatementModeConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatementModeConfiguration.swift; sourceTree = ""; };
72EA17B51FD31F10009D5CE6 /* ExplicitACLRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExplicitACLRule.swift; sourceTree = ""; };
740DF1AF203F5AFC0081F694 /* EmptyStringRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyStringRule.swift; sourceTree = ""; };
787CDE38208E7D41005F3D2F /* SwitchCaseAlignmentConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchCaseAlignmentConfiguration.swift; sourceTree = ""; };
@@ -498,6 +510,10 @@
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 = ""; };
+ 8B01E4FB20A4183C00C9233E /* FunctionParameterCountConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FunctionParameterCountConfiguration.swift; sourceTree = ""; };
+ 8B01E4FF20A4340A00C9233E /* FunctionParameterCountRuleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FunctionParameterCountRuleTests.swift; sourceTree = ""; };
+ 8F2CC1CA20A6A070006ED34F /* FileNameConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileNameConfiguration.swift; sourceTree = ""; };
+ 8F2CC1CC20A6A189006ED34F /* FileNameRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileNameRuleTests.swift; sourceTree = ""; };
8F8050811FFE0CBB006F5B93 /* Configuration+IndentationStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Configuration+IndentationStyle.swift"; sourceTree = ""; };
8FC9F5101F4B8E48006826C1 /* IsDisjointRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IsDisjointRule.swift; sourceTree = ""; };
8FD216CB205584AF008ED13F /* CharacterSet+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CharacterSet+SwiftLint.swift"; sourceTree = ""; };
@@ -525,7 +541,7 @@
B89F3BCB1FD5EDA900931E59 /* RequiredEnumCaseRuleTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequiredEnumCaseRuleTestCase.swift; sourceTree = ""; };
BB00B4E71F5216070079869F /* MultipleClosuresWithTrailingClosureRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultipleClosuresWithTrailingClosureRule.swift; sourceTree = ""; };
BF48D2D61CBCCA5F0080BDAE /* TrailingWhitespaceConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrailingWhitespaceConfiguration.swift; sourceTree = ""; };
- C26330352073DAA200D7B4FD /* LowerACLThanBodyRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LowerACLThanBodyRule.swift; sourceTree = ""; };
+ C26330352073DAA200D7B4FD /* LowerACLThanParentRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LowerACLThanParentRule.swift; sourceTree = ""; };
C328A2F51E67595500A9E4D7 /* ExplicitTypeInterfaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExplicitTypeInterfaceRule.swift; sourceTree = ""; };
C3DE5DAA1E7DF99B00761483 /* FatalErrorMessageRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FatalErrorMessageRule.swift; sourceTree = ""; };
C946FEC91EAE5E20007DD778 /* LetVarWhitespaceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LetVarWhitespaceRule.swift; sourceTree = ""; };
@@ -601,7 +617,7 @@
D47EF4811F69E34D0012C4CA /* ColonRule+Dictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ColonRule+Dictionary.swift"; sourceTree = ""; };
D47EF4831F69E3D60012C4CA /* ColonRule+Type.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ColonRule+Type.swift"; sourceTree = ""; };
D47F31141EC918B600E3E1CA /* ProtocolPropertyAccessorsOrderRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProtocolPropertyAccessorsOrderRule.swift; sourceTree = ""; };
- D48AE2CB1DFB58C5001C6A4A /* AttributesRulesExamples.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributesRulesExamples.swift; sourceTree = ""; };
+ D48AE2CB1DFB58C5001C6A4A /* AttributesRuleExamples.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributesRuleExamples.swift; sourceTree = ""; };
D48B51201F4F5DEF0068AB98 /* RuleList+Documentation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "RuleList+Documentation.swift"; sourceTree = ""; };
D48B51221F4F5E4B0068AB98 /* DocumentationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DocumentationTests.swift; sourceTree = ""; };
D49896F02026B36C00814A83 /* RedundantSetAccessControlRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedundantSetAccessControlRule.swift; sourceTree = ""; };
@@ -624,6 +640,7 @@
D4C4A3511DEFBBB700E0E04C /* FileHeaderConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileHeaderConfiguration.swift; sourceTree = ""; };
D4C889701E385B7B00BAE88D /* RedundantDiscardableLetRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedundantDiscardableLetRule.swift; sourceTree = ""; };
D4CA758E1E2DEEA500A40E8A /* NumberSeparatorRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberSeparatorRuleTests.swift; sourceTree = ""; };
+ D4CFC5D1209EC95A00668488 /* FunctionDefaultParameterAtEndRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FunctionDefaultParameterAtEndRule.swift; sourceTree = ""; };
D4D1B9B91EAC2C870028BE6A /* AccessControlLevel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessControlLevel.swift; sourceTree = ""; };
D4D5A5FE1E1F3A1C00D15E0C /* ShorthandOperatorRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShorthandOperatorRule.swift; sourceTree = ""; };
D4DA1DF31E17511D0037413D /* CompilerProtocolInitRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompilerProtocolInitRule.swift; sourceTree = ""; };
@@ -663,8 +680,9 @@
E81ADD731ED6052F000CD451 /* CommandTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandTests.swift; sourceTree = ""; };
E81FB3E31C6D507B00DC988F /* CommonOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommonOptions.swift; sourceTree = ""; };
E82367DF1ED3BD1E0040A88E /* Configuration+Cache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Configuration+Cache.swift"; sourceTree = ""; };
- E832F10A1B17E2F5003F265F /* NSFileManager+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFileManager+SwiftLint.swift"; sourceTree = ""; };
+ E832F10A1B17E2F5003F265F /* FileManager+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FileManager+SwiftLint.swift"; sourceTree = ""; };
E832F10C1B17E725003F265F /* IntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntegrationTests.swift; sourceTree = ""; };
+ E83530C51ED6328A00FBAF79 /* FileNameRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileNameRule.swift; sourceTree = ""; };
E83A0B341A5D382B0041A60A /* VersionCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionCommand.swift; sourceTree = ""; };
E847F0A81BFBBABD00EA9363 /* EmptyCountRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyCountRule.swift; sourceTree = ""; };
E84E07461C13F95300F11122 /* AutoCorrectCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutoCorrectCommand.swift; sourceTree = ""; };
@@ -782,6 +800,7 @@
125AAC77203AA82D0004BCE0 /* ExplicitTypeInterfaceConfiguration.swift */,
D4C4A3511DEFBBB700E0E04C /* FileHeaderConfiguration.swift */,
29FFC3781F1574FD007E4825 /* FileLengthRuleConfiguration.swift */,
+ 8B01E4FB20A4183C00C9233E /* FunctionParameterCountConfiguration.swift */,
47ACC8971E7DC74E0088EEB2 /* ImplicitlyUnwrappedOptionalConfiguration.swift */,
3B034B6C1E0BE544005D49A9 /* LineLengthConfiguration.swift */,
3BCC04D01C4F56D3006073C3 /* NameConfiguration.swift */,
@@ -798,12 +817,13 @@
B89F3BC71FD5ED7D00931E59 /* RequiredEnumCaseRuleConfiguration.swift */,
3B0B14531C505D6300BE82F7 /* SeverityConfiguration.swift */,
3BCC04CF1C4F56D3006073C3 /* SeverityLevelsConfiguration.swift */,
- 725094881D0855760039B353 /* StatementPositionConfiguration.swift */,
+ 725094881D0855760039B353 /* StatementModeConfiguration.swift */,
D40F83871DE9179200524C62 /* TrailingCommaConfiguration.swift */,
BF48D2D61CBCCA5F0080BDAE /* TrailingWhitespaceConfiguration.swift */,
CE8178EB1EAC02CD0063186E /* UnusedOptionalBindingConfiguration.swift */,
006204DA1E1E48F900FFFBE1 /* VerticalWhitespaceConfiguration.swift */,
787CDE38208E7D41005F3D2F /* SwitchCaseAlignmentConfiguration.swift */,
+ 8F2CC1CA20A6A070006ED34F /* FileNameConfiguration.swift */,
);
path = RuleConfigurations;
sourceTree = "";
@@ -981,7 +1001,9 @@
02FD8AEE1BFC18D60014BFFB /* ExtendedNSStringTests.swift */,
D4998DE81DF194F20006E05D /* FileHeaderRuleTests.swift */,
29FFC37B1F157BA8007E4825 /* FileLengthRuleTests.swift */,
+ 8F2CC1CC20A6A189006ED34F /* FileNameRuleTests.swift */,
D4348EE91C46122C007707FB /* FunctionBodyLengthRuleTests.swift */,
+ 8B01E4FF20A4340A00C9233E /* FunctionParameterCountRuleTests.swift */,
3B20CD091EB699380069EF2E /* GenericTypeNameRuleTests.swift */,
3B3A9A321EA3DFD90075B121 /* IdentifierNameRuleTests.swift */,
47ACC8991E7DCCAD0088EEB2 /* ImplicitlyUnwrappedOptionalConfigurationTests.swift */,
@@ -1011,7 +1033,7 @@
D4470D5A1EB76F44008A1B2E /* UnusedOptionalBindingRuleTests.swift */,
006204DD1E1E4E0A00FFFBE1 /* VerticalWhitespaceRuleTests.swift */,
F480DC801F2609AB00099465 /* XCTestCase+BundlePath.swift */,
- 3B12C9C21C320A53000B423F /* Yaml+SwiftLintTests.swift */,
+ 3B12C9C21C320A53000B423F /* YamlSwiftLintTests.swift */,
3B30C4A01C3785B300E04027 /* YamlParserTests.swift */,
D0D1212219E878CC005E4BAA /* Configuration */,
3B12C9BE1C3209AC000B423F /* Resources */,
@@ -1069,11 +1091,12 @@
children = (
D4E2BA841F6CD77B00E8E184 /* ArrayInitRule.swift */,
D47A510F1DB2DD4800A4CC21 /* AttributesRule.swift */,
- D48AE2CB1DFB58C5001C6A4A /* AttributesRulesExamples.swift */,
+ D48AE2CB1DFB58C5001C6A4A /* AttributesRuleExamples.swift */,
D4FD4C841F2A260A00DD8AA8 /* BlockBasedKVORule.swift */,
D4B0228D1E0CC608007E5297 /* ClassDelegateProtocolRule.swift */,
1F11B3CE1C252F23002E8FA8 /* ClosingBraceRule.swift */,
D43B046A1E075905004016AF /* ClosureEndIndentationRule.swift */,
+ 3A915E5920A1543000519F3A /* ClosureEndIndentationRuleExamples.swift */,
D47079A81DFDBED000027086 /* ClosureParameterPositionRule.swift */,
1E82D5581D7775C7009553D7 /* ClosureSpacingRule.swift */,
E88DEA831B0990F500A66CB0 /* ColonRule.swift */,
@@ -1091,16 +1114,18 @@
62622F6A1F2F2E3500D5D099 /* DiscouragedDirectInitRule.swift */,
6258783A1FFC458100AC34F2 /* DiscouragedObjectLiteralRule.swift */,
62640150201552E0005B9C4A /* DiscouragedOptionalBooleanRule.swift */,
- C26330352073DAA200D7B4FD /* LowerACLThanBodyRule.swift */,
+ D4CFC5D1209EC95A00668488 /* FunctionDefaultParameterAtEndRule.swift */,
6264015320155533005B9C4A /* DiscouragedOptionalBooleanRuleExamples.swift */,
629ADD052006302D0009E362 /* DiscouragedOptionalCollectionRule.swift */,
- 62FE5D30200CAB6E00F68793 /* DiscouragedOptionalCollectionRuleExamples.swift */,
+ 62FE5D30200CAB6E00F68793 /* DiscouragedOptionalCollectionExamples.swift */,
E315B83B1DFA4BC500621B44 /* DynamicInlineRule.swift */,
E847F0A81BFBBABD00EA9363 /* EmptyCountRule.swift */,
- 740DF1AF203F5AFC0081F694 /* EmptyStringRule.swift */,
D4470D581EB6B4D1008A1B2E /* EmptyEnumArgumentsRule.swift */,
D47079AC1DFE2FA700027086 /* EmptyParametersRule.swift */,
D47079A61DFCEB2D00027086 /* EmptyParenthesesWithTrailingClosureRule.swift */,
+ 740DF1AF203F5AFC0081F694 /* EmptyStringRule.swift */,
+ 62A3E95B209E078000547A86 /* EmptyXCTestMethodRule.swift */,
+ 626B01B420A1735900D2C42F /* EmptyXCTestMethodRuleExamples.swift */,
72EA17B51FD31F10009D5CE6 /* ExplicitACLRule.swift */,
827169B21F488181003FB9AF /* ExplicitEnumRawValueRule.swift */,
7C0C2E791D2866CB0076435A /* ExplicitInitRule.swift */,
@@ -1111,6 +1136,7 @@
C3DE5DAA1E7DF99B00761483 /* FatalErrorMessageRule.swift */,
D4C4A34D1DEA877200E0E04C /* FileHeaderRule.swift */,
E88DEA891B0992B300A66CB0 /* FileLengthRule.swift */,
+ E83530C51ED6328A00FBAF79 /* FileNameRule.swift */,
D42D2B371E09CC0D00CD7A2E /* FirstWhereRule.swift */,
E88DEA7F1B09903300A66CB0 /* ForceCastRule.swift */,
E816194D1BFBFEAB00946723 /* ForceTryRule.swift */,
@@ -1125,7 +1151,7 @@
47FF3BDF1E7C745100187E6D /* ImplicitlyUnwrappedOptionalRule.swift */,
D4470D561EB69225008A1B2E /* ImplicitReturnRule.swift */,
8FC9F5101F4B8E48006826C1 /* IsDisjointRule.swift */,
- 62A6E7911F3317E3003A0479 /* JoinedDefaultRule.swift */,
+ 62A6E7911F3317E3003A0479 /* JoinedDefaultParameterRule.swift */,
D4DA1DF91E18D6200037413D /* LargeTupleRule.swift */,
E88DEA7D1B098F2A00A66CB0 /* LeadingWhitespaceRule.swift */,
4DB7815C1CAD690100BC4723 /* LegacyCGGeometryFunctionsRule.swift */,
@@ -1136,6 +1162,7 @@
C946FEC91EAE5E20007DD778 /* LetVarWhitespaceRule.swift */,
E88DEA7B1B098D7D00A66CB0 /* LineLengthRule.swift */,
D4EA77C91F81FACC00C315FB /* LiteralExpressionEndIdentationRule.swift */,
+ C26330352073DAA200D7B4FD /* LowerACLThanParentRule.swift */,
856651A61D6B395F005E6B29 /* MarkRule.swift */,
188B3FF1207D61040073C2D6 /* ModifierOrderRule.swift */,
B25DCD0D1F7EF2280028A199 /* MultilineArgumentsConfiguration.swift */,
@@ -1274,7 +1301,7 @@
37B3FA8A1DFD45A700AD30D2 /* Dictionary+SwiftLint.swift */,
24E17F701B1481FF008195BE /* File+Cache.swift */,
E88DEA741B09852000A66CB0 /* File+SwiftLint.swift */,
- E832F10A1B17E2F5003F265F /* NSFileManager+SwiftLint.swift */,
+ E832F10A1B17E2F5003F265F /* FileManager+SwiftLint.swift */,
3BA79C9A1C4767910057E705 /* NSRange+SwiftLint.swift */,
3BB47D841C51D80000AE6A10 /* NSRegularExpression+SwiftLint.swift */,
E81619521BFC162C00946723 /* QueuedPrint.swift */,
@@ -1540,6 +1567,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 8B01E4FD20A41C8700C9233E /* FunctionParameterCountConfiguration.swift in Sources */,
740DF1B1203F62BB0081F694 /* EmptyStringRule.swift in Sources */,
4DB7815E1CAD72BA00BC4723 /* LegacyCGGeometryFunctionsRule.swift in Sources */,
6CC4259B1C77046200AEA885 /* SyntaxMap+SwiftLint.swift in Sources */,
@@ -1550,7 +1578,7 @@
D47079A71DFCEB2D00027086 /* EmptyParenthesesWithTrailingClosureRule.swift in Sources */,
E881985E1BEA982100333A11 /* TypeBodyLengthRule.swift in Sources */,
69F88BF71BDA38A6005E7CAE /* OpeningBraceRule.swift in Sources */,
- C26330382073DAC500D7B4FD /* LowerACLThanBodyRule.swift in Sources */,
+ C26330382073DAC500D7B4FD /* LowerACLThanParentRule.swift in Sources */,
78F032461D7C877E00BE709A /* OverriddenSuperCallRule.swift in Sources */,
E80E018D1B92C0F60078EB70 /* Command.swift in Sources */,
E88198571BEA953300333A11 /* ForceCastRule.swift in Sources */,
@@ -1570,6 +1598,7 @@
3B034B6E1E0BE549005D49A9 /* LineLengthConfiguration.swift in Sources */,
B25DCD0C1F7E9FA20028A199 /* MultilineArgumentsRule.swift in Sources */,
6258783B1FFC458100AC34F2 /* DiscouragedObjectLiteralRule.swift in Sources */,
+ 62A3E95D209E084000547A86 /* EmptyXCTestMethodRule.swift in Sources */,
D4C4A34C1DEA4FF000E0E04C /* AttributesConfiguration.swift in Sources */,
83D71E281B131ECE000395DE /* RuleDescription.swift in Sources */,
D4470D571EB69225008A1B2E /* ImplicitReturnRule.swift in Sources */,
@@ -1590,8 +1619,11 @@
E88198551BEA949A00333A11 /* ControlStatementRule.swift in Sources */,
E57B23C11B1D8BF000DEA512 /* ReturnArrowWhitespaceRule.swift in Sources */,
D4246D6D1F30D8620097E658 /* PrivateOverFilePrivateRuleConfiguration.swift in Sources */,
+ 3A915E5B20A1543700519F3A /* ClosureEndIndentationRuleExamples.swift in Sources */,
629ADD062006302D0009E362 /* DiscouragedOptionalCollectionRule.swift in Sources */,
E816194E1BFBFEAB00946723 /* ForceTryRule.swift in Sources */,
+ 8F2CC1CB20A6A070006ED34F /* FileNameConfiguration.swift in Sources */,
+ D4CFC5D2209EC95A00668488 /* FunctionDefaultParameterAtEndRule.swift in Sources */,
E88198541BEA945100333A11 /* CommaRule.swift in Sources */,
D4DA1DFE1E1A10DB0037413D /* NumberSeparatorConfiguration.swift in Sources */,
E88198601BEA98F000333A11 /* IdentifierNameRule.swift in Sources */,
@@ -1681,7 +1713,7 @@
D4DA1DF41E17511D0037413D /* CompilerProtocolInitRule.swift in Sources */,
629C60D91F43906700B4AF92 /* SingleTestClassRule.swift in Sources */,
621061BF1ED57E640082D51E /* MultilineParametersRuleExamples.swift in Sources */,
- D48AE2CC1DFB58C5001C6A4A /* AttributesRulesExamples.swift in Sources */,
+ D48AE2CC1DFB58C5001C6A4A /* AttributesRuleExamples.swift in Sources */,
E88DEA6F1B09843F00A66CB0 /* Location.swift in Sources */,
D43B046B1E075905004016AF /* ClosureEndIndentationRule.swift in Sources */,
D47EF4821F69E34D0012C4CA /* ColonRule+Dictionary.swift in Sources */,
@@ -1690,7 +1722,7 @@
C328A2F71E6759AE00A9E4D7 /* ExplicitTypeInterfaceRule.swift in Sources */,
93E0C3CE1D67BD7F007FA25D /* ConditionalReturnsOnNewlineRule.swift in Sources */,
D43DB1081DC573DA00281215 /* ImplicitGetterRule.swift in Sources */,
- 62A6E7931F3317E3003A0479 /* JoinedDefaultRule.swift in Sources */,
+ 62A6E7931F3317E3003A0479 /* JoinedDefaultParameterRule.swift in Sources */,
D4FD4C851F2A260A00DD8AA8 /* BlockBasedKVORule.swift in Sources */,
7C0C2E7A1D2866CB0076435A /* ExplicitInitRule.swift in Sources */,
E88DEA771B098D0C00A66CB0 /* Rule.swift in Sources */,
@@ -1699,7 +1731,7 @@
B25DCD0E1F7EF2280028A199 /* MultilineArgumentsConfiguration.swift in Sources */,
24B4DF0D1D6DFDE90097803B /* RedundantNilCoalescingRule.swift in Sources */,
D4130D971E16183F00242361 /* IdentifierNameRuleExamples.swift in Sources */,
- 7250948A1D0859260039B353 /* StatementPositionConfiguration.swift in Sources */,
+ 7250948A1D0859260039B353 /* StatementModeConfiguration.swift in Sources */,
E81619531BFC162C00946723 /* QueuedPrint.swift in Sources */,
E87E4A051BFB927C00FCFE46 /* TrailingSemicolonRule.swift in Sources */,
D4B472411F66486300BD6EF1 /* FallthroughRule.swift in Sources */,
@@ -1735,14 +1767,16 @@
E88DEA6B1B0983FE00A66CB0 /* StyleViolation.swift in Sources */,
62622F6B1F2F2E3500D5D099 /* DiscouragedDirectInitRule.swift in Sources */,
B89F3BCD1FD5EDFB00931E59 /* RequiredEnumCaseRule.swift in Sources */,
+ E83530C61ED6328A00FBAF79 /* FileNameRule.swift in Sources */,
3BB47D831C514E8100AE6A10 /* RegexConfiguration.swift in Sources */,
D401D9261ED85EF0005DA5D4 /* RuleKind.swift in Sources */,
+ 626B01B620A173F100D2C42F /* EmptyXCTestMethodRuleExamples.swift in Sources */,
D4C889711E385B7B00BAE88D /* RedundantDiscardableLetRule.swift in Sources */,
D4D1B9BB1EAC2C910028BE6A /* AccessControlLevel.swift in Sources */,
4A9A3A3A1DC1D75F00DF5183 /* HTMLReporter.swift in Sources */,
D40F83881DE9179200524C62 /* TrailingCommaConfiguration.swift in Sources */,
827169B31F488181003FB9AF /* ExplicitEnumRawValueRule.swift in Sources */,
- 62FE5D32200CABDD00F68793 /* DiscouragedOptionalCollectionRuleExamples.swift in Sources */,
+ 62FE5D32200CABDD00F68793 /* DiscouragedOptionalCollectionExamples.swift in Sources */,
D49896F12026B36C00814A83 /* RedundantSetAccessControlRule.swift in Sources */,
29FFC37A1F15764D007E4825 /* FileLengthRuleConfiguration.swift in Sources */,
ED641C3820AA07B400212C62 /* NoFallthroughOnlyRule.swift in Sources */,
@@ -1753,7 +1787,7 @@
29AD4C661F6EA1D5009B66E1 /* ContainsOverFirstNotNilRule.swift in Sources */,
C946FECB1EAE67EE007DD778 /* LetVarWhitespaceRule.swift in Sources */,
E881985D1BEA97EB00333A11 /* TrailingWhitespaceRule.swift in Sources */,
- E832F10B1B17E2F5003F265F /* NSFileManager+SwiftLint.swift in Sources */,
+ E832F10B1B17E2F5003F265F /* FileManager+SwiftLint.swift in Sources */,
E816194C1BFBF35D00946723 /* SwiftDeclarationKind+SwiftLint.swift in Sources */,
D4DABFD71E2C23B1009617B6 /* NotificationCenterDetachmentRule.swift in Sources */,
3BA79C9B1C4767910057E705 /* NSRange+SwiftLint.swift in Sources */,
@@ -1784,12 +1818,13 @@
buildActionMask = 2147483647;
files = (
825F19D11EEFF19700969EF1 /* ObjectLiteralRuleTests.swift in Sources */,
- 3B12C9C31C320A53000B423F /* Yaml+SwiftLintTests.swift in Sources */,
+ 3B12C9C31C320A53000B423F /* YamlSwiftLintTests.swift in Sources */,
E832F10D1B17E725003F265F /* IntegrationTests.swift in Sources */,
D4C27C001E12DFF500DF713E /* LinterCacheTests.swift in Sources */,
D45255C81F0932F8003C9B56 /* RuleDescription+Examples.swift in Sources */,
E81ADD721ED5ED9D000CD451 /* RegionTests.swift in Sources */,
D4998DE91DF194F20006E05D /* FileHeaderRuleTests.swift in Sources */,
+ 8B01E50220A4349100C9233E /* FunctionParameterCountRuleTests.swift in Sources */,
47ACC89C1E7DCFA00088EEB2 /* ImplicitlyUnwrappedOptionalRuleTests.swift in Sources */,
E81ADD741ED6052F000CD451 /* CommandTests.swift in Sources */,
29FFC37D1F157BDE007E4825 /* FileLengthRuleTests.swift in Sources */,
@@ -1832,6 +1867,7 @@
3B63D46F1E1F09DF0057BE35 /* LineLengthRuleTests.swift in Sources */,
3BCC04D41C502BAB006073C3 /* RuleConfigurationTests.swift in Sources */,
E809EDA31B8A73FB00399043 /* ConfigurationTests.swift in Sources */,
+ 8F2CC1CD20A6A189006ED34F /* FileNameRuleTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1874,7 +1910,7 @@
baseConfigurationReference = D0D1212619E878CC005E4BAA /* Debug.xcconfig */;
buildSettings = {
MACOSX_DEPLOYMENT_TARGET = 10.10;
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -1883,7 +1919,7 @@
baseConfigurationReference = D0D1212819E878CC005E4BAA /* Release.xcconfig */;
buildSettings = {
MACOSX_DEPLOYMENT_TARGET = 10.10;
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Release;
};
@@ -1899,7 +1935,7 @@
INFOPLIST_FILE = "Source/SwiftLintFramework/Supporting Files/Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFramework;
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
WARNING_CFLAGS = (
@@ -1922,7 +1958,7 @@
INFOPLIST_FILE = "Source/SwiftLintFramework/Supporting Files/Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFramework;
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
WARNING_CFLAGS = (
@@ -1940,7 +1976,7 @@
INFOPLIST_FILE = "Tests/SwiftLintFrameworkTests/Supporting Files/Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFrameworkTests;
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -1951,7 +1987,7 @@
INFOPLIST_FILE = "Tests/SwiftLintFrameworkTests/Supporting Files/Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFrameworkTests;
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Release;
};
@@ -1960,7 +1996,7 @@
baseConfigurationReference = D0D1212719E878CC005E4BAA /* Profile.xcconfig */;
buildSettings = {
MACOSX_DEPLOYMENT_TARGET = 10.10;
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Profile;
};
@@ -1976,7 +2012,7 @@
INFOPLIST_FILE = "Source/SwiftLintFramework/Supporting Files/Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFramework;
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
WARNING_CFLAGS = (
@@ -1994,7 +2030,7 @@
INFOPLIST_FILE = "Tests/SwiftLintFrameworkTests/Supporting Files/Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFrameworkTests;
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Profile;
};
@@ -2003,7 +2039,7 @@
baseConfigurationReference = D0D1212919E878CC005E4BAA /* Test.xcconfig */;
buildSettings = {
MACOSX_DEPLOYMENT_TARGET = 10.10;
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Test;
};
@@ -2019,7 +2055,7 @@
INFOPLIST_FILE = "Source/SwiftLintFramework/Supporting Files/Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFramework;
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
WARNING_CFLAGS = (
@@ -2037,7 +2073,7 @@
INFOPLIST_FILE = "Tests/SwiftLintFrameworkTests/Supporting Files/Info.plist";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = SwiftLintFrameworkTests;
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Test;
};
@@ -2049,7 +2085,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks /Library/Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks /Library/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -2061,7 +2097,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks /Library/Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks /Library/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Test;
};
@@ -2073,7 +2109,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks /Library/Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks /Library/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Release;
};
@@ -2085,7 +2121,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks /Library/Frameworks/SwiftLintFramework.framework/Versions/Current/Frameworks /Library/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Profile;
};
diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift
index bae11444312..a3b88116474 100644
--- a/Tests/LinuxMain.swift
+++ b/Tests/LinuxMain.swift
@@ -194,6 +194,19 @@ extension FileLengthRuleTests {
]
}
+extension FileNameRuleTests {
+ static var allTests: [(String, (FileNameRuleTests) -> () throws -> Void)] = [
+ ("testMainDoesntTrigger", testMainDoesntTrigger),
+ ("testLinuxMainDoesntTrigger", testLinuxMainDoesntTrigger),
+ ("testClassNameDoesntTrigger", testClassNameDoesntTrigger),
+ ("testStructNameDoesntTrigger", testStructNameDoesntTrigger),
+ ("testExtensionNameDoesntTrigger", testExtensionNameDoesntTrigger),
+ ("testMisspelledNameDoesTrigger", testMisspelledNameDoesTrigger),
+ ("testMisspelledNameDoesntTriggerWithOverride", testMisspelledNameDoesntTriggerWithOverride),
+ ("testMainDoesTriggerWithoutOverride", testMainDoesTriggerWithoutOverride)
+ ]
+}
+
extension FunctionBodyLengthRuleTests {
static var allTests: [(String, (FunctionBodyLengthRuleTests) -> () throws -> Void)] = [
("testFunctionBodyLengths", testFunctionBodyLengths),
@@ -202,6 +215,13 @@ extension FunctionBodyLengthRuleTests {
]
}
+extension FunctionParameterCountRuleTests {
+ static var allTests: [(String, (FunctionParameterCountRuleTests) -> () throws -> Void)] = [
+ ("testFunctionParameterCount", testFunctionParameterCount),
+ ("testDefaultFunctionParameterCount", testDefaultFunctionParameterCount)
+ ]
+}
+
extension GenericTypeNameRuleTests {
static var allTests: [(String, (GenericTypeNameRuleTests) -> () throws -> Void)] = [
("testGenericTypeName", testGenericTypeName),
@@ -375,8 +395,8 @@ extension RequiredEnumCaseRuleTestCase {
]
}
-extension RuleConfigurationsTests {
- static var allTests: [(String, (RuleConfigurationsTests) -> () throws -> Void)] = [
+extension RuleConfigurationTests {
+ static var allTests: [(String, (RuleConfigurationTests) -> () throws -> Void)] = [
("testNameConfigurationSetsCorrectly", testNameConfigurationSetsCorrectly),
("testNameConfigurationThrowsOnBadConfig", testNameConfigurationThrowsOnBadConfig),
("testNameConfigurationMinLengthThreshold", testNameConfigurationMinLengthThreshold),
@@ -448,6 +468,7 @@ extension RulesTests {
("testLowerACLThanParent", testLowerACLThanParent),
("testEmptyParenthesesWithTrailingClosure", testEmptyParenthesesWithTrailingClosure),
("testEmptyString", testEmptyString),
+ ("testEmptyXCTestMethods", testEmptyXCTestMethods),
("testExplicitACL", testExplicitACL),
("testExplicitEnumRawValue", testExplicitEnumRawValue),
("testExplicitInit", testExplicitInit),
@@ -461,6 +482,7 @@ extension RulesTests {
("testForceUnwrapping", testForceUnwrapping),
("testForWhere", testForWhere),
("testFunctionBodyLength", testFunctionBodyLength),
+ ("testFunctionDefaultParameterAtEnd", testFunctionDefaultParameterAtEnd),
("testFunctionParameterCount", testFunctionParameterCount),
("testImplicitGetter", testImplicitGetter),
("testImplicitlyUnwrappedOptional", testImplicitlyUnwrappedOptional),
@@ -630,7 +652,9 @@ XCTMain([
testCase(ExtendedNSStringTests.allTests),
testCase(FileHeaderRuleTests.allTests),
testCase(FileLengthRuleTests.allTests),
+ testCase(FileNameRuleTests.allTests),
testCase(FunctionBodyLengthRuleTests.allTests),
+ testCase(FunctionParameterCountRuleTests.allTests),
testCase(GenericTypeNameRuleTests.allTests),
testCase(IdentifierNameRuleTests.allTests),
testCase(ImplicitlyUnwrappedOptionalConfigurationTests.allTests),
@@ -647,7 +671,7 @@ XCTMain([
testCase(RegionTests.allTests),
testCase(ReporterTests.allTests),
testCase(RequiredEnumCaseRuleTestCase.allTests),
- testCase(RuleConfigurationsTests.allTests),
+ testCase(RuleConfigurationTests.allTests),
testCase(RuleTests.allTests),
testCase(RulesTests.allTests),
testCase(SourceKitCrashTests.allTests),
diff --git a/Tests/SwiftLintFrameworkTests/FileNameRuleTests.swift b/Tests/SwiftLintFrameworkTests/FileNameRuleTests.swift
new file mode 100644
index 00000000000..840f6fab4c3
--- /dev/null
+++ b/Tests/SwiftLintFrameworkTests/FileNameRuleTests.swift
@@ -0,0 +1,52 @@
+import SourceKittenFramework
+import SwiftLintFramework
+import XCTest
+
+private let fixturesDirectory = #file.bridge()
+ .deletingLastPathComponent.bridge()
+ .appendingPathComponent("Resources/FileNameRuleFixtures")
+
+class FileNameRuleTests: XCTestCase {
+ private func validate(fileName: String, excludedOverride: [String]? = nil) throws -> [StyleViolation] {
+ let file = File(path: fixturesDirectory.stringByAppendingPathComponent(fileName))!
+ let rule: FileNameRule
+ if let excluded = excludedOverride {
+ rule = try FileNameRule(configuration: ["excluded": excluded])
+ } else {
+ rule = FileNameRule()
+ }
+ return rule.validate(file: file)
+ }
+
+ func testMainDoesntTrigger() {
+ XCTAssert(try validate(fileName: "main.swift").isEmpty)
+ }
+
+ func testLinuxMainDoesntTrigger() {
+ XCTAssert(try validate(fileName: "LinuxMain.swift").isEmpty)
+ }
+
+ func testClassNameDoesntTrigger() {
+ XCTAssert(try validate(fileName: "MyClass.swift").isEmpty)
+ }
+
+ func testStructNameDoesntTrigger() {
+ XCTAssert(try validate(fileName: "MyStruct.swift").isEmpty)
+ }
+
+ func testExtensionNameDoesntTrigger() {
+ XCTAssert(try validate(fileName: "NSString+Extension.swift").isEmpty)
+ }
+
+ func testMisspelledNameDoesTrigger() {
+ XCTAssertEqual(try validate(fileName: "MyStructf.swift").count, 1)
+ }
+
+ func testMisspelledNameDoesntTriggerWithOverride() {
+ XCTAssert(try validate(fileName: "MyStructf.swift", excludedOverride: ["MyStructf.swift"]).isEmpty)
+ }
+
+ func testMainDoesTriggerWithoutOverride() {
+ XCTAssertEqual(try validate(fileName: "main.swift", excludedOverride: []).count, 1)
+ }
+}
diff --git a/Tests/SwiftLintFrameworkTests/FunctionParameterCountRuleTests.swift b/Tests/SwiftLintFrameworkTests/FunctionParameterCountRuleTests.swift
new file mode 100644
index 00000000000..388c5802bb9
--- /dev/null
+++ b/Tests/SwiftLintFrameworkTests/FunctionParameterCountRuleTests.swift
@@ -0,0 +1,54 @@
+import SwiftLintFramework
+import XCTest
+
+private func funcWithParameters(_ parameters: String, violates: Bool = false) -> String {
+ let marker = violates ? "↓" : ""
+
+ return "func \(marker)abc(\(parameters)) {}\n"
+}
+
+private func violatingFuncWithParameters(_ parameters: String) -> String {
+ return funcWithParameters(parameters, violates: true)
+}
+
+class FunctionParameterCountRuleTests: XCTestCase {
+
+ func testFunctionParameterCount() {
+ let baseDescription = FunctionParameterCountRule.description
+ let nonTriggeringExamples = [
+ funcWithParameters(repeatElement("x: Int, ", count: 3).joined() + "x: Int")
+ ]
+
+ let triggeringExamples = [
+ funcWithParameters(repeatElement("x: Int, ", count: 5).joined() + "x: Int")
+ ]
+
+ let description = baseDescription.with(nonTriggeringExamples: nonTriggeringExamples)
+ .with(triggeringExamples: triggeringExamples)
+
+ verifyRule(description)
+ }
+
+ func testDefaultFunctionParameterCount() {
+ let baseDescription = FunctionParameterCountRule.description
+ let nonTriggeringExamples = [
+ funcWithParameters(repeatElement("x: Int, ", count: 3).joined() + "x: Int")
+ ]
+
+ let defaultParams = repeatElement("x: Int = 0, ", count: 2).joined() + "x: Int = 0"
+ let triggeringExamples = [
+ funcWithParameters(repeatElement("x: Int, ", count: 3).joined() + defaultParams)
+ ]
+
+ let description = baseDescription.with(nonTriggeringExamples: nonTriggeringExamples)
+ .with(triggeringExamples: triggeringExamples)
+
+ verifyRule(description, ruleConfiguration: ["ignores_default_parameters": false])
+ }
+
+ private func violations(_ string: String) -> [StyleViolation] {
+ let config = makeConfig(nil, FunctionParameterCountRule.description.identifier)!
+
+ return SwiftLintFrameworkTests.violations(string, config: config)
+ }
+}
diff --git a/Tests/SwiftLintFrameworkTests/LinterCacheTests.swift b/Tests/SwiftLintFrameworkTests/LinterCacheTests.swift
index 479d4c4a96f..8286f54567b 100644
--- a/Tests/SwiftLintFrameworkTests/LinterCacheTests.swift
+++ b/Tests/SwiftLintFrameworkTests/LinterCacheTests.swift
@@ -323,6 +323,8 @@ class LinterCacheTests: XCTestCase {
func testDetectSwiftVersion() {
#if swift(>=4.2.0)
let version = "4.2.0"
+ #elseif swift(>=4.1.2)
+ let version = "4.1.2"
#elseif swift(>=4.1.1)
let version = "4.1.1"
#elseif swift(>=4.1.0)
@@ -337,6 +339,8 @@ class LinterCacheTests: XCTestCase {
let version = "4.0.0"
#elseif swift(>=3.4.0)
let version = "4.2.0" // Since we can't pass SWIFT_VERSION=3 to sourcekit, it returns 4.2.0
+ #elseif swift(>=3.3.2)
+ let version = "4.1.2" // Since we can't pass SWIFT_VERSION=3 to sourcekit, it returns 4.1.2
#elseif swift(>=3.3.1)
let version = "4.1.1" // Since we can't pass SWIFT_VERSION=3 to sourcekit, it returns 4.1.1
#elseif swift(>=3.3.0)
diff --git a/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/LinuxMain.swift b/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/LinuxMain.swift
new file mode 100644
index 00000000000..115660e78ef
--- /dev/null
+++ b/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/LinuxMain.swift
@@ -0,0 +1,10 @@
+@testable import SwiftLintFrameworkTests
+import XCTest
+
+extension AttributesRuleTests {
+ static var allTests: [(String, (AttributesRuleTests) -> () throws -> Void)] = [
+ ("testAttributesWithDefaultConfiguration", testAttributesWithDefaultConfiguration),
+ ("testAttributesWithAlwaysOnSameLine", testAttributesWithAlwaysOnSameLine),
+ ("testAttributesWithAlwaysOnLineAbove", testAttributesWithAlwaysOnLineAbove)
+ ]
+}
diff --git a/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/MyClass.swift b/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/MyClass.swift
new file mode 100644
index 00000000000..0463202d419
--- /dev/null
+++ b/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/MyClass.swift
@@ -0,0 +1,2 @@
+struct MyStruct {}
+class MyClass {}
diff --git a/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/MyStruct.swift b/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/MyStruct.swift
new file mode 100644
index 00000000000..0463202d419
--- /dev/null
+++ b/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/MyStruct.swift
@@ -0,0 +1,2 @@
+struct MyStruct {}
+class MyClass {}
diff --git a/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/MyStructf.swift b/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/MyStructf.swift
new file mode 100644
index 00000000000..0463202d419
--- /dev/null
+++ b/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/MyStructf.swift
@@ -0,0 +1,2 @@
+struct MyStruct {}
+class MyClass {}
diff --git a/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/NSString+Extension.swift b/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/NSString+Extension.swift
new file mode 100644
index 00000000000..be7ae4f8230
--- /dev/null
+++ b/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/NSString+Extension.swift
@@ -0,0 +1,6 @@
+struct MyStruct {}
+class MyClass {}
+
+extension NSString {
+ func asdf() {}
+}
diff --git a/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/main.swift b/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/main.swift
new file mode 100644
index 00000000000..990af910329
--- /dev/null
+++ b/Tests/SwiftLintFrameworkTests/Resources/FileNameRuleFixtures/main.swift
@@ -0,0 +1,3 @@
+struct A {}
+
+print("hello")
diff --git a/Tests/SwiftLintFrameworkTests/RuleConfigurationTests.swift b/Tests/SwiftLintFrameworkTests/RuleConfigurationTests.swift
index 68160949e18..21b7cdfe0aa 100644
--- a/Tests/SwiftLintFrameworkTests/RuleConfigurationTests.swift
+++ b/Tests/SwiftLintFrameworkTests/RuleConfigurationTests.swift
@@ -4,7 +4,7 @@ import XCTest
// swiftlint:disable type_body_length
-class RuleConfigurationsTests: XCTestCase {
+class RuleConfigurationTests: XCTestCase {
func testNameConfigurationSetsCorrectly() {
let config = [ "min_length": ["warning": 17, "error": 7],
"max_length": ["warning": 170, "error": 700],
diff --git a/Tests/SwiftLintFrameworkTests/RulesTests.swift b/Tests/SwiftLintFrameworkTests/RulesTests.swift
index a462c5fc2bb..ec82b97ed74 100644
--- a/Tests/SwiftLintFrameworkTests/RulesTests.swift
+++ b/Tests/SwiftLintFrameworkTests/RulesTests.swift
@@ -102,6 +102,10 @@ class RulesTests: XCTestCase {
verifyRule(EmptyStringRule.description)
}
+ func testEmptyXCTestMethods() {
+ verifyRule(EmptyXCTestMethodRule.description)
+ }
+
func testExplicitACL() {
verifyRule(ExplicitACLRule.description)
}
@@ -154,6 +158,10 @@ class RulesTests: XCTestCase {
verifyRule(FunctionBodyLengthRule.description)
}
+ func testFunctionDefaultParameterAtEnd() {
+ verifyRule(FunctionDefaultParameterAtEndRule.description)
+ }
+
func testFunctionParameterCount() {
verifyRule(FunctionParameterCountRule.description)
}
diff --git a/Tests/SwiftLintFrameworkTests/Yaml+SwiftLintTests.swift b/Tests/SwiftLintFrameworkTests/YamlSwiftLintTests.swift
similarity index 100%
rename from Tests/SwiftLintFrameworkTests/Yaml+SwiftLintTests.swift
rename to Tests/SwiftLintFrameworkTests/YamlSwiftLintTests.swift