Skip to content

Commit b2180c4

Browse files
committed
Fix renaming enum case parameters with unnamed associated arguments
We treated enum case parameters the same way as function parameters and weren’t considering that they can be unlabeled. That caused us to insert eg. `_ ` in front of the case’s type, producing `case myCase(_ String)`, which is invalid. Report `enumCaseParameters` as a special parameter kind so that sourcekitd can work with it. swiftlang/sourcekit-lsp#1228
1 parent 4d300ac commit b2180c4

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

Sources/SwiftIDEUtils/DeclNameLocation.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ public struct DeclNameLocation: Equatable {
102102
/// The parameter of a function declaration, like `func foo(a b: Int)`
103103
case parameters([Argument])
104104

105+
/// An enum case declaration like `case myCase(label: String)`.
106+
///
107+
/// For enum case parameters the argument label is removed when set to empty instead of being changed to eg.
108+
/// `myCase(_ label: String)`
109+
case enumCaseParameters([Argument])
110+
105111
/// Same as `param` but the parameters can't be collapsed if they are the same. This is the case for subscript
106112
/// declarations.
107113
///
@@ -123,6 +129,8 @@ public struct DeclNameLocation: Equatable {
123129
)
124130
case .parameters(let parameters):
125131
return .parameters(parameters.map { $0.advanced(by: utf8Offset) })
132+
case .enumCaseParameters(let parameters):
133+
return .enumCaseParameters(parameters.map { $0.advanced(by: utf8Offset) })
126134
case .noncollapsibleParameters(let parameters):
127135
return .noncollapsibleParameters(parameters.map { $0.advanced(by: utf8Offset) })
128136
case .selector(let arguments):

Sources/SwiftIDEUtils/NameMatcher.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ public class NameMatcher: SyntaxAnyVisitor {
298298
return .unlabeled(argument: Syntax(argument.secondName) ?? Syntax(argument.colon) ?? Syntax(argument.type))
299299
}
300300
}
301-
addResolvedLocIfRequested(baseName: node.name, argumentLabels: .parameters(argumentLabels))
301+
addResolvedLocIfRequested(baseName: node.name, argumentLabels: .enumCaseParameters(argumentLabels))
302302
}
303303
return .visitChildren
304304
}

Tests/SwiftIDEUtilsTest/NameMatcherTests.swift

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ private func assertNameMatcherResult(
5151
case .noArguments: argumentLabels = []
5252
case .call(let labels, _): argumentLabels = labels
5353
case .parameters(let labels): argumentLabels = labels
54+
case .enumCaseParameters(let labels): argumentLabels = labels
5455
case .noncollapsibleParameters(let labels): argumentLabels = labels
5556
case .selector(let labels): argumentLabels = labels
5657
}
@@ -75,6 +76,7 @@ private struct DeclNameLocationSpec {
7576
case noArguments
7677
case call
7778
case parameters
79+
case enumCaseParameters
7880
case noncollapsibleParameters
7981
case selector
8082

@@ -83,6 +85,7 @@ private struct DeclNameLocationSpec {
8385
case .noArguments: self = .noArguments
8486
case .call: self = .call
8587
case .parameters: self = .parameters
88+
case .enumCaseParameters: self = .enumCaseParameters
8689
case .noncollapsibleParameters: self = .noncollapsibleParameters
8790
case .selector: self = .selector
8891
}
@@ -326,4 +329,56 @@ class NameMatcherTests: XCTestCase {
326329
]
327330
)
328331
}
332+
333+
func testEnumCaseParameterWithLabels() {
334+
assertNameMatcherResult(
335+
"""
336+
enum MyEnum {
337+
case 1️⃣myCase(label: String)
338+
}
339+
""",
340+
expected: [
341+
DeclNameLocationSpec(baseName: "myCase", argumentLabels: ["label"], type: .enumCaseParameters)
342+
]
343+
)
344+
}
345+
346+
func testEnumCaseParameterWithoutLabels() {
347+
assertNameMatcherResult(
348+
"""
349+
enum MyEnum {
350+
case 1️⃣myCase(String)
351+
}
352+
""",
353+
expected: [
354+
DeclNameLocationSpec(baseName: "myCase", argumentLabels: [""], type: .enumCaseParameters)
355+
]
356+
)
357+
}
358+
359+
func testEnumCaseParameterWithoutAssociatedValues() {
360+
assertNameMatcherResult(
361+
"""
362+
enum MyEnum {
363+
case 1️⃣myCase
364+
}
365+
""",
366+
expected: [
367+
DeclNameLocationSpec(baseName: "myCase", argumentLabels: [], type: .noArguments)
368+
]
369+
)
370+
}
371+
372+
func testEnumCaseParameterWithoutWildcardAsExternalLabel() {
373+
assertNameMatcherResult(
374+
"""
375+
enum MyEnum {
376+
case 1️⃣myCase(_ label: String)
377+
}
378+
""",
379+
expected: [
380+
DeclNameLocationSpec(baseName: "myCase", argumentLabels: ["_ label"], type: .enumCaseParameters)
381+
]
382+
)
383+
}
329384
}

0 commit comments

Comments
 (0)