Skip to content

Commit cc4327d

Browse files
authored
Merge pull request #1077 from ahoppen/ahoppen/de-dupe-definitions
De-dupe locations returned from the defintions request
2 parents 67e45bd + 61dde3f commit cc4327d

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

Sources/SourceKitLSP/SourceKitServer.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1818,7 +1818,7 @@ extension SourceKitServer {
18181818
position: req.position
18191819
)
18201820
)
1821-
return try await symbols.asyncMap { (symbol) -> [Location] in
1821+
let locations = try await symbols.asyncMap { (symbol) -> [Location] in
18221822
if symbol.bestLocalDeclaration != nil && !(symbol.isDynamic ?? true)
18231823
&& symbol.usr?.hasPrefix("s:") ?? false /* Swift symbols have USRs starting with s: */
18241824
{
@@ -1830,6 +1830,11 @@ extension SourceKitServer {
18301830
}
18311831
return try await self.definitionLocations(for: symbol, in: req.textDocument.uri, languageService: languageService)
18321832
}.flatMap { $0 }
1833+
// Remove any duplicate locations. We might end up with duplicate locations when performing a definition request
1834+
// on eg. `MyStruct()` when no explicit initializer is declared. In this case we get two symbol infos, one for the
1835+
// declaration of the `MyStruct` type and one for the initializer, which is implicit and thus has the location of
1836+
// the `MyStruct` declaration itself.
1837+
return locations.unique
18331838
}
18341839

18351840
func definition(
@@ -2374,3 +2379,11 @@ fileprivate extension RequestID {
23742379
}
23752380
}
23762381
}
2382+
2383+
fileprivate extension Sequence where Element: Hashable {
2384+
/// Removes all duplicate elements from the sequence, maintaining order.
2385+
var unique: [Element] {
2386+
var set = Set<Element>()
2387+
return self.filter { set.insert($0).inserted }
2388+
}
2389+
}

Tests/SourceKitLSPTests/DefinitionTests.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,4 +362,32 @@ class DefinitionTests: XCTestCase {
362362
)
363363
)
364364
}
365+
366+
func testDefinitionOfImplicitInitializer() async throws {
367+
let testClient = try await TestSourceKitLSPClient()
368+
let uri = DocumentURI.for(.swift)
369+
370+
let positions = testClient.openDocument(
371+
"""
372+
class 1️⃣Foo {}
373+
374+
func test() {
375+
2️⃣Foo()
376+
}
377+
""",
378+
uri: uri
379+
)
380+
381+
let response = try await testClient.send(
382+
DefinitionRequest(textDocument: TextDocumentIdentifier(uri), position: positions["2️⃣"])
383+
)
384+
guard case .locations(let locations) = response else {
385+
XCTFail("Expected locations response")
386+
return
387+
}
388+
XCTAssertEqual(
389+
locations,
390+
[Location(uri: uri, range: Range(positions["1️⃣"]))]
391+
)
392+
}
365393
}

0 commit comments

Comments
 (0)