Skip to content

Commit 7a61ff9

Browse files
committed
Adjust test cases for fixed enum case rename
Enum case rename is fixed by changes in sourcekitd. We can remove our workaround for the issue and add test cases that test the rename behavior. Fixes #1228 rdar://127646036
1 parent 76a0db7 commit 7a61ff9

File tree

3 files changed

+125
-45
lines changed

3 files changed

+125
-45
lines changed

Sources/SKTestSupport/SkipUnless.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,31 @@ public actor SkipUnless {
156156
}
157157
}
158158

159+
/// Checks whether the sourcekitd contains a fix to rename labels of enum cases correctly
160+
/// (https://github.com/apple/swift/pull/74241).
161+
public static func sourcekitdCanRenameEnumCaseLabels(
162+
file: StaticString = #filePath,
163+
line: UInt = #line
164+
) async throws {
165+
return try await shared.skipUnlessSupportedByToolchain(swiftVersion: SwiftVersion(6, 0), file: file, line: line) {
166+
let testClient = try await TestSourceKitLSPClient()
167+
let uri = DocumentURI(for: .swift)
168+
let positions = testClient.openDocument(
169+
"""
170+
enum MyEnum {
171+
case 1️⃣myCase(2️⃣String)
172+
}
173+
""",
174+
uri: uri
175+
)
176+
177+
let renameResult = try await testClient.send(
178+
RenameRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1️⃣"], newName: "myCase(label:)")
179+
)
180+
return renameResult?.changes == [uri: [TextEdit(range: Range(positions["2️⃣"]), newText: "label: ")]]
181+
}
182+
}
183+
159184
/// Whether clangd has support for the `workspace/indexedRename` request.
160185
public static func clangdSupportsIndexBasedRename(
161186
file: StaticString = #filePath,

Sources/SourceKitLSP/Rename.swift

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,24 +1003,6 @@ extension SwiftLanguageService {
10031003
return nil
10041004
}
10051005

1006-
/// Returns `true` if the given position is inside an `EnumCaseDeclSyntax`.
1007-
fileprivate func isInsideEnumCaseDecl(position: Position, snapshot: DocumentSnapshot) async -> Bool {
1008-
let syntaxTree = await syntaxTreeManager.syntaxTree(for: snapshot)
1009-
var node = Syntax(syntaxTree.token(at: snapshot.absolutePosition(of: position)))
1010-
1011-
while let parent = node?.parent {
1012-
if parent.is(EnumCaseDeclSyntax.self) {
1013-
return true
1014-
}
1015-
if parent.is(MemberBlockItemSyntax.self) || parent.is(CodeBlockItemSyntax.self) {
1016-
// `MemberBlockItemSyntax` and `CodeBlockItemSyntax` can't be nested inside an EnumCaseDeclSyntax. Early exit.
1017-
return false
1018-
}
1019-
node = parent
1020-
}
1021-
return false
1022-
}
1023-
10241006
/// When the user requested a rename at `position` in `snapshot`, determine the position at which the rename should be
10251007
/// performed internally, the USR of the symbol to rename and the range to rename that should be returned to the
10261008
/// editor.
@@ -1095,17 +1077,8 @@ extension SwiftLanguageService {
10951077

10961078
try Task.checkCancellation()
10971079

1098-
var requestedNewName = request.newName
1099-
if let openParenIndex = requestedNewName.firstIndex(of: "("),
1100-
await isInsideEnumCaseDecl(position: renamePosition, snapshot: snapshot)
1101-
{
1102-
// We don't support renaming enum parameter labels at the moment
1103-
// (https://github.com/apple/sourcekit-lsp/issues/1228)
1104-
requestedNewName = String(requestedNewName[..<openParenIndex])
1105-
}
1106-
11071080
let oldName = CrossLanguageName(clangName: nil, swiftName: oldNameString, definitionLanguage: .swift)
1108-
let newName = CrossLanguageName(clangName: nil, swiftName: requestedNewName, definitionLanguage: .swift)
1081+
let newName = CrossLanguageName(clangName: nil, swiftName: request.newName, definitionLanguage: .swift)
11091082
var edits = try await editsToRename(
11101083
locations: renameLocations,
11111084
in: snapshot,
@@ -1398,13 +1371,6 @@ extension SwiftLanguageService {
13981371
if name.hasSuffix("()") {
13991372
name = String(name.dropLast(2))
14001373
}
1401-
if let openParenIndex = name.firstIndex(of: "("),
1402-
await isInsideEnumCaseDecl(position: renamePosition, snapshot: snapshot)
1403-
{
1404-
// We don't support renaming enum parameter labels at the moment
1405-
// (https://github.com/apple/sourcekit-lsp/issues/1228)
1406-
name = String(name[..<openParenIndex])
1407-
}
14081374
guard let relatedIdentRange = response.relatedIdentifiers.first(where: { $0.range.contains(renamePosition) })?.range
14091375
else {
14101376
return nil

Tests/SourceKitLSPTests/RenameTests.swift

Lines changed: 99 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,14 +1170,15 @@ final class RenameTests: XCTestCase {
11701170
}
11711171

11721172
func testRenameEnumCaseWithUnlabeledAssociatedValue() async throws {
1173+
try await SkipUnless.sourcekitdCanRenameEnumCaseLabels()
11731174
try await assertSingleFileRename(
11741175
"""
11751176
enum MyEnum {
11761177
case 1️⃣myCase(String)
11771178
}
11781179
""",
11791180
newName: "newName",
1180-
expectedPrepareRenamePlaceholder: "myCase",
1181+
expectedPrepareRenamePlaceholder: "myCase(_:)",
11811182
expected: """
11821183
enum MyEnum {
11831184
case newName(String)
@@ -1187,39 +1188,127 @@ final class RenameTests: XCTestCase {
11871188
}
11881189

11891190
func testAddLabelToEnumCase() async throws {
1190-
// We don't support renaming enum parameter labels at the moment
1191-
// (https://github.com/apple/sourcekit-lsp/issues/1228)
1191+
try await SkipUnless.sourcekitdCanRenameEnumCaseLabels()
11921192
try await assertSingleFileRename(
11931193
"""
11941194
enum MyEnum {
11951195
case 1️⃣myCase(String)
11961196
}
11971197
""",
11981198
newName: "newName(newLabel:)",
1199-
expectedPrepareRenamePlaceholder: "myCase",
1199+
expectedPrepareRenamePlaceholder: "myCase(_:)",
12001200
expected: """
12011201
enum MyEnum {
1202-
case newName(String)
1202+
case newName(newLabel: String)
12031203
}
12041204
"""
12051205
)
12061206
}
12071207

1208-
func testRemoveLabelToEnumCase() async throws {
1209-
// We don't support renaming enum parameter labels at the moment
1210-
// (https://github.com/apple/sourcekit-lsp/issues/1228)
1208+
func testRemoveLabelFromEnumCase() async throws {
1209+
try await SkipUnless.sourcekitdCanRenameEnumCaseLabels()
12111210
try await assertSingleFileRename(
12121211
"""
12131212
enum MyEnum {
1214-
case 1️⃣myCase(label: String)
1213+
case myCase(label: String)
1214+
}
1215+
1216+
func test() {
1217+
_ = MyEnum.2️⃣myCase(label: "abc")
12151218
}
12161219
""",
12171220
newName: "newName(_:)",
1218-
expectedPrepareRenamePlaceholder: "myCase",
1221+
expectedPrepareRenamePlaceholder: "myCase(label:)",
1222+
expected: """
1223+
enum MyEnum {
1224+
case newName(_ label: String)
1225+
}
1226+
1227+
func test() {
1228+
_ = MyEnum.newName("abc")
1229+
}
1230+
"""
1231+
)
1232+
}
1233+
1234+
func testRenameEnumCaseWithUnderscoreLabel() async throws {
1235+
try await SkipUnless.sourcekitdCanRenameEnumCaseLabels()
1236+
try await assertSingleFileRename(
1237+
"""
1238+
enum MyEnum {
1239+
case myCase(_ label: String)
1240+
}
1241+
1242+
func test() {
1243+
_ = MyEnum.2️⃣myCase("abc")
1244+
}
1245+
""",
1246+
newName: "newName(_:)",
1247+
expectedPrepareRenamePlaceholder: "myCase(_:)",
1248+
expected: """
1249+
enum MyEnum {
1250+
case newName(_ label: String)
1251+
}
1252+
1253+
func test() {
1254+
_ = MyEnum.newName("abc")
1255+
}
1256+
"""
1257+
)
1258+
}
1259+
1260+
func testRenameEnumCaseWithUnderscoreToLabelMatchingInternalName() async throws {
1261+
try await SkipUnless.sourcekitdCanRenameEnumCaseLabels()
1262+
try await assertSingleFileRename(
1263+
"""
1264+
enum MyEnum {
1265+
case myCase(_ label: String)
1266+
}
1267+
1268+
func test() {
1269+
_ = MyEnum.2️⃣myCase("abc")
1270+
}
1271+
""",
1272+
newName: "newName(label:)",
1273+
expectedPrepareRenamePlaceholder: "myCase(_:)",
12191274
expected: """
12201275
enum MyEnum {
12211276
case newName(label: String)
12221277
}
1278+
1279+
func test() {
1280+
_ = MyEnum.newName(label: "abc")
1281+
}
1282+
"""
1283+
)
1284+
}
1285+
1286+
func testRenameEnumCaseWithUnderscoreToLabelNotMatchingInternalName() async throws {
1287+
try await SkipUnless.sourcekitdCanRenameEnumCaseLabels()
1288+
// Note that the renamed code doesn't compile because enum cases can't have an external and internal parameter name.
1289+
// But it's probably the best thing we can do because we don't want to erase the user-specified internal name, which
1290+
// they didn't request to rename. Also, this is a pretty niche case and having a special case for it is probably not
1291+
// worth it.
1292+
try await assertSingleFileRename(
1293+
"""
1294+
enum MyEnum {
1295+
case myCase(_ label: String)
1296+
}
1297+
1298+
func test() {
1299+
_ = MyEnum.2️⃣myCase("abc")
1300+
}
1301+
""",
1302+
newName: "newName(publicLabel:)",
1303+
expectedPrepareRenamePlaceholder: "myCase(_:)",
1304+
expected: """
1305+
enum MyEnum {
1306+
case newName(publicLabel label: String)
1307+
}
1308+
1309+
func test() {
1310+
_ = MyEnum.newName(publicLabel: "abc")
1311+
}
12231312
"""
12241313
)
12251314
}

0 commit comments

Comments
 (0)