Skip to content

Commit 70d900e

Browse files
committed
Extend copied file mapping to all LSP requests returning locations
This addresses issue #2276 by ensuring that all LSP requests that return source file locations map copied header files back to their original locations, not just jump-to-definition. Previously, only the definition request applied this mapping. Now, the following requests also adjust locations for copied files: - textDocument/references - textDocument/implementation - workspace/symbol - callHierarchy/prepare - callHierarchy/incomingCalls - callHierarchy/outgoingCalls - typeHierarchy/prepare - typeHierarchy/supertypes - typeHierarchy/subtypes This provides consistent navigation behavior, ensuring users are always taken to the original source files instead of build artifacts when possible.
1 parent d449cb7 commit 70d900e

File tree

4 files changed

+635
-66
lines changed

4 files changed

+635
-66
lines changed

Sources/BuildServerIntegration/BuildServerManager.swift

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,96 @@ package actor BuildServerManager: QueueBasedMessageHandler {
962962
return locations.map { locationAdjustedForCopiedFiles($0) }
963963
}
964964

965+
package func workspaceEditAdjustedForCopiedFiles(_ workspaceEdit: WorkspaceEdit?) async -> WorkspaceEdit? {
966+
guard var edit = workspaceEdit else {
967+
return nil
968+
}
969+
if let changes = edit.changes {
970+
var newChanges: [DocumentURI: [TextEdit]] = [:]
971+
for (uri, edits) in changes {
972+
let newUri = self.locationAdjustedForCopiedFiles(
973+
Location(uri: uri, range: Position(line: 0, utf16index: 0)..<Position(line: 0, utf16index: 0))
974+
).uri
975+
newChanges[newUri, default: []].append(contentsOf: edits)
976+
}
977+
edit.changes = newChanges
978+
}
979+
if let documentChanges = edit.documentChanges {
980+
var newDocumentChanges: [WorkspaceEditDocumentChange] = []
981+
for change in documentChanges {
982+
switch change {
983+
case .textDocumentEdit(var textEdit):
984+
let newUri = self.locationAdjustedForCopiedFiles(
985+
Location(uri: textEdit.textDocument.uri, range: Position(line: 0, utf16index: 0)..<Position(line: 0, utf16index: 0))
986+
).uri
987+
textEdit.textDocument.uri = newUri
988+
newDocumentChanges.append(.textDocumentEdit(textEdit))
989+
case .createFile(var create):
990+
let newUri = self.locationAdjustedForCopiedFiles(
991+
Location(uri: create.uri, range: Position(line: 0, utf16index: 0)..<Position(line: 0, utf16index: 0))
992+
).uri
993+
create.uri = newUri
994+
newDocumentChanges.append(.createFile(create))
995+
case .renameFile(var rename):
996+
let newOldUri = self.locationAdjustedForCopiedFiles(
997+
Location(uri: rename.oldUri, range: Position(line: 0, utf16index: 0)..<Position(line: 0, utf16index: 0))
998+
).uri
999+
let newNewUri = self.locationAdjustedForCopiedFiles(
1000+
Location(uri: rename.newUri, range: Position(line: 0, utf16index: 0)..<Position(line: 0, utf16index: 0))
1001+
).uri
1002+
rename.oldUri = newOldUri
1003+
rename.newUri = newNewUri
1004+
newDocumentChanges.append(.renameFile(rename))
1005+
case .deleteFile(var delete):
1006+
let newUri = self.locationAdjustedForCopiedFiles(
1007+
Location(uri: delete.uri, range: Position(line: 0, utf16index: 0)..<Position(line: 0, utf16index: 0))
1008+
).uri
1009+
delete.uri = newUri
1010+
newDocumentChanges.append(.deleteFile(delete))
1011+
}
1012+
}
1013+
edit.documentChanges = newDocumentChanges
1014+
}
1015+
return edit
1016+
}
1017+
1018+
package func locationsOrLocationLinksAdjustedForCopiedFiles(_ response: LocationsOrLocationLinksResponse?) async -> LocationsOrLocationLinksResponse? {
1019+
guard let response = response else {
1020+
return nil
1021+
}
1022+
switch response {
1023+
case .locations(let locations):
1024+
let remappedLocations = await self.locationsAdjustedForCopiedFiles(locations)
1025+
return .locations(remappedLocations)
1026+
case .locationLinks(let locationLinks):
1027+
var remappedLinks: [LocationLink] = []
1028+
for link in locationLinks {
1029+
let newUri = self.locationAdjustedForCopiedFiles(Location(uri: link.targetUri, range: link.targetRange)).uri
1030+
remappedLinks.append(LocationLink(
1031+
originSelectionRange: link.originSelectionRange,
1032+
targetUri: newUri,
1033+
targetRange: link.targetRange,
1034+
targetSelectionRange: link.targetSelectionRange
1035+
))
1036+
}
1037+
return .locationLinks(remappedLinks)
1038+
}
1039+
}
1040+
1041+
package func typeHierarchyItemAdjustedForCopiedFiles(_ item: TypeHierarchyItem) async -> TypeHierarchyItem {
1042+
let adjustedLocation = await self.locationAdjustedForCopiedFiles(Location(uri: item.uri, range: item.range))
1043+
return TypeHierarchyItem(
1044+
name: item.name,
1045+
kind: item.kind,
1046+
tags: item.tags,
1047+
detail: item.detail,
1048+
uri: adjustedLocation.uri,
1049+
range: adjustedLocation.range,
1050+
selectionRange: item.selectionRange,
1051+
data: item.data
1052+
)
1053+
}
1054+
9651055
@discardableResult
9661056
package func scheduleRecomputeCopyFileMap() -> Task<Void, Never> {
9671057
let task = Task { [previousUpdateTask = copiedFileMapUpdateTask] in

Sources/ClangLanguageService/ClangLanguageService.swift

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,11 @@ extension ClangLanguageService {
481481
}
482482

483483
package func declaration(_ req: DeclarationRequest) async throws -> LocationsOrLocationLinksResponse? {
484-
return try await forwardRequestToClangd(req)
484+
let result = try await forwardRequestToClangd(req)
485+
guard let workspace = self.workspace.value else {
486+
return result
487+
}
488+
return await workspace.buildServerManager.locationsOrLocationLinksAdjustedForCopiedFiles(result)
485489
}
486490

487491
package func completion(_ req: CompletionRequest) async throws -> CompletionList {
@@ -618,7 +622,11 @@ extension ClangLanguageService {
618622
}
619623

620624
package func indexedRename(_ request: IndexedRenameRequest) async throws -> WorkspaceEdit? {
621-
return try await forwardRequestToClangd(request)
625+
let workspaceEdit = try await forwardRequestToClangd(request)
626+
guard let workspace = self.workspace.value else {
627+
return workspaceEdit
628+
}
629+
return await workspace.buildServerManager.workspaceEditAdjustedForCopiedFiles(workspaceEdit)
622630
}
623631

624632
// MARK: - Other
@@ -634,7 +642,12 @@ extension ClangLanguageService {
634642
position: renameRequest.position
635643
)
636644
let symbolDetail = try await forwardRequestToClangd(symbolInfoRequest).only
637-
return (try await edits ?? WorkspaceEdit(), symbolDetail?.usr)
645+
let workspaceEdit = try await edits
646+
guard let workspace = self.workspace.value else {
647+
return (workspaceEdit ?? WorkspaceEdit(), symbolDetail?.usr)
648+
}
649+
let remappedEdit = await workspace.buildServerManager.workspaceEditAdjustedForCopiedFiles(workspaceEdit)
650+
return (remappedEdit ?? WorkspaceEdit(), symbolDetail?.usr)
638651
}
639652

640653
package func syntacticDocumentTests(

0 commit comments

Comments
 (0)