From 2039ee6b7bc1cfdc85e2011e5b3dcdf9f0e3473a Mon Sep 17 00:00:00 2001 From: Ornithologist Coder Date: Fri, 5 Jan 2018 06:48:54 +0100 Subject: [PATCH] Improves 'let' keyword validation --- Rules.md | 22 +++++++++ .../Rules/PrefixedTopLevelConstantRule.swift | 49 ++++++++++++++++--- 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/Rules.md b/Rules.md index 3cded3e54..e7e936554 100644 --- a/Rules.md +++ b/Rules.md @@ -9012,6 +9012,19 @@ internal var foo = "Foo" var foo = true ``` +```swift +var foo = true, bar = true +``` + +```swift +var foo = true, let kFoo = true +``` + +```swift +let + kFoo = true +``` +
Triggering Examples @@ -9036,6 +9049,15 @@ let ↓Foo = true let ↓foo = 2, ↓bar = true ``` +```swift +var foo = true, let ↓Foo = true +``` + +```swift +let + ↓foo = true +``` +
diff --git a/Source/SwiftLintFramework/Rules/PrefixedTopLevelConstantRule.swift b/Source/SwiftLintFramework/Rules/PrefixedTopLevelConstantRule.swift index 11038e7c6..f69fe9db5 100644 --- a/Source/SwiftLintFramework/Rules/PrefixedTopLevelConstantRule.swift +++ b/Source/SwiftLintFramework/Rules/PrefixedTopLevelConstantRule.swift @@ -12,6 +12,8 @@ import SourceKittenFramework public struct PrefixedTopLevelConstantRule: ASTRule, OptInRule, ConfigurationProviderRule { public var configuration = SeverityConfiguration(.warning) + private let topLevelPrefix = "k" + public init() {} public static let description = RuleDescription( @@ -30,14 +32,21 @@ public struct PrefixedTopLevelConstantRule: ASTRule, OptInRule, ConfigurationPro "private var foo = 20.0", "public var foo = false", "internal var foo = \"Foo\"", - "var foo = true" + "var foo = true", + "var foo = true, bar = true", + "var foo = true, let kFoo = true", + "let\n" + + " kFoo = true" ], triggeringExamples: [ "private let ↓Foo = 20.0", "public let ↓Foo = false", "internal let ↓Foo = \"Foo\"", "let ↓Foo = true", - "let ↓foo = 2, ↓bar = true" + "let ↓foo = 2, ↓bar = true", + "var foo = true, let ↓Foo = true", + "let\n" + + " ↓foo = true" ] ) @@ -48,15 +57,39 @@ public struct PrefixedTopLevelConstantRule: ASTRule, OptInRule, ConfigurationPro kind == .varGlobal, let offset = dictionary.offset, let nameOffset = dictionary.nameOffset, - let name = dictionary.name, - let content = file.contents.bridge().substringWithByteRange(start: offset, length: nameOffset - offset), - content.hasPrefix("let") && !name.hasPrefix("k") + let name = dictionary.name else { return [] } - return [StyleViolation(ruleDescription: type(of: self).description, - severity: configuration.severity, - location: Location(file: file, byteOffset: nameOffset))] + let range = NSRange(location: offset, length: nameOffset - offset) + + guard isDeclaredAsConstant(in: range, on: file) && !name.hasPrefix(topLevelPrefix) else { + return [] + } + + return [ + StyleViolation(ruleDescription: type(of: self).description, + severity: configuration.severity, + location: Location(file: file, byteOffset: nameOffset)) + ] + } + + private func isDeclaredAsConstant(in range: NSRange, on file: File) -> Bool { + let tokens = file.syntaxMap.tokens(inByteRange: range) + let contents = file.contents.bridge() + + let letKeywords = tokens.filter { token in + guard + SyntaxKind(rawValue: token.type) == .keyword, + let keyword = contents.substringWithByteRange(start: token.offset, length: token.length) + else { + return false + } + + return keyword == "let" + } + + return !letKeywords.isEmpty } }