Add new option to `attributes` rule to influence it for attributes with arguments (#4855)
This commit is contained in:
parent
f0138ea1df
commit
7756793356
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -2,7 +2,14 @@
|
|||
|
||||
#### Breaking
|
||||
|
||||
* None.
|
||||
* The `attributes` rule now expects attributes with arguments to be placed
|
||||
on their own line above the declaration they are supposed to influence.
|
||||
This applies to attributes with any kinds of arguments including single
|
||||
key path arguments which were previously handled in a different way. This
|
||||
behavior can be turned off by setting `attributes_with_arguments_always_on_line_above`
|
||||
to `false.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#4843](https://github.com/realm/SwiftLint/issues/4843)
|
||||
|
||||
#### Experimental
|
||||
|
||||
|
@ -59,6 +66,14 @@
|
|||
[whiteio](https://github.com/whiteio)
|
||||
[#4923](https://github.com/realm/SwiftLint/issues/4923)
|
||||
|
||||
* The `attributes` rule received a new boolean option
|
||||
`attributes_with_arguments_always_on_line_above` which is `true` by default.
|
||||
Setting it to `false` ensures that attributes with arguments like
|
||||
`@Persisted(primaryKey: true)` don't violate the rule if they are on the same
|
||||
line with the variable declaration.
|
||||
[SimplyDanny](https://github.com/SimplyDanny)
|
||||
[#4843](https://github.com/realm/SwiftLint/issues/4843)
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* Fix `lower_acl_than_parent` rule rewriter by preserving leading whitespace.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
struct AttributesConfiguration: SeverityBasedRuleConfiguration, Equatable {
|
||||
var severityConfiguration = SeverityConfiguration(.warning)
|
||||
private(set) var attributesWithArgumentsAlwaysOnNewLine = true
|
||||
private(set) var alwaysOnSameLine = Set<String>()
|
||||
private(set) var alwaysOnNewLine = Set<String>()
|
||||
|
||||
|
@ -20,6 +21,11 @@ struct AttributesConfiguration: SeverityBasedRuleConfiguration, Equatable {
|
|||
throw ConfigurationError.unknownConfiguration
|
||||
}
|
||||
|
||||
if let attributesWithArgumentsAlwaysOnNewLine
|
||||
= configuration["attributes_with_arguments_always_on_line_above"] as? Bool {
|
||||
self.attributesWithArgumentsAlwaysOnNewLine = attributesWithArgumentsAlwaysOnNewLine
|
||||
}
|
||||
|
||||
if let alwaysOnSameLine = configuration["always_on_same_line"] as? [String] {
|
||||
self.alwaysOnSameLine = Set(alwaysOnSameLine)
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ private extension AttributeListSyntax {
|
|||
return (attribute, .sameLineAsDeclaration)
|
||||
} else if configuration.alwaysOnNewLine.contains(atPrefixedName) {
|
||||
return (attribute, .dedicatedLine)
|
||||
} else if attribute.argument != nil {
|
||||
} else if attribute.argument != nil, configuration.attributesWithArgumentsAlwaysOnNewLine {
|
||||
return (attribute, .dedicatedLine)
|
||||
}
|
||||
|
||||
|
@ -165,20 +165,9 @@ private extension AttributeListSyntax {
|
|||
}
|
||||
}
|
||||
|
||||
var hasAttributeWithKeypathArgument: Bool {
|
||||
contains { element in
|
||||
switch element {
|
||||
case .attribute(let attribute):
|
||||
return attribute.hasKeypathArgument
|
||||
case .ifConfigDecl:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:disable:next cyclomatic_complexity
|
||||
func makeHelper(locationConverter: SourceLocationConverter) -> RuleHelper? {
|
||||
guard let parent, !hasAttributeWithKeypathArgument else {
|
||||
guard let parent else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -226,9 +215,3 @@ private extension AttributeListSyntax {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
private extension AttributeSyntax {
|
||||
var hasKeypathArgument: Bool {
|
||||
argument?.as(TupleExprElementListSyntax.self)?.first?.expression.is(KeyPathExprSyntax.self) == true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,15 +82,15 @@ internal struct AttributesRuleExamples {
|
|||
final class AppDelegate: NSAppDelegate {}
|
||||
"""),
|
||||
Example(#"""
|
||||
@_spi(Private) import SomeFramework
|
||||
|
||||
@_spi(Private)
|
||||
final class MyView: View {
|
||||
@SwiftUI.Environment(\.colorScheme) var colorScheme: ColorScheme
|
||||
@SwiftUI.Environment(\.colorScheme) var first: ColorScheme
|
||||
@Environment(\.colorScheme) var second: ColorScheme
|
||||
@Persisted(primaryKey: true) var id: Int
|
||||
}
|
||||
"""#),
|
||||
Example(#"""
|
||||
final class MyView: View {
|
||||
@Environment(\.colorScheme) var colorScheme: ColorScheme
|
||||
}
|
||||
"""#)
|
||||
"""#, configuration: ["attributes_with_arguments_always_on_line_above": false], excludeFromDocumentation: true)
|
||||
]
|
||||
|
||||
static let triggeringExamples = [
|
||||
|
@ -124,6 +124,16 @@ internal struct AttributesRuleExamples {
|
|||
Example("@GKInspectable\n ↓var maxSpeed: Float"),
|
||||
Example("@discardableResult ↓func a() -> Int"),
|
||||
Example("@objc\n @discardableResult ↓func a() -> Int"),
|
||||
Example("@objc\n\n @discardableResult\n ↓func a() -> Int")
|
||||
Example("@objc\n\n @discardableResult\n ↓func a() -> Int"),
|
||||
Example(#"""
|
||||
struct S: View {
|
||||
@Environment(\.colorScheme) ↓var first: ColorScheme
|
||||
@Persisted var id: Int
|
||||
@FetchRequest(
|
||||
animation: nil
|
||||
)
|
||||
var entities: FetchedResults
|
||||
}
|
||||
"""#, excludeFromDocumentation: true)
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue