diff --git a/Sources/SourceKitLSP/SourceKitLSPServer.swift b/Sources/SourceKitLSP/SourceKitLSPServer.swift index 38dc2dcf3..7b59f8ca1 100644 --- a/Sources/SourceKitLSP/SourceKitLSPServer.swift +++ b/Sources/SourceKitLSP/SourceKitLSPServer.swift @@ -2025,8 +2025,23 @@ extension SourceKitLSPServer { } } - if occurrences.isEmpty, let bestLocalDeclaration = symbol.bestLocalDeclaration { - return [bestLocalDeclaration] + if occurrences.isEmpty { + if let bestLocalDeclaration = symbol.bestLocalDeclaration { + return [bestLocalDeclaration] + } + // Fallback: The symbol was not found in the index. This often happens with + // third-party binary frameworks or libraries where indexing data is missing. + // If module info is available, fallback to generating the textual interface. + if let systemModule = symbol.systemModule { + let location = try await self.definitionInInterface( + moduleName: systemModule.moduleName, + groupName: systemModule.groupName, + symbolUSR: symbol.usr, + originatorUri: uri, + languageService: languageService + ) + return [location] + } } return occurrences.compactMap { indexToLSPLocation($0.location) }.sorted() diff --git a/Tests/SourceKitLSPTests/DefinitionTests.swift b/Tests/SourceKitLSPTests/DefinitionTests.swift index e8940aafc..84d955c10 100644 --- a/Tests/SourceKitLSPTests/DefinitionTests.swift +++ b/Tests/SourceKitLSPTests/DefinitionTests.swift @@ -689,4 +689,40 @@ class DefinitionTests: SourceKitLSPTestCase { ) XCTAssertEqual(response?.locations?.map(\.uri), [try project.uri(for: "Test.h")]) } + + func testJumpToSwiftInterfaceIfIndexLookupFails() async throws { + let project = try await SwiftPMTestProject( + files: [ + "Lib/Lib.swift": """ + public func abc() {} + """, + "Executable/Executable.swift": """ + import Lib + + func test() { + 1️⃣abc() + } + """, + ], + manifest: """ + let package = Package( + name: "MyLibrary", + targets: [ + .target(name: "Lib"), + .executableTarget(name: "Executable", dependencies: ["Lib"]) + ] + ) + """ + ) + try await SwiftPMTestProject.build( + at: project.scratchDirectory, + extraArguments: ["--disable-index-store", "-Xswiftc", "-avoid-emit-module-source-info"] + ) + + let (uri, positions) = try project.openDocument("Executable.swift") + let definitions = try await project.testClient.send( + DefinitionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["1️⃣"]) + ) + XCTAssertTrue(definitions?.locations?.first?.uri.pseudoPath.hasSuffix("Lib.swiftinterface") ?? false) + } }