Add rule for single space after period on comments (#4624)
This commit is contained in:
parent
33fa42becb
commit
3745704c03
|
@ -48,6 +48,7 @@ opt_in_rules:
|
|||
- overridden_super_call
|
||||
- override_in_extension
|
||||
- pattern_matching_keywords
|
||||
- period_spacing
|
||||
- prefer_self_type_over_type_of_self
|
||||
- private_action
|
||||
- private_outlet
|
||||
|
|
|
@ -49,6 +49,11 @@
|
|||
`single_test_class` and `empty_xctest_method` rules.
|
||||
[Martin Redington](https://github.com/mildm8nnered)
|
||||
[#4200](https://github.com/realm/SwiftLint/issues/4200)
|
||||
|
||||
* Add `period_spacing` opt-in rule that checks periods are not followed
|
||||
by 2 or more spaces in comments.
|
||||
[Julioacarrettoni](https://github.com/Julioacarrettoni)
|
||||
[#4624](https://github.com/realm/SwiftLint/pull/4624)
|
||||
|
||||
* Show warnings in the console for Analyzer rules that are listed in the
|
||||
`opt_in_rules` configuration section.
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import IDEUtils
|
||||
|
||||
extension SyntaxClassification {
|
||||
// True if it is any kind of comment.
|
||||
var isComment: Bool {
|
||||
switch self {
|
||||
case .lineComment, .docLineComment, .blockComment, .docBlockComment:
|
||||
return true
|
||||
case .none, .keyword, .identifier, .typeIdentifier, .operatorIdentifier, .dollarIdentifier, .integerLiteral,
|
||||
.floatingLiteral, .stringLiteral, .stringInterpolationAnchor, .poundDirectiveKeyword, .buildConfigId,
|
||||
.attribute, .objectLiteral, .editorPlaceholder:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -137,6 +137,7 @@ public let primaryRuleList = RuleList(rules: [
|
|||
OverriddenSuperCallRule.self,
|
||||
OverrideInExtensionRule.self,
|
||||
PatternMatchingKeywordsRule.self,
|
||||
PeriodSpacingRule.self,
|
||||
PreferNimbleRule.self,
|
||||
PreferSelfInStaticReferencesRule.self,
|
||||
PreferSelfTypeOverTypeOfSelfRule.self,
|
||||
|
|
|
@ -122,15 +122,9 @@ struct CommentSpacingRule: SourceKitFreeRule, ConfigurationProviderRule, Substit
|
|||
func violationRanges(in file: SwiftLintFile) -> [NSRange] {
|
||||
// Find all comment tokens in the file and regex search them for violations
|
||||
file.syntaxClassifications
|
||||
.compactMap { (classifiedRange: SyntaxClassifiedRange) -> [NSRange]? in
|
||||
switch classifiedRange.kind {
|
||||
case .blockComment, .docBlockComment, .lineComment, .docLineComment:
|
||||
break
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
let range = classifiedRange.range.toSourceKittenByteRange()
|
||||
.filter(\.kind.isComment)
|
||||
.map { $0.range.toSourceKittenByteRange() }
|
||||
.compactMap { (range: ByteRange) -> [NSRange]? in
|
||||
return file.stringView
|
||||
.substringWithByteRange(range)
|
||||
.map(StringView.init)
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
import Foundation
|
||||
import IDEUtils
|
||||
import SourceKittenFramework
|
||||
|
||||
struct PeriodSpacingRule: SourceKitFreeRule, ConfigurationProviderRule, OptInRule, SubstitutionCorrectableRule {
|
||||
var configuration = SeverityConfiguration(.warning)
|
||||
|
||||
init() {}
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "period_spacing",
|
||||
name: "Period Spacing",
|
||||
description: "Periods should not be followed by more than one space.",
|
||||
kind: .style,
|
||||
nonTriggeringExamples: [
|
||||
Example("let pi = 3.2"),
|
||||
Example("let pi = Double.pi"),
|
||||
Example("let pi = Double. pi"),
|
||||
Example("let pi = Double. pi"),
|
||||
Example("// A. Single."),
|
||||
Example("/// - code: Identifier of the error. Integer."),
|
||||
Example("""
|
||||
// value: Multiline.
|
||||
// Comment.
|
||||
"""),
|
||||
Example("""
|
||||
/**
|
||||
Sentence ended in period.
|
||||
|
||||
- Sentence 2 new line characters after.
|
||||
**/
|
||||
""")
|
||||
],
|
||||
triggeringExamples: [
|
||||
Example("/* Only god knows why. ↓ This symbol does nothing. */", testWrappingInComment: false),
|
||||
Example("// Only god knows why. ↓ This symbol does nothing.", testWrappingInComment: false),
|
||||
Example("// Single. Double. ↓ End.", testWrappingInComment: false),
|
||||
Example("// Single. Double. ↓ Triple. ↓ End.", testWrappingInComment: false),
|
||||
Example("// Triple. ↓ Quad. ↓ End.", testWrappingInComment: false),
|
||||
Example("/// - code: Identifier of the error. ↓ Integer.", testWrappingInComment: false)
|
||||
],
|
||||
corrections: [
|
||||
Example("/* Why. ↓ Symbol does nothing. */"): Example("/* Why. Symbol does nothing. */"),
|
||||
Example("// Why. ↓ Symbol does nothing."): Example("// Why. Symbol does nothing."),
|
||||
Example("// Single. Double. ↓ End."): Example("// Single. Double. End."),
|
||||
Example("// Single. Double. ↓ Triple. ↓ End."): Example("// Single. Double. Triple. End."),
|
||||
Example("// Triple. ↓ Quad. ↓ End."): Example("// Triple. Quad. End."),
|
||||
Example("/// - code: Identifier. ↓ Integer."): Example("/// - code: Identifier. Integer.")
|
||||
]
|
||||
)
|
||||
|
||||
func violationRanges(in file: SwiftLintFile) -> [NSRange] {
|
||||
// Find all comment tokens in the file and regex search them for violations
|
||||
file.syntaxClassifications
|
||||
.filter(\.kind.isComment)
|
||||
.map { $0.range.toSourceKittenByteRange() }
|
||||
.compactMap { (range: ByteRange) -> [NSRange]? in
|
||||
return file.stringView
|
||||
.substringWithByteRange(range)
|
||||
.map(StringView.init)
|
||||
.map { commentBody in
|
||||
// Look for a period followed by two or more whitespaces but not new line or carriage returns
|
||||
return regex(#"\.[^\S\r\n]{2,}"#)
|
||||
.matches(in: commentBody)
|
||||
.compactMap { result in
|
||||
// Set the location to start from the second whitespace till the last one.
|
||||
return file.stringView.byteRangeToNSRange(
|
||||
ByteRange(
|
||||
// Safe to mix NSRange offsets with byte offsets here because the
|
||||
// regex can't contain multi-byte characters
|
||||
location: ByteCount(range.lowerBound.value + result.range.lowerBound + 2),
|
||||
length: ByteCount(result.range.length.advanced(by: -2))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.flatMap { $0 }
|
||||
}
|
||||
|
||||
func validate(file: SwiftLintFile) -> [StyleViolation] {
|
||||
return violationRanges(in: file).map { range in
|
||||
StyleViolation(
|
||||
ruleDescription: Self.description,
|
||||
severity: configuration.severity,
|
||||
location: Location(file: file, characterOffset: range.location)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func substitution(for violationRange: NSRange, in file: SwiftLintFile) -> (NSRange, String)? {
|
||||
return (violationRange, "")
|
||||
}
|
||||
}
|
|
@ -811,6 +811,12 @@ class PatternMatchingKeywordsRuleGeneratedTests: XCTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
class PeriodSpacingRuleGeneratedTests: XCTestCase {
|
||||
func testWithDefaultConfiguration() {
|
||||
verifyRule(PeriodSpacingRule.description)
|
||||
}
|
||||
}
|
||||
|
||||
class PreferNimbleRuleGeneratedTests: XCTestCase {
|
||||
func testWithDefaultConfiguration() {
|
||||
verifyRule(PreferNimbleRule.description)
|
||||
|
|
Loading…
Reference in New Issue