mirror of
https://github.com/realm/SwiftLint.git
synced 2026-06-06 20:18:40 +00:00
Merge pull request #1091 from marcelofabri/uppercase-enums-swift-2.3
type_name rule validates enum values with Swift 2.3
This commit is contained in:
@@ -42,6 +42,11 @@
|
||||
[Scott Berrevoets](https://github.com/sberrevoets)
|
||||
[#900](https://github.com/realm/SwiftLint/issues/900)
|
||||
|
||||
* `type_name` rule forces enum values to be UpperCamelCase again
|
||||
when used with Swift 2.3.
|
||||
[Marcelo Fabri](https://github.com/marcelofabri)
|
||||
[#1090](https://github.com/realm/SwiftLint/issues/1090)
|
||||
|
||||
* Make `weak_delegate` rule ignore computed properties.
|
||||
[Rafael Machado](https://github.com/rakaramos/)
|
||||
[#1089](https://github.com/realm/SwiftLint/issues/1089)
|
||||
|
||||
@@ -18,59 +18,25 @@ public struct TypeNameRule: ASTRule, ConfigurationProviderRule {
|
||||
|
||||
public init() {}
|
||||
|
||||
private static func nonTriggeringExamples() -> [String] {
|
||||
let types = ["class", "struct", "enum"]
|
||||
let typeExamples: [String] = types.flatMap { (type: String) -> [String] in
|
||||
[
|
||||
"\(type) MyType {}",
|
||||
"private \(type) _MyType {}",
|
||||
"enum MyType {\ncase value\n}",
|
||||
"\(type) \(repeatElement("A", count: 40).joined()) {}"
|
||||
]
|
||||
}
|
||||
let typeAliasAndAssociatedTypeExamples = [
|
||||
"typealias Foo = Void",
|
||||
"private typealias Foo = Void",
|
||||
"protocol Foo {\n associatedtype Bar\n }",
|
||||
"protocol Foo {\n associatedtype Bar: Equatable\n }"
|
||||
]
|
||||
|
||||
return typeExamples + typeAliasAndAssociatedTypeExamples
|
||||
}
|
||||
|
||||
private static func triggeringExamples() -> [String] {
|
||||
let types = ["class", "struct", "enum"]
|
||||
let typeExamples: [String] = types.flatMap { (type: String) -> [String] in
|
||||
[
|
||||
"↓\(type) myType {}",
|
||||
"↓\(type) _MyType {}",
|
||||
"private ↓\(type) MyType_ {}",
|
||||
"↓\(type) My {}",
|
||||
"↓\(type) \(repeatElement("A", count: 41).joined()) {}"
|
||||
]
|
||||
}
|
||||
let typeAliasAndAssociatedTypeExamples: [String] = [
|
||||
"typealias ↓X = Void",
|
||||
"private typealias ↓Foo_Bar = Void",
|
||||
"private typealias ↓foo = Void",
|
||||
"typealias ↓\(repeatElement("A", count: 41).joined()) = Void",
|
||||
"protocol Foo {\n associatedtype ↓X\n }",
|
||||
"protocol Foo {\n associatedtype ↓Foo_Bar: Equatable\n }",
|
||||
"protocol Foo {\n associatedtype ↓\(repeatElement("A", count: 41).joined())\n }"
|
||||
]
|
||||
|
||||
return typeExamples + typeAliasAndAssociatedTypeExamples
|
||||
}
|
||||
|
||||
public static let description = RuleDescription(
|
||||
identifier: "type_name",
|
||||
name: "Type Name",
|
||||
description: "Type name should only contain alphanumeric characters, start with an " +
|
||||
"uppercase character and span between 3 and 40 characters in length.",
|
||||
nonTriggeringExamples: TypeNameRule.nonTriggeringExamples(),
|
||||
triggeringExamples: TypeNameRule.triggeringExamples()
|
||||
nonTriggeringExamples: TypeNameRuleExamples.swift3NonTriggeringExamples,
|
||||
triggeringExamples: TypeNameRuleExamples.swift3TriggeringExamples
|
||||
)
|
||||
|
||||
private let typeKinds: [SwiftDeclarationKind] = {
|
||||
let common = SwiftDeclarationKind.typeKinds()
|
||||
switch SwiftVersion.current {
|
||||
case .two:
|
||||
return common + [.enumelement]
|
||||
case .three:
|
||||
return common
|
||||
}
|
||||
}()
|
||||
|
||||
public func validateFile(_ file: File) -> [StyleViolation] {
|
||||
return validateTypeAliasesAndAssociatedTypes(file) +
|
||||
validateFile(file, dictionary: file.structure.dictionary)
|
||||
@@ -80,7 +46,7 @@ public struct TypeNameRule: ASTRule, ConfigurationProviderRule {
|
||||
kind: SwiftDeclarationKind,
|
||||
dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
|
||||
|
||||
guard SwiftDeclarationKind.typeKinds().contains(kind),
|
||||
guard typeKinds.contains(kind),
|
||||
let name = dictionary["key.name"] as? String,
|
||||
let offset = (dictionary["key.offset"] as? Int64).flatMap({ Int($0) }) else {
|
||||
return []
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// TypeNameRuleExamples.swift
|
||||
// SwiftLint
|
||||
//
|
||||
// Created by Marcelo Fabri on 30/12/16.
|
||||
// Copyright © 2016 Realm. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
internal struct TypeNameRuleExamples {
|
||||
|
||||
static let swift2NonTriggeringExamples = commonNonTriggeringExamples + ["enum MyType {\ncase Value\n}"]
|
||||
|
||||
static let swift3NonTriggeringExamples = commonNonTriggeringExamples + ["enum MyType {\ncase value\n}"]
|
||||
|
||||
static let swift2TriggeringExamples = commonTriggeringExamples + ["enum MyType {\ncase ↓value\n}"]
|
||||
|
||||
static let swift3TriggeringExamples = commonTriggeringExamples
|
||||
|
||||
private static let types = ["class", "struct", "enum"]
|
||||
|
||||
private static let commonNonTriggeringExamples: [String] = {
|
||||
let typeExamples: [String] = types.flatMap { (type: String) -> [String] in
|
||||
[
|
||||
"\(type) MyType {}",
|
||||
"private \(type) _MyType {}",
|
||||
"\(type) \(repeatElement("A", count: 40).joined()) {}"
|
||||
]
|
||||
}
|
||||
let typeAliasAndAssociatedTypeExamples = [
|
||||
"typealias Foo = Void",
|
||||
"private typealias Foo = Void",
|
||||
"protocol Foo {\n associatedtype Bar\n }",
|
||||
"protocol Foo {\n associatedtype Bar: Equatable\n }"
|
||||
]
|
||||
|
||||
return typeExamples + typeAliasAndAssociatedTypeExamples
|
||||
}()
|
||||
|
||||
private static let commonTriggeringExamples: [String] = {
|
||||
let typeExamples: [String] = types.flatMap { (type: String) -> [String] in
|
||||
[
|
||||
"↓\(type) myType {}",
|
||||
"↓\(type) _MyType {}",
|
||||
"private ↓\(type) MyType_ {}",
|
||||
"↓\(type) My {}",
|
||||
"↓\(type) \(repeatElement("A", count: 41).joined()) {}"
|
||||
]
|
||||
}
|
||||
let typeAliasAndAssociatedTypeExamples: [String] = [
|
||||
"typealias ↓X = Void",
|
||||
"private typealias ↓Foo_Bar = Void",
|
||||
"private typealias ↓foo = Void",
|
||||
"typealias ↓\(repeatElement("A", count: 41).joined()) = Void",
|
||||
"protocol Foo {\n associatedtype ↓X\n }",
|
||||
"protocol Foo {\n associatedtype ↓Foo_Bar: Equatable\n }",
|
||||
"protocol Foo {\n associatedtype ↓\(repeatElement("A", count: 41).joined())\n }"
|
||||
]
|
||||
|
||||
return typeExamples + typeAliasAndAssociatedTypeExamples
|
||||
}()
|
||||
}
|
||||
@@ -87,6 +87,7 @@
|
||||
D286EC021E02DF6F0003CF72 /* SortedImportsRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D286EC001E02DA190003CF72 /* SortedImportsRule.swift */; };
|
||||
D40AD08A1E032F9700F48C30 /* UnusedClosureParameterRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40AD0891E032F9700F48C30 /* UnusedClosureParameterRule.swift */; };
|
||||
D40F83881DE9179200524C62 /* TrailingCommaConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40F83871DE9179200524C62 /* TrailingCommaConfiguration.swift */; };
|
||||
D4130D991E16CC1300242361 /* TypeNameRuleExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4130D981E16CC1300242361 /* TypeNameRuleExamples.swift */; };
|
||||
D41E7E0B1DF9DABB0065259A /* RedundantStringEnumValueRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41E7E0A1DF9DABB0065259A /* RedundantStringEnumValueRule.swift */; };
|
||||
D42D2B381E09CC0D00CD7A2E /* FirstWhereRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42D2B371E09CC0D00CD7A2E /* FirstWhereRule.swift */; };
|
||||
D4348EEA1C46122C007707FB /* FunctionBodyLengthRuleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4348EE91C46122C007707FB /* FunctionBodyLengthRuleTests.swift */; };
|
||||
@@ -335,6 +336,7 @@
|
||||
D286EC001E02DA190003CF72 /* SortedImportsRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortedImportsRule.swift; sourceTree = "<group>"; };
|
||||
D40AD0891E032F9700F48C30 /* UnusedClosureParameterRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnusedClosureParameterRule.swift; sourceTree = "<group>"; };
|
||||
D40F83871DE9179200524C62 /* TrailingCommaConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrailingCommaConfiguration.swift; sourceTree = "<group>"; };
|
||||
D4130D981E16CC1300242361 /* TypeNameRuleExamples.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypeNameRuleExamples.swift; sourceTree = "<group>"; };
|
||||
D41E7E0A1DF9DABB0065259A /* RedundantStringEnumValueRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedundantStringEnumValueRule.swift; sourceTree = "<group>"; };
|
||||
D42D2B371E09CC0D00CD7A2E /* FirstWhereRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirstWhereRule.swift; sourceTree = "<group>"; };
|
||||
D4348EE91C46122C007707FB /* FunctionBodyLengthRuleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionBodyLengthRuleTests.swift; sourceTree = "<group>"; };
|
||||
@@ -797,6 +799,7 @@
|
||||
E88DEA851B0991BF00A66CB0 /* TrailingWhitespaceRule.swift */,
|
||||
E88DEA8D1B0999CD00A66CB0 /* TypeBodyLengthRule.swift */,
|
||||
E88DEA911B099B1F00A66CB0 /* TypeNameRule.swift */,
|
||||
D4130D981E16CC1300242361 /* TypeNameRuleExamples.swift */,
|
||||
D40AD0891E032F9700F48C30 /* UnusedClosureParameterRule.swift */,
|
||||
D43B04631E0620AB004016AF /* UnusedEnumeratedRule.swift */,
|
||||
E81CDE701C00FEAA00B430F6 /* ValidDocsRule.swift */,
|
||||
@@ -1136,6 +1139,7 @@
|
||||
1EC163521D5992D900DD2928 /* VerticalWhitespaceRule.swift in Sources */,
|
||||
57ED827B1CF656E3002B3513 /* JUnitReporter.swift in Sources */,
|
||||
D43B04691E072291004016AF /* ColonConfiguration.swift in Sources */,
|
||||
D4130D991E16CC1300242361 /* TypeNameRuleExamples.swift in Sources */,
|
||||
24E17F721B14BB3F008195BE /* File+Cache.swift in Sources */,
|
||||
009E09281DFEE4C200B588A7 /* ProhibitedSuperRule.swift in Sources */,
|
||||
E80E018F1B92C1350078EB70 /* Region.swift in Sources */,
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
<Test
|
||||
Identifier = "RulesTests/testNumberSeparator()">
|
||||
</Test>
|
||||
<Test
|
||||
Identifier = "RulesTests/testTypeName()">
|
||||
</Test>
|
||||
</SkippedTests>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
|
||||
@@ -12,6 +12,18 @@ import XCTest
|
||||
#if !SWIFT_PACKAGE
|
||||
class Swift2RulesTests: XCTestCase {
|
||||
|
||||
func testAttributes() {
|
||||
let description = RuleDescription(
|
||||
identifier: AttributesRule.description.identifier,
|
||||
name: AttributesRule.description.name,
|
||||
description: AttributesRule.description.description,
|
||||
nonTriggeringExamples: AttributesRuleExamples.swift2NonTriggeringExamples,
|
||||
triggeringExamples: AttributesRuleExamples.swift2TriggeringExamples
|
||||
)
|
||||
|
||||
verifyRule(description)
|
||||
}
|
||||
|
||||
func testNumberSeparator() {
|
||||
let description = RuleDescription(
|
||||
identifier: NumberSeparatorRule.description.identifier,
|
||||
@@ -25,13 +37,13 @@ class Swift2RulesTests: XCTestCase {
|
||||
verifyRule(description)
|
||||
}
|
||||
|
||||
func testAttributes() {
|
||||
func testTypeName() {
|
||||
let description = RuleDescription(
|
||||
identifier: AttributesRule.description.identifier,
|
||||
name: AttributesRule.description.name,
|
||||
description: AttributesRule.description.description,
|
||||
nonTriggeringExamples: AttributesRuleExamples.swift2NonTriggeringExamples,
|
||||
triggeringExamples: AttributesRuleExamples.swift2TriggeringExamples
|
||||
identifier: TypeNameRule.description.identifier,
|
||||
name: TypeNameRule.description.name,
|
||||
description: TypeNameRule.description.description,
|
||||
nonTriggeringExamples: TypeNameRuleExamples.swift2NonTriggeringExamples,
|
||||
triggeringExamples: TypeNameRuleExamples.swift2TriggeringExamples
|
||||
)
|
||||
|
||||
verifyRule(description)
|
||||
|
||||
Reference in New Issue
Block a user