mirror of
https://github.com/nicklockwood/SwiftFormat.git
synced 2026-05-17 10:30:35 +00:00
Update --self-required to support assignment type names like OSLogMessage (#2448)
Co-authored-by: calda <1811727+calda@users.noreply.github.com>
This commit is contained in:
@@ -2888,7 +2888,7 @@ Insert/remove explicit `self` where applicable.
|
||||
Option | Description
|
||||
--- | ---
|
||||
`--self` | Explicit self: "insert", "remove" (default) or "init-only"
|
||||
`--self-required` | Comma-delimited list of functions with @autoclosure arguments
|
||||
`--self-required` | Comma-delimited list of functions / types with @autoclosure arguments
|
||||
|
||||
<details>
|
||||
<summary>Examples</summary>
|
||||
|
||||
@@ -130,10 +130,59 @@ extension Formatter {
|
||||
}
|
||||
index = scopeStart
|
||||
}
|
||||
if !staticSelf,
|
||||
isAssignedToSelfRequiredType(at: index)
|
||||
{
|
||||
return false
|
||||
}
|
||||
removeTokens(in: i ..< nextIndex)
|
||||
return true
|
||||
}
|
||||
|
||||
/// Whether the expression at the given index is on the RHS of an assignment
|
||||
/// whose LHS has a type annotation matching a `selfRequired` type.
|
||||
/// e.g. `let _: OSLogMessage = "\(self.bar)"` or `let _: OSLogMessage = foo(self.bar)`
|
||||
func isAssignedToSelfRequiredType(at i: Int) -> Bool {
|
||||
guard !options.selfRequired.isEmpty else { return false }
|
||||
// Walk backwards from start of expression to find `=` operator
|
||||
var index = i
|
||||
while let prevIndex = self.index(of: .nonSpaceOrCommentOrLinebreak, before: index) {
|
||||
if tokens[prevIndex] == .operator("=", .infix) {
|
||||
return isSelfRequiredType(beforeAssignment: prevIndex)
|
||||
}
|
||||
switch tokens[prevIndex] {
|
||||
case .identifier, .operator(".", .infix),
|
||||
.keyword("try"), .keyword("await"),
|
||||
.operator("?", .postfix), .operator("!", .postfix):
|
||||
index = prevIndex
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/// Whether the type annotation before an `=` operator is a `selfRequired` type.
|
||||
func isSelfRequiredType(beforeAssignment equalsIndex: Int) -> Bool {
|
||||
var typeIndex = equalsIndex
|
||||
while let prevTypeIndex = index(of: .nonSpaceOrCommentOrLinebreak, before: typeIndex) {
|
||||
if tokens[prevTypeIndex].isUnwrapOperator {
|
||||
typeIndex = prevTypeIndex
|
||||
} else if tokens[prevTypeIndex] == .endOfScope(">"),
|
||||
let matchingStart = startOfScope(at: prevTypeIndex)
|
||||
{
|
||||
typeIndex = matchingStart
|
||||
} else {
|
||||
typeIndex = prevTypeIndex
|
||||
break
|
||||
}
|
||||
}
|
||||
guard tokens[typeIndex].isIdentifier else {
|
||||
return false
|
||||
}
|
||||
return options.selfRequired.contains(tokens[typeIndex].unescaped())
|
||||
}
|
||||
|
||||
/// gather declared variable names, starting at index after let/var keyword
|
||||
func processDeclaredVariables(at index: inout Int, names: inout Set<String>,
|
||||
removeSelfKeyword: String?, onlyLocal: Bool,
|
||||
|
||||
@@ -838,7 +838,7 @@ struct _Descriptors {
|
||||
let selfRequired = OptionDescriptor(
|
||||
argumentName: "self-required",
|
||||
displayName: "Self Required",
|
||||
help: "Comma-delimited list of functions with @autoclosure arguments",
|
||||
help: "Comma-delimited list of functions / types with @autoclosure arguments",
|
||||
keyPath: \FormatOptions.selfRequired
|
||||
)
|
||||
let throwCapturing = OptionDescriptor(
|
||||
|
||||
@@ -879,6 +879,111 @@ final class RedundantSelfTests: XCTestCase {
|
||||
testFormatting(for: input, rule: .redundantSelf, options: options, exclude: [.propertyTypes])
|
||||
}
|
||||
|
||||
func testNoRemoveSelfInStringInterpolationWithSelfRequiredTypeAnnotation() {
|
||||
let input = """
|
||||
class C {
|
||||
let bar = NSObject()
|
||||
func f() {
|
||||
let _: OSLogMessage = "\\(self.bar)"
|
||||
}
|
||||
}
|
||||
"""
|
||||
let options = FormatOptions(selfRequired: ["OSLogMessage"])
|
||||
testFormatting(for: input, rule: .redundantSelf, options: options,
|
||||
exclude: [.propertyTypes])
|
||||
}
|
||||
|
||||
func testNoRemoveSelfInStringInterpolationWithOptionalSelfRequiredTypeAnnotation() {
|
||||
let input = """
|
||||
class C {
|
||||
let bar = NSObject()
|
||||
func f() {
|
||||
let x: OSLogMessage? = "\\(self.bar)"
|
||||
}
|
||||
}
|
||||
"""
|
||||
let options = FormatOptions(selfRequired: ["OSLogMessage"])
|
||||
testFormatting(for: input, rule: .redundantSelf, options: options,
|
||||
exclude: [.propertyTypes])
|
||||
}
|
||||
|
||||
func testRemoveSelfInStringInterpolationWithNonSelfRequiredTypeAnnotation() {
|
||||
let input = """
|
||||
class C {
|
||||
let bar = "test"
|
||||
func f() {
|
||||
let x: String = "\\(self.bar)"
|
||||
}
|
||||
}
|
||||
"""
|
||||
let output = """
|
||||
class C {
|
||||
let bar = "test"
|
||||
func f() {
|
||||
let x: String = "\\(bar)"
|
||||
}
|
||||
}
|
||||
"""
|
||||
testFormatting(for: input, output, rule: .redundantSelf,
|
||||
exclude: [.propertyTypes, .redundantType])
|
||||
}
|
||||
|
||||
func testNoRemoveSelfInFunctionCallWithSelfRequiredTypeAnnotation() {
|
||||
let input = """
|
||||
class C {
|
||||
let bar = NSObject()
|
||||
func f() {
|
||||
let _: OSLogMessage = foo(self.bar)
|
||||
}
|
||||
}
|
||||
"""
|
||||
let options = FormatOptions(selfRequired: ["OSLogMessage"])
|
||||
testFormatting(for: input, rule: .redundantSelf, options: options,
|
||||
exclude: [.propertyTypes])
|
||||
}
|
||||
|
||||
func testNoRemoveSelfInMethodChainWithSelfRequiredTypeAnnotation() {
|
||||
let input = """
|
||||
class C {
|
||||
let bar = NSObject()
|
||||
func f() {
|
||||
let _: OSLogMessage = Foo.bar(self.bar)
|
||||
}
|
||||
}
|
||||
"""
|
||||
let options = FormatOptions(selfRequired: ["OSLogMessage"])
|
||||
testFormatting(for: input, rule: .redundantSelf, options: options,
|
||||
exclude: [.propertyTypes])
|
||||
}
|
||||
|
||||
func testNoRemoveSelfInDirectAssignmentWithSelfRequiredTypeAnnotation() {
|
||||
let input = """
|
||||
class C {
|
||||
let bar = NSObject()
|
||||
func f() {
|
||||
let _: OSLogMessage = self.bar
|
||||
}
|
||||
}
|
||||
"""
|
||||
let options = FormatOptions(selfRequired: ["OSLogMessage"])
|
||||
testFormatting(for: input, rule: .redundantSelf, options: options,
|
||||
exclude: [.propertyTypes])
|
||||
}
|
||||
|
||||
func testNoRemoveSelfInSelfRequiredTypeInitializer() {
|
||||
let input = """
|
||||
class C {
|
||||
let bar = NSObject()
|
||||
func f() {
|
||||
let msg = OSLogMessage(self.bar)
|
||||
}
|
||||
}
|
||||
"""
|
||||
let options = FormatOptions(selfRequired: ["OSLogMessage"])
|
||||
testFormatting(for: input, rule: .redundantSelf, options: options,
|
||||
exclude: [.propertyTypes])
|
||||
}
|
||||
|
||||
func testSelfRemovedFromSwitchCaseWhere() {
|
||||
let input = """
|
||||
class Foo {
|
||||
|
||||
Reference in New Issue
Block a user