Add `include_multiline_strings` option to `indentation_width` rule (#4785)

This commit is contained in:
Martin Redington 2023-02-26 10:52:29 +00:00 committed by GitHub
parent 04791929a7
commit d73d87ac97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 4 deletions

View File

@ -24,7 +24,7 @@
* Make forceExclude work with directly specified files. * Make forceExclude work with directly specified files.
[jimmya](https://github.com/jimmya) [jimmya](https://github.com/jimmya)
[#issue_number](https://github.com/realm/SwiftLint/issues/4609) [#4609](https://github.com/realm/SwiftLint/issues/4609)
* Separate analyzer rules as an independent section in the rule directory of * Separate analyzer rules as an independent section in the rule directory of
the reference. the reference.
@ -87,6 +87,10 @@
[Martin Redington](https://github.com/mildm8nnered) [Martin Redington](https://github.com/mildm8nnered)
[#4767](https://github.com/realm/SwiftLint/issues/4767) [#4767](https://github.com/realm/SwiftLint/issues/4767)
* Adds `include_multiline_strings` option to `indentation_width` rule.
[Martin Redington](https://github.com/mildm8nnered)
[#4248](https://github.com/realm/SwiftLint/issues/4248)
#### Bug Fixes #### Bug Fixes
* Report violations in all `<scope>_length` rules when the error threshold is * Report violations in all `<scope>_length` rules when the error threshold is

View File

@ -4,23 +4,27 @@ struct IndentationWidthConfiguration: RuleConfiguration, Equatable {
+ "indentation_width: \(indentationWidth), " + "indentation_width: \(indentationWidth), "
+ "include_comments: \(includeComments), " + "include_comments: \(includeComments), "
+ "include_compiler_directives: \(includeCompilerDirectives)" + "include_compiler_directives: \(includeCompilerDirectives)"
+ "include_multiline_strings: \(includeMultilineStrings)"
} }
private(set) var severityConfiguration: SeverityConfiguration private(set) var severityConfiguration: SeverityConfiguration
private(set) var indentationWidth: Int private(set) var indentationWidth: Int
private(set) var includeComments: Bool private(set) var includeComments: Bool
private(set) var includeCompilerDirectives: Bool private(set) var includeCompilerDirectives: Bool
private(set) var includeMultilineStrings: Bool
init( init(
severity: ViolationSeverity, severity: ViolationSeverity,
indentationWidth: Int, indentationWidth: Int,
includeComments: Bool, includeComments: Bool,
includeCompilerDirectives: Bool includeCompilerDirectives: Bool,
includeMultilineStrings: Bool
) { ) {
self.severityConfiguration = SeverityConfiguration(severity) self.severityConfiguration = SeverityConfiguration(severity)
self.indentationWidth = indentationWidth self.indentationWidth = indentationWidth
self.includeComments = includeComments self.includeComments = includeComments
self.includeCompilerDirectives = includeCompilerDirectives self.includeCompilerDirectives = includeCompilerDirectives
self.includeMultilineStrings = includeMultilineStrings
} }
mutating func apply(configuration: Any) throws { mutating func apply(configuration: Any) throws {
@ -43,5 +47,9 @@ struct IndentationWidthConfiguration: RuleConfiguration, Equatable {
if let includeCompilerDirectives = configurationDict["include_compiler_directives"] as? Bool { if let includeCompilerDirectives = configurationDict["include_compiler_directives"] as? Bool {
self.includeCompilerDirectives = includeCompilerDirectives self.includeCompilerDirectives = includeCompilerDirectives
} }
if let includeMultilineStrings = configurationDict["include_multiline_strings"] as? Bool {
self.includeMultilineStrings = includeMultilineStrings
}
} }
} }

View File

@ -20,7 +20,8 @@ struct IndentationWidthRule: ConfigurationProviderRule, OptInRule {
severity: .warning, severity: .warning,
indentationWidth: 4, indentationWidth: 4,
includeComments: true, includeComments: true,
includeCompilerDirectives: true includeCompilerDirectives: true,
includeMultilineStrings: true
) )
static let description = RuleDescription( static let description = RuleDescription(
identifier: "indentation_width", identifier: "indentation_width",
@ -58,7 +59,7 @@ struct IndentationWidthRule: ConfigurationProviderRule, OptInRule {
let indentationCharacterCount = line.content.countOfLeadingCharacters(in: CharacterSet(charactersIn: " \t")) let indentationCharacterCount = line.content.countOfLeadingCharacters(in: CharacterSet(charactersIn: " \t"))
if line.content.count == indentationCharacterCount { continue } if line.content.count == indentationCharacterCount { continue }
if ignoreComment(line: line, in: file) { continue } if ignoreComment(line: line, in: file) || ignoreMultilineStrings(line: line, in: file) { continue }
// Get space and tab count in prefix // Get space and tab count in prefix
let prefix = String(line.content.prefix(indentationCharacterCount)) let prefix = String(line.content.prefix(indentationCharacterCount))
@ -167,6 +168,16 @@ struct IndentationWidthRule: ConfigurationProviderRule, OptInRule {
return false return false
} }
private func ignoreMultilineStrings(line: Line, in file: SwiftLintFile) -> Bool {
if configuration.includeMultilineStrings {
return false
}
if file.syntaxMap.tokens(inByteRange: line.byteRange).kinds == [.string] {
return true
}
return false
}
/// Validates whether the indentation of a specific line is valid based on the indentation of the previous line. /// Validates whether the indentation of a specific line is valid based on the indentation of the previous line.
/// ///
/// - parameter indentation: The indentation of the line to validate. /// - parameter indentation: The indentation of the line to validate.

View File

@ -196,12 +196,27 @@ class IndentationWidthRuleTests: XCTestCase {
""", includeCompilerDirectives: true) """, 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
)
}
// MARK: Helpers // MARK: Helpers
private func countViolations( private func countViolations(
in example: Example, in example: Example,
indentationWidth: Int? = nil, indentationWidth: Int? = nil,
includeComments: Bool? = nil, includeComments: Bool? = nil,
includeCompilerDirectives: Bool? = nil, includeCompilerDirectives: Bool? = nil,
includeMultilineStrings: Bool? = nil,
file: StaticString = #file, file: StaticString = #file,
line: UInt = #line line: UInt = #line
) -> Int { ) -> Int {
@ -215,6 +230,9 @@ class IndentationWidthRuleTests: XCTestCase {
if let includeCompilerDirectives { if let includeCompilerDirectives {
configDict["include_compiler_directives"] = includeCompilerDirectives configDict["include_compiler_directives"] = includeCompilerDirectives
} }
if let includeMultilineStrings {
configDict["include_multiline_strings"] = includeMultilineStrings
}
guard let config = makeConfig(configDict, IndentationWidthRule.description.identifier) else { guard let config = makeConfig(configDict, IndentationWidthRule.description.identifier) else {
XCTFail("Unable to create rule configuration.", file: (file), line: line) XCTFail("Unable to create rule configuration.", file: (file), line: line)
@ -230,6 +248,7 @@ class IndentationWidthRuleTests: XCTestCase {
indentationWidth: Int? = nil, indentationWidth: Int? = nil,
includeComments: Bool? = nil, includeComments: Bool? = nil,
includeCompilerDirectives: Bool? = nil, includeCompilerDirectives: Bool? = nil,
includeMultilineStrings: Bool? = nil,
file: StaticString = #file, file: StaticString = #file,
line: UInt = #line line: UInt = #line
) { ) {
@ -239,6 +258,7 @@ class IndentationWidthRuleTests: XCTestCase {
indentationWidth: indentationWidth, indentationWidth: indentationWidth,
includeComments: includeComments, includeComments: includeComments,
includeCompilerDirectives: includeCompilerDirectives, includeCompilerDirectives: includeCompilerDirectives,
includeMultilineStrings: includeMultilineStrings,
file: file, file: file,
line: line line: line
), ),
@ -253,6 +273,7 @@ class IndentationWidthRuleTests: XCTestCase {
indentationWidth: Int? = nil, indentationWidth: Int? = nil,
includeComments: Bool? = nil, includeComments: Bool? = nil,
includeCompilerDirectives: Bool? = nil, includeCompilerDirectives: Bool? = nil,
includeMultilineStrings: Bool? = nil,
file: StaticString = #file, file: StaticString = #file,
line: UInt = #line line: UInt = #line
) { ) {
@ -262,6 +283,7 @@ class IndentationWidthRuleTests: XCTestCase {
indentationWidth: indentationWidth, indentationWidth: indentationWidth,
includeComments: includeComments, includeComments: includeComments,
includeCompilerDirectives: includeCompilerDirectives, includeCompilerDirectives: includeCompilerDirectives,
includeMultilineStrings: includeMultilineStrings,
file: file, file: file,
line: line line: line
) )
@ -272,6 +294,7 @@ class IndentationWidthRuleTests: XCTestCase {
indentationWidth: Int? = nil, indentationWidth: Int? = nil,
includeComments: Bool? = nil, includeComments: Bool? = nil,
includeCompilerDirectives: Bool? = nil, includeCompilerDirectives: Bool? = nil,
includeMultilineStrings: Bool? = nil,
file: StaticString = #file, file: StaticString = #file,
line: UInt = #line line: UInt = #line
) { ) {
@ -281,6 +304,7 @@ class IndentationWidthRuleTests: XCTestCase {
indentationWidth: indentationWidth, indentationWidth: indentationWidth,
includeComments: includeComments, includeComments: includeComments,
includeCompilerDirectives: includeCompilerDirectives, includeCompilerDirectives: includeCompilerDirectives,
includeMultilineStrings: includeMultilineStrings,
file: file, file: file,
line: line line: line
) )