Skip to content

Commit

Permalink
Add nested type handling specification to file_name rule (#2718)
Browse files Browse the repository at this point in the history
* Add nestedTypeSeparator to FileNameConfiguration

* Add tests for nested_type_separator configurability of file_name rule

* Add changelog entry

* Fix changelog position after rebase
  • Loading branch information
fredpi authored and jpsim committed Apr 30, 2019
1 parent 9be5a97 commit 3b9917f
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 4 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
swift test --filter testSimulateHomebrewTest
```
[Norio Nomura](https://github.com/norio-nomura)
* Add option to configure how nested types should be separated in file names by
introducting `nested_type_separator` configuration for the `file_name` rule.
[Frederick Pietschmann](https://github.com/fredpi)
[#2717](https://github.com/realm/SwiftLint/issues/2717)

#### Bug Fixes

Expand Down
11 changes: 9 additions & 2 deletions Source/SwiftLintFramework/Rules/Idiomatic/FileNameRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public struct FileNameRule: ConfigurationProviderRule, OptInRule {
severity: .warning,
excluded: ["main.swift", "LinuxMain.swift"],
prefixPattern: "",
suffixPattern: "\\+.*"
suffixPattern: "\\+.*",
nestedTypeSeparator: "."
)

public init() {}
Expand All @@ -43,17 +44,23 @@ public struct FileNameRule: ConfigurationProviderRule, OptInRule {

var typeInFileName = fileName.bridge().deletingPathExtension

// Process prefix
if let match = prefixRegex.firstMatch(in: typeInFileName, options: [], range: typeInFileName.fullNSRange),
let range = typeInFileName.nsrangeToIndexRange(match.range) {
typeInFileName.removeSubrange(range)
}

// Process suffix
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()
// Process nested type separator
let allDeclaredTypeNames = file.structure.dictionary.recursiveDeclaredTypeNames().map {
$0.replacingOccurrences(of: ".", with: configuration.nestedTypeSeparator)
}

guard !allDeclaredTypeNames.isEmpty, !allDeclaredTypeNames.contains(typeInFileName) else {
return []
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ public struct FileNameConfiguration: RuleConfiguration, Equatable {
private(set) public var excluded: Set<String>
private(set) public var prefixPattern: String
private(set) public var suffixPattern: String
private(set) public var nestedTypeSeparator: String

public init(severity: ViolationSeverity, excluded: [String] = [],
prefixPattern: String = "", suffixPattern: String = "\\+.*") {
prefixPattern: String = "", suffixPattern: String = "\\+.*", nestedTypeSeparator: String = ".") {
self.severity = SeverityConfiguration(severity)
self.excluded = Set(excluded)
self.prefixPattern = prefixPattern
self.suffixPattern = suffixPattern
self.nestedTypeSeparator = nestedTypeSeparator
}

public mutating func apply(configuration: Any) throws {
Expand All @@ -34,5 +36,8 @@ public struct FileNameConfiguration: RuleConfiguration, Equatable {
if let suffixPattern = configurationDict["suffix_pattern"] as? String {
self.suffixPattern = suffixPattern
}
if let nestedTypeSeparator = configurationDict["nested_type_separator"] as? String {
self.nestedTypeSeparator = nestedTypeSeparator
}
}
}
2 changes: 2 additions & 0 deletions Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,8 @@ extension FileNameRuleTests {
("testStructNameDoesntTrigger", testStructNameDoesntTrigger),
("testExtensionNameDoesntTrigger", testExtensionNameDoesntTrigger),
("testNestedExtensionDoesntTrigger", testNestedExtensionDoesntTrigger),
("testNestedTypeSeparatorDoesntTrigger", testNestedTypeSeparatorDoesntTrigger),
("testWrongNestedTypeSeparatorDoesTrigger", testWrongNestedTypeSeparatorDoesTrigger),
("testMisspelledNameDoesTrigger", testMisspelledNameDoesTrigger),
("testMisspelledNameDoesntTriggerWithOverride", testMisspelledNameDoesntTriggerWithOverride),
("testMainDoesTriggerWithoutOverride", testMainDoesTriggerWithoutOverride),
Expand Down
16 changes: 15 additions & 1 deletion Tests/SwiftLintFrameworkTests/FileNameRuleTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ private let fixturesDirectory = #file.bridge()

class FileNameRuleTests: XCTestCase {
private func validate(fileName: String, excludedOverride: [String]? = nil,
prefixPattern: String? = nil, suffixPattern: String? = nil) throws -> [StyleViolation] {
prefixPattern: String? = nil, suffixPattern: String? = nil,
nestedTypeSeparator: String? = nil) throws -> [StyleViolation] {
let file = File(path: fixturesDirectory.stringByAppendingPathComponent(fileName))!
let rule: FileNameRule
if let excluded = excludedOverride {
Expand All @@ -19,9 +20,12 @@ class FileNameRuleTests: XCTestCase {
rule = try FileNameRule(configuration: ["prefix_pattern": prefixPattern])
} else if let suffixPattern = suffixPattern {
rule = try FileNameRule(configuration: ["suffix_pattern": suffixPattern])
} else if let nestedTypeSeparator = nestedTypeSeparator {
rule = try FileNameRule(configuration: ["nested_type_separator": nestedTypeSeparator])
} else {
rule = FileNameRule()
}

return rule.validate(file: file)
}

Expand Down Expand Up @@ -49,6 +53,16 @@ class FileNameRuleTests: XCTestCase {
XCTAssert(try validate(fileName: "Notification.Name+Extension.swift").isEmpty)
}

func testNestedTypeSeparatorDoesntTrigger() {
XCTAssert(try validate(fileName: "NotificationName+Extension.swift", nestedTypeSeparator: "").isEmpty)
XCTAssert(try validate(fileName: "Notification__Name+Extension.swift", nestedTypeSeparator: "__").isEmpty)
}

func testWrongNestedTypeSeparatorDoesTrigger() {
XCTAssert(try !validate(fileName: "Notification__Name+Extension.swift", nestedTypeSeparator: ".").isEmpty)
XCTAssert(try !validate(fileName: "NotificationName+Extension.swift", nestedTypeSeparator: "__").isEmpty)
}

func testMisspelledNameDoesTrigger() {
XCTAssertEqual(try validate(fileName: "MyStructf.swift").count, 1)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Foundation

extension Notification.Name {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import Foundation

extension Notification.Name {
}

0 comments on commit 3b9917f

Please sign in to comment.