Skip to content

Commit 73ec325

Browse files
authored
Merge pull request #1006 from ahoppen/ahoppen/prepare-rename
Support the prepare rename request
2 parents 2f80cca + 527600e commit 73ec325

File tree

4 files changed

+74
-1
lines changed

4 files changed

+74
-1
lines changed

Sources/SourceKitLSP/Rename.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,14 @@ extension SourceKitServer {
363363
edits.changes = changes
364364
return edits
365365
}
366+
367+
func prepareRename(
368+
_ request: PrepareRenameRequest,
369+
workspace: Workspace,
370+
languageService: ToolchainLanguageServer
371+
) async throws -> PrepareRenameResponse? {
372+
try await languageService.prepareRename(request)
373+
}
366374
}
367375

368376
// MARK: - Swift
@@ -575,6 +583,25 @@ extension SwiftLanguageServer {
575583
}
576584
}
577585
}
586+
587+
public func prepareRename(_ request: PrepareRenameRequest) async throws -> PrepareRenameResponse? {
588+
let snapshot = try self.documentManager.latestSnapshot(request.textDocument.uri)
589+
590+
let response = try await self.relatedIdentifiers(
591+
at: request.position,
592+
in: snapshot,
593+
includeNonEditableBaseNames: true
594+
)
595+
guard let name = response.name,
596+
let range = response.relatedIdentifiers.first(where: { $0.range.contains(request.position) })?.range
597+
else {
598+
return nil
599+
}
600+
return PrepareRenameResponse(
601+
range: range,
602+
placeholder: name
603+
)
604+
}
578605
}
579606

580607
// MARK: - Clang
@@ -593,4 +620,8 @@ extension ClangLanguageServerShim {
593620
) async throws -> [TextEdit] {
594621
throw ResponseError.internalError("Global rename not implemented for clangd")
595622
}
623+
624+
public func prepareRename(_ request: PrepareRenameRequest) async throws -> PrepareRenameResponse? {
625+
return nil
626+
}
596627
}

Sources/SourceKitLSP/SourceKitServer.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,8 @@ extension SourceKitServer: MessageHandler {
911911
await self.handleRequest(for: request, requestHandler: self.inlayHint)
912912
case let request as RequestAndReply<DocumentDiagnosticsRequest>:
913913
await self.handleRequest(for: request, requestHandler: self.documentDiagnostic)
914+
case let request as RequestAndReply<PrepareRenameRequest>:
915+
await self.handleRequest(for: request, requestHandler: self.prepareRename)
914916
// IMPORTANT: When adding a new entry to this switch, also add it to the `TaskMetadata` initializer.
915917
default:
916918
reply(.failure(ResponseError.methodNotFound(R.method)))
@@ -1175,7 +1177,7 @@ extension SourceKitServer {
11751177
supportsCodeActions: true
11761178
)
11771179
),
1178-
renameProvider: .value(RenameOptions()),
1180+
renameProvider: .value(RenameOptions(prepareProvider: true)),
11791181
colorProvider: .bool(true),
11801182
foldingRangeProvider: .bool(!registry.clientHasDynamicFoldingRangeRegistration),
11811183
declarationProvider: .bool(true),

Sources/SourceKitLSP/ToolchainLanguageServer.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ public protocol ToolchainLanguageServer: AnyObject {
161161
newName: String
162162
) async throws -> [TextEdit]
163163

164+
/// Return compound decl name that will be used as a placeholder for a rename request at a specific position.
165+
func prepareRename(_ request: PrepareRenameRequest) async throws -> PrepareRenameResponse?
166+
164167
// MARK: - Other
165168

166169
func executeCommand(_ req: ExecuteCommandRequest) async throws -> LSPAny?

Tests/SourceKitLSPTests/RenameTests.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,4 +686,41 @@ final class RenameTests: XCTestCase {
686686
}
687687
)
688688
}
689+
690+
func testPrepeareRenameOnDefinition() async throws {
691+
let testClient = try await TestSourceKitLSPClient()
692+
let uri = DocumentURI.for(.swift)
693+
let positions = testClient.openDocument(
694+
"""
695+
func 1️⃣foo2️⃣(a: Int) {}
696+
""",
697+
uri: uri
698+
)
699+
let response = try await testClient.send(
700+
PrepareRenameRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1️⃣"])
701+
)
702+
let range = try XCTUnwrap(response?.range)
703+
let placeholder = try XCTUnwrap(response?.placeholder)
704+
XCTAssertEqual(range, positions["1️⃣"]..<positions["2️⃣"])
705+
XCTAssertEqual(placeholder, "foo(a:)")
706+
}
707+
708+
func testPrepeareRenameOnReference() async throws {
709+
let testClient = try await TestSourceKitLSPClient()
710+
let uri = DocumentURI.for(.swift)
711+
let positions = testClient.openDocument(
712+
"""
713+
func foo(a: Int, b: Int = 1) {}
714+
1️⃣foo2️⃣(a: 1)
715+
""",
716+
uri: uri
717+
)
718+
let response = try await testClient.send(
719+
PrepareRenameRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1️⃣"])
720+
)
721+
let range = try XCTUnwrap(response?.range)
722+
let placeholder = try XCTUnwrap(response?.placeholder)
723+
XCTAssertEqual(range, positions["1️⃣"]..<positions["2️⃣"])
724+
XCTAssertEqual(placeholder, "foo(a:b:)")
725+
}
689726
}

0 commit comments

Comments
 (0)