Skip to content

Commit f90d3c9

Browse files
committed
If there are multiple definition occurrences and getting the cross-language name fails for one symbol, try the next definition
1 parent 968828b commit f90d3c9

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

Sources/SourceKitLSP/Rename.swift

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -554,24 +554,50 @@ extension SourceKitServer {
554554
index: IndexStoreDB
555555
) async throws -> CrossLanguageName? {
556556
let definitions = index.occurrences(ofUSR: usr, roles: [.definition])
557+
if definitions.isEmpty {
558+
logger.error("no definitions for \(usr) found")
559+
return nil
560+
}
557561
if definitions.count > 1 {
558562
logger.log("Multiple definitions for \(usr) found")
559563
}
560564
// There might be multiple definitions of the same symbol eg. in different `#if` branches. In this case pick any of
561565
// them because with very high likelihood they all translate to the same clang and Swift name. Sort the entries to
562566
// ensure that we deterministically pick the same entry every time.
563-
guard let definitionSymbol = definitions.sorted().first else {
564-
logger.error("no definitions for \(usr) found")
565-
return nil
567+
for definitionOccurrence in definitions.sorted() {
568+
do {
569+
return try await getCrossLanguageName(
570+
forDefinitionOccurrence: definitionOccurrence,
571+
overrideName: overrideName,
572+
workspace: workspace,
573+
index: index
574+
)
575+
} catch {
576+
// If getting the cross-language name fails for this occurrence, try the next definition, if there are multiple.
577+
logger.log(
578+
"Getting cross-language name for occurrence at \(definitionOccurrence.location) failed. \(error.forLogging)"
579+
)
580+
}
566581
}
582+
return nil
583+
}
584+
585+
private func getCrossLanguageName(
586+
forDefinitionOccurrence definitionOccurrence: SymbolOccurrence,
587+
overrideName: String? = nil,
588+
workspace: Workspace,
589+
index: IndexStoreDB
590+
) async throws -> CrossLanguageName {
591+
let definitionSymbol = definitionOccurrence.symbol
592+
let usr = definitionSymbol.usr
567593
let definitionLanguage: Language =
568-
switch definitionSymbol.symbol.language {
594+
switch definitionSymbol.language {
569595
case .c: .c
570596
case .cxx: .cpp
571597
case .objc: .objective_c
572598
case .swift: .swift
573599
}
574-
let definitionDocumentUri = DocumentURI(URL(fileURLWithPath: definitionSymbol.location.path))
600+
let definitionDocumentUri = DocumentURI(URL(fileURLWithPath: definitionOccurrence.location.path))
575601

576602
guard
577603
let definitionLanguageService = await self.languageService(
@@ -580,25 +606,24 @@ extension SourceKitServer {
580606
in: workspace
581607
)
582608
else {
583-
logger.fault("Failed to get language service for the document defining \(usr)")
584-
return nil
609+
throw ResponseError.unknown("Failed to get language service for the document defining \(usr)")
585610
}
586611

587-
let definitionName = overrideName ?? definitionSymbol.symbol.name
612+
let definitionName = overrideName ?? definitionSymbol.name
588613

589614
switch definitionLanguageService {
590615
case is ClangLanguageServerShim:
591616
let swiftName: String?
592617
if let swiftReference = await getReferenceFromSwift(usr: usr, index: index, workspace: workspace) {
593-
let isObjectiveCSelector = definitionLanguage == .objective_c && definitionSymbol.symbol.kind.isMethod
618+
let isObjectiveCSelector = definitionLanguage == .objective_c && definitionSymbol.kind.isMethod
594619
swiftName = try await swiftReference.languageServer.translateClangNameToSwift(
595620
at: swiftReference.location,
596621
in: swiftReference.snapshot,
597622
isObjectiveCSelector: isObjectiveCSelector,
598623
name: definitionName
599624
)
600625
} else {
601-
logger.debug("Not translating \(usr) to Swift because it is not referenced from Swift")
626+
logger.debug("Not translating \(definitionSymbol) to Swift because it is not referenced from Swift")
602627
swiftName = nil
603628
}
604629
return CrossLanguageName(clangName: definitionName, swiftName: swiftName, definitionLanguage: definitionLanguage)
@@ -612,7 +637,7 @@ extension SourceKitServer {
612637
let clangName: String?
613638
if hasReferenceFromClang {
614639
clangName = try await swiftLanguageServer.translateSwiftNameToClang(
615-
at: definitionSymbol.location,
640+
at: definitionOccurrence.location,
616641
in: definitionDocumentUri,
617642
name: CompoundDeclName(definitionName)
618643
)

0 commit comments

Comments
 (0)