Skip to content

Commit 17eca18

Browse files
authored
Merge pull request #989 from ahoppen/ahoppen/dont-use-local-loc-for-c-definition
Don’t use the best local declaration when jumping to definition of a C function
2 parents 2d01d5d + 4077ce3 commit 17eca18

File tree

2 files changed

+69
-3
lines changed

2 files changed

+69
-3
lines changed

Sources/SourceKitLSP/SourceKitServer.swift

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,8 +1718,14 @@ extension SourceKitServer {
17181718
return []
17191719
}
17201720

1721-
if let bestLocalDeclaration = symbol.bestLocalDeclaration, !(symbol.isDynamic ?? true) {
1722-
// If we have a known non-dynamic symbol, we don't need to do an index lookup
1721+
if let bestLocalDeclaration = symbol.bestLocalDeclaration,
1722+
!(symbol.isDynamic ?? true),
1723+
symbol.usr?.hasPrefix("s:") ?? false /* Swift symbols have USRs starting with s: */
1724+
{
1725+
// If we have a known non-dynamic symbol within Swift, we don't need to do an index lookup.
1726+
// For non-Swift symbols, we need to perform an index lookup because the best local declaration will point to
1727+
// a header file but jump-to-definition should prefer the implementation (there's the declaration request to jump
1728+
// to the function's declaration).
17231729
return [bestLocalDeclaration]
17241730
}
17251731

@@ -1735,7 +1741,11 @@ extension SourceKitServer {
17351741
}
17361742

17371743
guard let index = await self.workspaceForDocument(uri: req.textDocument.uri)?.index else {
1738-
return []
1744+
if let bestLocalDeclaration = symbol.bestLocalDeclaration {
1745+
return [bestLocalDeclaration]
1746+
} else {
1747+
return []
1748+
}
17391749
}
17401750
guard let usr = symbol.usr else { return [] }
17411751
logger.info("performing indexed jump-to-def with usr \(usr)")
@@ -1771,6 +1781,10 @@ extension SourceKitServer {
17711781
}
17721782
}
17731783

1784+
if occurrences.isEmpty, let bestLocalDeclaration = symbol.bestLocalDeclaration {
1785+
return [bestLocalDeclaration]
1786+
}
1787+
17741788
return try await occurrences.asyncCompactMap { occurrence in
17751789
if URL(fileURLWithPath: occurrence.location.path).pathExtension == "swiftinterface" {
17761790
// If the location is in `.swiftinterface` file, use moduleName to return textual interface.

Tests/SourceKitLSPTests/DefinitionTests.swift

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,56 @@ class DefinitionTests: XCTestCase {
143143
]
144144
)
145145
}
146+
147+
func testJumpToCDefinitionFromSwift() async throws {
148+
let ws = try await SwiftPMTestWorkspace(
149+
files: [
150+
"Sources/MyLibrary/include/test.h": """
151+
void myFunc(void);
152+
""",
153+
"Sources/MyLibrary/test.c": """
154+
#include "test.h"
155+
156+
void 1️⃣myFunc(void) {}
157+
""",
158+
"Sources/MySwiftLibrary/main.swift":
159+
"""
160+
import MyLibrary
161+
162+
2️⃣myFunc()
163+
""",
164+
],
165+
manifest: """
166+
// swift-tools-version: 5.7
167+
168+
import PackageDescription
169+
170+
let package = Package(
171+
name: "MyLibrary",
172+
targets: [
173+
.target(name: "MyLibrary"),
174+
.target(name: "MySwiftLibrary", dependencies: ["MyLibrary"])
175+
]
176+
)
177+
""",
178+
build: true
179+
)
180+
181+
let (uri, positions) = try ws.openDocument("main.swift")
182+
183+
let response = try await ws.testClient.send(
184+
DefinitionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["2️⃣"])
185+
)
186+
guard case .locations(let locations) = response else {
187+
XCTFail("Expected locations response")
188+
return
189+
}
190+
191+
XCTAssertEqual(locations.count, 1)
192+
let location = try XCTUnwrap(locations.first)
193+
XCTAssertEqual(
194+
location,
195+
Location(uri: try ws.uri(for: "test.c"), range: Range(try ws.position(of: "1️⃣", in: "test.c")))
196+
)
197+
}
146198
}

0 commit comments

Comments
 (0)