Skip to content

Commit 7734133

Browse files
committed
Filter backticks in TestItem IDs
Backticks in TestItem IDs should be sanitized. Use the new TokenSyntax.identifier when building up the TestItem IDs.
1 parent 05d9d63 commit 7734133

File tree

3 files changed

+82
-9
lines changed

3 files changed

+82
-9
lines changed

Sources/LanguageServerProtocol/SupportTypes/TestItem.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public struct TestItem: ResponseType, Equatable {
6868
tags: [TestTag]
6969
) {
7070
self.id = id
71-
self.label = label
71+
self.label = id == label ? self.id : label
7272
self.description = description
7373
self.sortText = sortText
7474
self.disabled = disabled

Sources/SourceKitLSP/Swift/SwiftTestingScanner.swift

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -269,15 +269,24 @@ final class SyntacticSwiftTestingTestScanner: SyntaxVisitor {
269269
}
270270

271271
override func visit(_ node: ActorDeclSyntax) -> SyntaxVisitorContinueKind {
272-
return visitTypeOrExtensionDecl(node, typeNames: [node.name.text])
272+
guard let identifier = node.name.identifier else {
273+
return .skipChildren
274+
}
275+
return visitTypeOrExtensionDecl(node, typeNames: [identifier.name])
273276
}
274277

275278
override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind {
276-
return visitTypeOrExtensionDecl(node, typeNames: [node.name.text])
279+
guard let identifier = node.name.identifier else {
280+
return .skipChildren
281+
}
282+
return visitTypeOrExtensionDecl(node, typeNames: [identifier.name])
277283
}
278284

279285
override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind {
280-
return visitTypeOrExtensionDecl(node, typeNames: [node.name.text])
286+
guard let identifier = node.name.identifier else {
287+
return .skipChildren
288+
}
289+
return visitTypeOrExtensionDecl(node, typeNames: [identifier.name])
281290
}
282291

283292
override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind {
@@ -289,15 +298,18 @@ final class SyntacticSwiftTestingTestScanner: SyntaxVisitor {
289298
}
290299

291300
override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind {
292-
return visitTypeOrExtensionDecl(node, typeNames: [node.name.text])
301+
guard let identifier = node.name.identifier else {
302+
return .skipChildren
303+
}
304+
return visitTypeOrExtensionDecl(node, typeNames: [identifier.name])
293305
}
294306

295307
override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind {
296308
let testAttribute = node.attributes
297309
.compactMap { $0.as(AttributeSyntax.self) }
298310
.first { $0.isNamed("Test", inModuleNamed: "Testing") }
299311

300-
guard let testAttribute else {
312+
guard let testAttribute, let identifier = node.name.identifier else {
301313
return .skipChildren
302314
}
303315
let attributeData = TestingAttributeData(attribute: testAttribute)
@@ -306,7 +318,7 @@ final class SyntacticSwiftTestingTestScanner: SyntaxVisitor {
306318
}
307319

308320
let name =
309-
node.name.text + "(" + node.signature.parameterClause.parameters.map { "\($0.firstName.text):" }.joined() + ")"
321+
identifier.name + "(" + node.signature.parameterClause.parameters.map { "\($0.firstName.identifier?.name ?? $0.firstName.text):" }.joined() + ")"
310322

311323
let range = snapshot.absolutePositionRange(
312324
of: node.positionAfterSkippingLeadingTrivia..<node.endPositionBeforeTrailingTrivia
@@ -398,12 +410,12 @@ fileprivate extension TypeSyntax {
398410
var components: [String]? {
399411
switch self.as(TypeSyntaxEnum.self) {
400412
case .identifierType(let identifierType):
401-
return [identifierType.name.text]
413+
return [identifierType.name.identifier?.name ?? identifierType.name.text]
402414
case .memberType(let memberType):
403415
guard let baseComponents = memberType.baseType.components else {
404416
return nil
405417
}
406-
return baseComponents + [memberType.name.text]
418+
return baseComponents + [memberType.name.identifier?.name ?? memberType.name.text]
407419
default:
408420
return nil
409421
}

Tests/SourceKitLSPTests/DocumentTestDiscoveryTests.swift

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,67 @@ final class DocumentTestDiscoveryTests: XCTestCase {
565565
)
566566
}
567567

568+
func testSwiftTestingTestWithBackticksInName() async throws {
569+
let testClient = try await TestSourceKitLSPClient()
570+
let uri = DocumentURI(for: .swift)
571+
572+
let positions = testClient.openDocument(
573+
"""
574+
import Testing
575+
576+
1️⃣struct `MyTests` {
577+
2️⃣@Test
578+
func `oneIsTwo`(`foo`: Int) {
579+
#expect(1 == 2)
580+
}3️⃣
581+
}4️⃣
582+
583+
5️⃣extension `MyTests` {
584+
6️⃣@Test
585+
func `twoIsThree`() {
586+
#expect(2 == 3)
587+
}7️⃣
588+
}8️⃣
589+
""",
590+
uri: uri
591+
)
592+
593+
let tests = try await testClient.send(DocumentTestsRequest(textDocument: TextDocumentIdentifier(uri)))
594+
XCTAssertEqual(
595+
tests,
596+
[
597+
TestItem(
598+
id: "MyTests",
599+
label: "MyTests",
600+
disabled: false,
601+
style: TestStyle.swiftTesting,
602+
location: Location(uri: uri, range: positions["1️⃣"]..<positions["4️⃣"]),
603+
children: [
604+
TestItem(
605+
id: "MyTests/oneIsTwo(foo:)",
606+
label: "oneIsTwo(foo:)",
607+
disabled: false,
608+
style: TestStyle.swiftTesting,
609+
location: Location(uri: uri, range: positions["2️⃣"]..<positions["3️⃣"]),
610+
children: [],
611+
tags: []
612+
),
613+
TestItem(
614+
id: "MyTests/twoIsThree()",
615+
label: "twoIsThree()",
616+
disabled: false,
617+
style: TestStyle.swiftTesting,
618+
location: Location(uri: uri, range: positions["6️⃣"]..<positions["7️⃣"]),
619+
children: [],
620+
tags: []
621+
),
622+
],
623+
tags: []
624+
)
625+
]
626+
)
627+
}
628+
568629
func testDisabledSwiftTestingTest() async throws {
569630
let testClient = try await TestSourceKitLSPClient()
570631
let uri = DocumentURI(for: .swift)

0 commit comments

Comments
 (0)