Improve violation message for attributes rule (#5108)

This commit is contained in:
Christian Panetta
2023-07-15 15:47:11 +02:00
committed by GitHub
parent 991827e5da
commit bf8edaaeff
2 changed files with 71 additions and 7 deletions
@@ -46,12 +46,30 @@ private extension AttributesRule {
let hasViolation = helper.hasViolation(
locationConverter: locationConverter,
attributesAndPlacements: attributesAndPlacements
attributesAndPlacements: attributesAndPlacements,
attributesWithArgumentsAlwaysOnNewLine: configuration.attributesWithArgumentsAlwaysOnNewLine
)
if hasViolation {
switch hasViolation {
case .argumentsAlwaysOnNewLineViolation:
let reason = """
Attributes with arguments or inside always_on_line_above must be on a new line \
instead of the same line
"""
violations.append(
ReasonedRuleViolation(
position: helper.violationPosition,
reason: reason,
severity: configuration.severityConfiguration.severity
)
)
return
case .violation:
violations.append(helper.violationPosition)
return
case .noViolation:
break
}
let linesForAttributes = attributesAndPlacements
@@ -112,6 +130,12 @@ private enum AttributePlacement {
case dedicatedLine
}
private enum Violation {
case argumentsAlwaysOnNewLineViolation
case noViolation
case violation
}
private struct RuleHelper {
let violationPosition: AbsolutePosition
let keywordLine: Int
@@ -119,8 +143,9 @@ private struct RuleHelper {
func hasViolation(
locationConverter: SourceLocationConverter,
attributesAndPlacements: [(AttributeSyntax, AttributePlacement)]
) -> Bool {
attributesAndPlacements: [(AttributeSyntax, AttributePlacement)],
attributesWithArgumentsAlwaysOnNewLine: Bool
) -> (Violation) {
var linesWithAttributes: Set<Int> = [keywordLine]
for (attribute, placement) in attributesAndPlacements {
guard let attributeStartLine = attribute.startLine(locationConverter: locationConverter) else {
@@ -130,18 +155,22 @@ private struct RuleHelper {
switch placement {
case .sameLineAsDeclaration:
if attributeStartLine != keywordLine {
return true
return .violation
}
case .dedicatedLine:
let hasViolation = attributeStartLine == keywordLine ||
linesWithAttributes.contains(attributeStartLine)
linesWithAttributes.insert(attributeStartLine)
if hasViolation {
return true
if attributesWithArgumentsAlwaysOnNewLine && shouldBeOnSameLine {
return .argumentsAlwaysOnNewLineViolation
} else {
return .violation
}
}
}
}
return false
return .noViolation
}
}
@@ -95,4 +95,39 @@ class AttributesRuleTests: SwiftLintTestCase {
ruleConfiguration: ["always_on_same_line": ["@discardableResult", "@objc",
"@IBAction", "@IBDesignable"]])
}
func testAttributesWithArgumentsAlwaysOnLineAboveFalse() {
let nonTriggeringExamples = [
Example("@Environment(\\.presentationMode) private var presentationMode")
]
let triggeringExamples = [
Example("""
@Environment(\\.presentationMode)
private ↓var presentationMode
""")
]
let argumentsAlwaysOnLineDescription = AttributesRule.description
.with(triggeringExamples: triggeringExamples)
.with(nonTriggeringExamples: nonTriggeringExamples)
verifyRule(argumentsAlwaysOnLineDescription,
ruleConfiguration: ["attributes_with_arguments_always_on_line_above": false])
}
func testAttributesWithArgumentsAlwaysOnLineAboveTrue() {
let nonTriggeringExamples = [
Example("@Environment(\\.presentationMode)\nprivate var presentationMode")
]
let triggeringExamples = [
Example("@Environment(\\.presentationMode) private ↓var presentationMode")
]
let argumentsAlwaysOnLineDescription = AttributesRule.description
.with(triggeringExamples: triggeringExamples)
.with(nonTriggeringExamples: nonTriggeringExamples)
verifyRule(argumentsAlwaysOnLineDescription,
ruleConfiguration: ["attributes_with_arguments_always_on_line_above": true])
}
}