Skip to content

Commit 970c5a5

Browse files
committed
Correctly compute container names for extensions
1 parent 2a0902b commit 970c5a5

File tree

2 files changed

+47
-15
lines changed

2 files changed

+47
-15
lines changed

Sources/SemanticIndex/CheckedIndex.swift

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ package final class CheckedIndex {
6060
private var checker: IndexOutOfDateChecker
6161
private let index: IndexStoreDB
6262

63-
/// Maps the USR of a symbol’s container the name of that container as well as the name of all containers the
64-
/// container might itself be contained in.
63+
/// Maps the USR of a symbol to its name and the name of all its containers, from outermost to innermost.
6564
///
6665
/// It is important that we cache this because we might find a lot of symbols in the same container for eg. workspace
6766
/// symbols (eg. consider many symbols in the same C++ namespace). If we didn't cache this value, then we would need
@@ -256,21 +255,26 @@ package final class CheckedIndex {
256255
}
257256
}.sorted().first
258257

259-
if let container {
260-
if let cached = containerNamesCache[container.symbol.usr] {
261-
return cached
262-
}
263-
let result: [String]
264-
if let containerDefinition = primaryDefinitionOrDeclarationOccurrence(ofUSR: container.symbol.usr) {
265-
result = self.containerNames(of: containerDefinition) + [container.symbol.name]
266-
} else {
267-
result = [container.symbol.name]
268-
}
269-
containerNamesCache[container.symbol.usr] = result
270-
return result
271-
} else {
258+
guard var containerSymbol = container?.symbol else {
272259
return []
273260
}
261+
if let cached = containerNamesCache[containerSymbol.usr] {
262+
return cached
263+
}
264+
265+
if containerSymbol.kind == .extension,
266+
let extendedSymbol = self.occurrences(relatedToUSR: containerSymbol.usr, roles: .extendedBy).first?.symbol
267+
{
268+
containerSymbol = extendedSymbol
269+
}
270+
let result: [String]
271+
if let containerDefinition = primaryDefinitionOrDeclarationOccurrence(ofUSR: containerSymbol.usr) {
272+
result = self.containerNames(of: containerDefinition) + [containerSymbol.name]
273+
} else {
274+
result = [containerSymbol.name]
275+
}
276+
containerNamesCache[containerSymbol.usr] = result
277+
return result
274278
}
275279
}
276280

Tests/SourceKitLSPTests/WorkspaceSymbolsTests.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,32 @@ class WorkspaceSymbolsTests: XCTestCase {
9595
]
9696
)
9797
}
98+
99+
func testContainerNameOfFunctionInExtension() async throws {
100+
let project = try await IndexedSingleSwiftFileTestProject(
101+
"""
102+
struct Foo {
103+
struct Bar {}
104+
}
105+
106+
extension Foo.Bar {
107+
func 1️⃣barMethod() {}
108+
}
109+
"""
110+
)
111+
let response = try await project.testClient.send(WorkspaceSymbolsRequest(query: "barMethod"))
112+
XCTAssertEqual(
113+
response,
114+
[
115+
.symbolInformation(
116+
SymbolInformation(
117+
name: "barMethod()",
118+
kind: .method,
119+
location: Location(uri: project.fileURI, range: Range(project.positions["1️⃣"])),
120+
containerName: "Foo.Bar"
121+
)
122+
)
123+
]
124+
)
125+
}
98126
}

0 commit comments

Comments
 (0)