Merge pull request #2310 from Dschee/file-name

Add options `prefix_pattern` and `suffix_pattern` to `file_name` rule
This commit is contained in:
Marcelo Fabri
2018-07-24 09:46:28 -07:00
committed by GitHub
11 changed files with 115 additions and 5 deletions
+4
View File
@@ -22,6 +22,10 @@
`class` for class-only protocols.
[Ornithologist Coder](https://github.com/ornithocoder)
[#2283](https://github.com/realm/SwiftLint/issues/2283)
* Add options `prefix_pattern` and `suffix_pattern` to rule `file_name`.
[Cihat Gündüz](https://github.com/Dschee)
[#2309](https://github.com/realm/SwiftLint/issues/2309)
* Add new bool config option `if_only` to rule `conditional_returns_on_newline`
to specify that the rule should only be applied to `if` statements.
@@ -71,6 +71,10 @@ extension String {
return fromIndex..<toIndex
}
internal var fullNSRange: NSRange {
return NSRange(location: 0, length: utf16.count)
}
public func absolutePathStandardized() -> String {
return bridge().absolutePathRepresentation().bridge().standardizingPath
}
@@ -15,7 +15,12 @@ private extension Dictionary where Key: ExpressibleByStringLiteral {
}
public struct FileNameRule: ConfigurationProviderRule, OptInRule {
public var configuration = FileNameConfiguration(severity: .warning, excluded: ["main.swift", "LinuxMain.swift"])
public var configuration = FileNameConfiguration(
severity: .warning,
excluded: ["main.swift", "LinuxMain.swift"],
prefixPattern: "",
suffixPattern: "\\+.*"
)
public init() {}
@@ -33,7 +38,20 @@ public struct FileNameRule: ConfigurationProviderRule, OptInRule {
return []
}
let typeInFileName = fileName.components(separatedBy: CharacterSet(charactersIn: "+.")).first ?? fileName
let prefixRegex = regex("\\A\(configuration.prefixPattern)")
let suffixRegex = regex("\(configuration.suffixPattern)\\z")
var typeInFileName = fileName.components(separatedBy: ".").first ?? fileName
if let match = prefixRegex.firstMatch(in: typeInFileName, options: [], range: typeInFileName.fullNSRange),
let range = typeInFileName.nsrangeToIndexRange(match.range) {
typeInFileName.removeSubrange(range)
}
if let match = suffixRegex.firstMatch(in: typeInFileName, options: [], range: typeInFileName.fullNSRange),
let range = typeInFileName.nsrangeToIndexRange(match.range) {
typeInFileName.removeSubrange(range)
}
let allDeclaredTypeNames = file.structure.dictionary.recursiveDeclaredTypeNames()
guard !allDeclaredTypeNames.isEmpty, !allDeclaredTypeNames.contains(typeInFileName) else {
@@ -6,10 +6,15 @@ public struct FileNameConfiguration: RuleConfiguration, Equatable {
private(set) public var severity: SeverityConfiguration
private(set) public var excluded: Set<String>
private(set) public var prefixPattern: String
private(set) public var suffixPattern: String
public init(severity: ViolationSeverity, excluded: [String] = []) {
public init(severity: ViolationSeverity, excluded: [String] = [],
prefixPattern: String = "", suffixPattern: String = "\\+.*") {
self.severity = SeverityConfiguration(severity)
self.excluded = Set(excluded)
self.prefixPattern = prefixPattern
self.suffixPattern = suffixPattern
}
public mutating func apply(configuration: Any) throws {
@@ -23,10 +28,18 @@ public struct FileNameConfiguration: RuleConfiguration, Equatable {
if let excluded = [String].array(of: configurationDict["excluded"]) {
self.excluded = Set(excluded)
}
if let prefixPattern = configurationDict["prefix_pattern"] as? String {
self.prefixPattern = prefixPattern
}
if let suffixPattern = configurationDict["suffix_pattern"] as? String {
self.suffixPattern = suffixPattern
}
}
}
public func == (lhs: FileNameConfiguration, rhs: FileNameConfiguration) -> Bool {
return lhs.severity == rhs.severity &&
lhs.excluded == rhs.excluded
lhs.excluded == rhs.excluded &&
lhs.prefixPattern == rhs.prefixPattern &&
lhs.suffixPattern == rhs.suffixPattern
}
@@ -7,11 +7,18 @@ private let fixturesDirectory = #file.bridge()
.appendingPathComponent("Resources/FileNameRuleFixtures")
class FileNameRuleTests: XCTestCase {
private func validate(fileName: String, excludedOverride: [String]? = nil) throws -> [StyleViolation] {
private func validate(fileName: String, excludedOverride: [String]? = nil,
prefixPattern: String? = nil, suffixPattern: 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 if let prefixPattern = prefixPattern, let suffixPattern = suffixPattern {
rule = try FileNameRule(configuration: ["prefix_pattern": prefixPattern, "suffix_pattern": suffixPattern])
} else if let prefixPattern = prefixPattern {
rule = try FileNameRule(configuration: ["prefix_pattern": prefixPattern])
} else if let suffixPattern = suffixPattern {
rule = try FileNameRule(configuration: ["suffix_pattern": suffixPattern])
} else {
rule = FileNameRule()
}
@@ -49,4 +56,32 @@ class FileNameRuleTests: XCTestCase {
func testMainDoesTriggerWithoutOverride() {
XCTAssertEqual(try validate(fileName: "main.swift", excludedOverride: []).count, 1)
}
func testCustomSuffixPattern() {
XCTAssert(try validate(fileName: "BoolExtension.swift", suffixPattern: "Extensions?").isEmpty)
XCTAssert(try validate(fileName: "BoolExtensions.swift", suffixPattern: "Extensions?").isEmpty)
}
func testCustomPrefixPattern() {
XCTAssert(try validate(fileName: "ExtensionBool.swift", prefixPattern: "Extensions?").isEmpty)
XCTAssert(try validate(fileName: "ExtensionsBool.swift", prefixPattern: "Extensions?").isEmpty)
}
func testCustomPrefixAndSuffixPatterns() {
XCTAssert(
try validate(
fileName: "SLBoolExtension.swift",
prefixPattern: "SL",
suffixPattern: "Extensions?|\\+.*"
).isEmpty
)
XCTAssert(
try validate(
fileName: "ExtensionBool+SwiftLint.swift",
prefixPattern: "Extensions?",
suffixPattern: "Extensions?|\\+.*"
).isEmpty
)
}
}
@@ -0,0 +1,6 @@
struct MyStruct {}
class MyClass {}
extension Bool {
func toggle() {}
}
@@ -0,0 +1,6 @@
struct MyStruct {}
class MyClass {}
extension Bool {
func toggle() {}
}
@@ -0,0 +1,6 @@
struct MyStruct {}
class MyClass {}
extension Bool {
func toggle() {}
}
@@ -0,0 +1,6 @@
struct MyStruct {}
class MyClass {}
extension Bool {
func toggle() {}
}
@@ -0,0 +1,6 @@
struct MyStruct {}
class MyClass {}
extension Bool {
func toggle() {}
}
@@ -0,0 +1,6 @@
struct MyStruct {}
class MyClass {}
extension Bool {
func toggle() {}
}