Fix false positives related to multiline strings in `indentation_width` rule (#4862)

This commit is contained in:
Sven Münnich 2023-04-04 19:27:16 +02:00 committed by GitHub
parent bd444fcd77
commit a2facce70c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 15 deletions

View File

@ -29,6 +29,9 @@
[SimplyDanny](https://github.com/SimplyDanny)
[#4860](https://github.com/realm/SwiftLint/issues/4860)
* Fix false positives in `indentation_width` rule.
[Sven Münnich](https://github.com/svenmuennich)
## 0.51.0: bzllint
#### Breaking

View File

@ -172,10 +172,21 @@ struct IndentationWidthRule: ConfigurationProviderRule, OptInRule {
if configuration.includeMultilineStrings {
return false
}
if file.syntaxMap.tokens(inByteRange: line.byteRange).kinds == [.string] {
return true
// A multiline string content line is characterized by beginning with a token of kind string whose range's lower
// bound is smaller than that of the line itself.
let tokensInLine = file.syntaxMap.tokens(inByteRange: line.byteRange)
guard
let firstToken = tokensInLine.first,
firstToken.kind == .string,
firstToken.range.lowerBound < line.byteRange.lowerBound else {
return false
}
return false
// Closing delimiters of a multiline string should follow the defined indentation. The Swift compiler requires
// those delimiters to be on their own line so we need to consider the number of tokens as well as the upper
// bounds.
return tokensInLine.count > 1 || line.byteRange.upperBound < firstToken.range.upperBound
}
/// Validates whether the indentation of a specific line is valid based on the indentation of the previous line.

View File

@ -196,18 +196,57 @@ class IndentationWidthRuleTests: XCTestCase {
""", includeCompilerDirectives: true)
}
func testIgnoredMultilineStrings() {
assertNoViolation(
in: "let x = \"\"\"\nstring1\n string2\n string3\n\"\"\"\n",
includeMultilineStrings: false
)
assert1Violation(
in: "let x = \"\"\"\nstring1\n string2\n string3\n\"\"\"\n"
)
assertViolations(
in: "let x = \"\"\"\nstring1\n string2\n string3\n string4\n\"\"\"\n",
equals: 2
)
func testIncludeMultilineStrings() {
let example0 = #"""
let x = """
string1
string2
string3
"""
"""#
assertNoViolation(in: example0, includeMultilineStrings: false)
assert1Violation(in: example0, includeMultilineStrings: true)
let example1 = #"""
let x = """
string1
string2
string3
string4
"""
"""#
assertNoViolation(in: example1, includeMultilineStrings: false)
assertViolations(in: example1, equals: 2, includeMultilineStrings: true)
let example2 = ##"""
let x = #"""
string1
"""#
"""##
assert1Violation(in: example2, includeMultilineStrings: false)
assert1Violation(in: example2, includeMultilineStrings: true)
let example3 = """
let x = [
"key": [
["nestedKey": "string"],
],
]
"""
assertNoViolation(in: example3, includeMultilineStrings: false)
assertNoViolation(in: example3, includeMultilineStrings: true)
let example4 = #"""
func test() -> String {
"""
Type:
- property: \(123) + \(456)
\(true)
"""
}
"""#
assertNoViolation(in: example4, includeMultilineStrings: false)
assert1Violation(in: example4, includeMultilineStrings: true)
}
// MARK: Helpers