Skip to content

Commit 4ead088

Browse files
committed
Simplify and refactor deduplication into standalone method
1 parent 3a09df6 commit 4ead088

File tree

2 files changed

+65
-26
lines changed

2 files changed

+65
-26
lines changed

Sources/SourceKitLSP/TestDiscovery.swift

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ extension SourceKitLSPServer {
273273
.flatMap { $0 }
274274
.sorted { $0.testItem.location < $1.testItem.location }
275275
.mergingTestsInExtensions()
276+
.deduplicatingIds()
276277
}
277278

278279
func documentTests(
@@ -283,6 +284,7 @@ extension SourceKitLSPServer {
283284
return try await documentTestsWithoutMergingExtensions(req, workspace: workspace, languageService: languageService)
284285
.prefixTestsWithModuleName(workspace: workspace)
285286
.mergingTestsInExtensions()
287+
.deduplicatingIds()
286288
}
287289

288290
private func documentTestsWithoutMergingExtensions(
@@ -441,16 +443,20 @@ fileprivate extension Array<AnnotatedTestItem> {
441443
// as the root item.
442444
if rootItem.isExtension && !item.isExtension {
443445
var newItem = item
444-
newItem.testItem.children = (newItem.testItem.children + rootItem.testItem.children).deduplicatingIds()
446+
newItem.testItem.children += rootItem.testItem.children
445447
rootItem = newItem
446-
} else if rootItem.testItem.children.isEmpty && item.testItem.children.isEmpty {
447-
itemDict[item.testItem.ambiguousTestDifferentiator] = item
448-
continue
449448
} else {
450-
rootItem.testItem.children = (rootItem.testItem.children + item.testItem.children).deduplicatingIds()
449+
rootItem.testItem.children += item.testItem.children
451450
}
452451

453-
itemDict[id] = rootItem
452+
// If this item shares an ID with a sibling and both are leaf
453+
// test items, store it by its disambiguated id to ensure we
454+
// don't overwrite the existing element.
455+
if rootItem.testItem.children.isEmpty && item.testItem.children.isEmpty {
456+
itemDict[item.testItem.ambiguousTestDifferentiator] = item
457+
} else {
458+
itemDict[id] = rootItem
459+
}
454460
} else {
455461
itemDict[id] = item
456462
}
@@ -487,7 +493,7 @@ fileprivate extension Array<AnnotatedTestItem> {
487493
.mergingTestsInExtensions()
488494
return newItem
489495
}
490-
return result.deduplicatingIds()
496+
return result
491497
}
492498

493499
func prefixTestsWithModuleName(workspace: Workspace) async -> Self {
@@ -520,32 +526,18 @@ fileprivate extension Array<TestItem> {
520526
/// by appending `/filename:filename:lineNumber`.
521527
func deduplicatingIds() -> [TestItem] {
522528
var idCounts: [String: Int] = [:]
523-
var result: [TestItem] = []
524-
var hasDuplicates = false
525-
result.reserveCapacity(self.count)
526-
527529
for element in self where element.children.isEmpty {
528530
idCounts[element.id, default: 0] += 1
529-
if idCounts[element.id, default: 0] > 1 {
530-
hasDuplicates = true
531-
}
532531
}
533532

534-
if !hasDuplicates {
535-
return self
536-
}
537-
538-
for element in self {
539-
if idCounts[element.id, default: 0] > 1 {
540-
var newItem = element
533+
return self.map {
534+
var newItem = $0
535+
newItem.children = newItem.children.deduplicatingIds()
536+
if idCounts[newItem.id, default: 0] > 1 {
541537
newItem.id = newItem.ambiguousTestDifferentiator
542-
result.append(newItem)
543-
} else {
544-
result.append(element)
545538
}
539+
return newItem
546540
}
547-
548-
return result
549541
}
550542
}
551543

Tests/SourceKitLSPTests/DocumentTestDiscoveryTests.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,53 @@ final class DocumentTestDiscoveryTests: XCTestCase {
455455
)
456456
}
457457

458+
func testSwiftTestingTestsWithDuplicateFunctionIdentifiersInSuite() async throws {
459+
let testClient = try await TestSourceKitLSPClient()
460+
let uri = DocumentURI(for: .swift)
461+
462+
let positions = testClient.openDocument(
463+
"""
464+
import Testing
465+
466+
1️⃣struct MySuite {
467+
3️⃣@Test(arguments: [1, 2, 3])
468+
func foo(_ x: Int) {}4️⃣
469+
5️⃣@Test(arguments: ["a", "b", "c"])
470+
func foo(_ x: String) {}6️⃣
471+
}2️⃣
472+
""",
473+
uri: uri
474+
)
475+
476+
let filename = uri.fileURL?.lastPathComponent ?? ""
477+
let tests = try await testClient.send(DocumentTestsRequest(textDocument: TextDocumentIdentifier(uri)))
478+
XCTAssertEqual(
479+
tests,
480+
[
481+
TestItem(
482+
id: "MySuite",
483+
label: "MySuite",
484+
style: TestStyle.swiftTesting,
485+
location: Location(uri: uri, range: positions["1️⃣"]..<positions["2️⃣"]),
486+
children: [
487+
TestItem(
488+
id: "MySuite/foo(_:)/\(filename):\(positions["3️⃣"].line + 1):\(positions["3️⃣"].utf16index + 2)",
489+
label: "foo(_:)",
490+
style: TestStyle.swiftTesting,
491+
location: Location(uri: uri, range: positions["3️⃣"]..<positions["4️⃣"])
492+
),
493+
TestItem(
494+
id: "MySuite/foo(_:)/\(filename):\(positions["5️⃣"].line + 1):\(positions["5️⃣"].utf16index + 2)",
495+
label: "foo(_:)",
496+
style: TestStyle.swiftTesting,
497+
location: Location(uri: uri, range: positions["5️⃣"]..<positions["6️⃣"])
498+
),
499+
]
500+
)
501+
]
502+
)
503+
}
504+
458505
func testSwiftTestingTestsWithDuplicateFunctionIdentifiersInExtension() async throws {
459506
let testClient = try await TestSourceKitLSPClient()
460507
let uri = DocumentURI(for: .swift)

0 commit comments

Comments
 (0)