Skip to content

Commit ec37284

Browse files
committed
Correctly handle raw identifier test suite names
Missed this in my previous patch, make sure we also add backticks to test suite names when they use raw identifiers.
1 parent b17800e commit ec37284

File tree

2 files changed

+137
-11
lines changed

2 files changed

+137
-11
lines changed

Sources/SourceKitLSP/Swift/SwiftTestingScanner.swift

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ final class SyntacticSwiftTestingTestScanner: SyntaxVisitor {
237237
return .skipChildren
238238
}
239239

240+
let displayName = attributeData?.displayName ?? typeNames.last!
241+
let typeNames = typeNames.map { backtickIfNeeded($0).name }
242+
240243
let memberScanner = SyntacticSwiftTestingTestScanner(
241244
snapshot: snapshot,
242245
allTestsDisabled: attributeData?.isDisabled ?? false,
@@ -256,7 +259,7 @@ final class SyntacticSwiftTestingTestScanner: SyntaxVisitor {
256259
let testItem = AnnotatedTestItem(
257260
testItem: TestItem(
258261
id: (parentTypeNames + typeNames).joined(separator: "/"),
259-
label: attributeData?.displayName ?? typeNames.last!,
262+
label: displayName,
260263
disabled: (attributeData?.isDisabled ?? false) || allTestsDisabled,
261264
style: TestStyle.swiftTesting,
262265
location: Location(uri: snapshot.uri, range: range),
@@ -305,15 +308,13 @@ final class SyntacticSwiftTestingTestScanner: SyntaxVisitor {
305308
return visitTypeOrExtensionDecl(node, typeNames: [identifier.name])
306309
}
307310

308-
/// If the given identifier requires backticks to be a valid decl identifier,
311+
/// If the given name requires backticks to be a valid decl identifier,
309312
/// applies backticks and returns `true` along with the new name. Otherwise
310-
/// returns `false` with the original name.
311-
func backtickIfNeeded(_ ident: Identifier) -> (backticked: Bool, name: String) {
312-
let name = ident.name
313-
if name == "``" {
314-
// Special case: `` stays as ``. Any other backticked name will have
315-
// been stripped by Identifier.
316-
return (true, name)
313+
/// returns `false` with the name.
314+
func backtickIfNeeded(_ name: String) -> (backticked: Bool, name: String) {
315+
var name = name
316+
if name.first == "`" && name.last == "`" {
317+
name = String(name.dropFirst().dropLast())
317318
}
318319
let needsBackticks = !name.isValidSwiftIdentifier(for: .variableName)
319320
return (needsBackticks, needsBackticks ? "`\(name)`" : name)
@@ -335,15 +336,15 @@ final class SyntacticSwiftTestingTestScanner: SyntaxVisitor {
335336
let parameters = node.signature.parameterClause.parameters.map { param in
336337
let result =
337338
if let identifier = param.firstName.identifier {
338-
backtickIfNeeded(identifier).name
339+
backtickIfNeeded(identifier.name).name
339340
} else {
340341
// Something like `_`, leave as-is.
341342
param.firstName.text
342343
}
343344
return "\(result):"
344345
}.joined()
345346

346-
let (hasBackticks, baseName) = backtickIfNeeded(identifier)
347+
let (hasBackticks, baseName) = backtickIfNeeded(identifier.name)
347348
let fullName = "\(baseName)(\(parameters))"
348349

349350
// If we have a display name provided by the attribute, use it, otherwise

Tests/SourceKitLSPTests/DocumentTestDiscoveryTests.swift

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,131 @@ final class DocumentTestDiscoveryTests: XCTestCase {
783783
)
784784
}
785785

786+
func testSwiftTestingTestWithNestedRawIdentifiers() async throws {
787+
let testClient = try await TestSourceKitLSPClient()
788+
let uri = DocumentURI(for: .swift)
789+
790+
let positions = testClient.openDocument(
791+
"""
792+
import Testing
793+
794+
1️⃣struct `A B` {
795+
2️⃣struct `C` {
796+
3️⃣struct `D.E` {
797+
4️⃣@Test
798+
func `foo bar`() {
799+
#expect(1 == 2)
800+
}5️⃣
801+
}6️⃣
802+
}7️⃣
803+
}8️⃣
804+
""",
805+
uri: uri
806+
)
807+
808+
let tests = try await testClient.send(DocumentTestsRequest(textDocument: TextDocumentIdentifier(uri)))
809+
XCTAssertEqual(
810+
tests,
811+
[
812+
TestItem(
813+
id: "`A B`",
814+
label: "A B",
815+
style: TestStyle.swiftTesting,
816+
location: Location(uri: uri, range: positions["1️⃣"]..<positions["8️⃣"]),
817+
children: [
818+
TestItem(
819+
id: "`A B`/C",
820+
label: "C",
821+
style: TestStyle.swiftTesting,
822+
location: Location(uri: uri, range: positions["2️⃣"]..<positions["7️⃣"]),
823+
children: [
824+
TestItem(
825+
id: "`A B`/C/`D.E`",
826+
label: "D.E",
827+
style: TestStyle.swiftTesting,
828+
location: Location(uri: uri, range: positions["3️⃣"]..<positions["6️⃣"]),
829+
children: [
830+
TestItem(
831+
id: "`A B`/C/`D.E`/`foo bar`()",
832+
label: "foo bar",
833+
style: TestStyle.swiftTesting,
834+
location: Location(uri: uri, range: positions["4️⃣"]..<positions["5️⃣"])
835+
)
836+
]
837+
)
838+
]
839+
)
840+
]
841+
)
842+
]
843+
)
844+
}
845+
846+
func testSwiftTestingTestWithNestedRawIdentifiersExtension() async throws {
847+
let testClient = try await TestSourceKitLSPClient()
848+
let uri = DocumentURI(for: .swift)
849+
850+
let positions = testClient.openDocument(
851+
"""
852+
import Testing
853+
854+
struct `A.B` {
855+
struct `C` {
856+
struct `D E` {}
857+
}
858+
}
859+
1️⃣extension `A.B`.`C`.`D E` {
860+
2️⃣@Test
861+
func `foo bar`() {
862+
#expect(1 == 2)
863+
}3️⃣
864+
}4️⃣
865+
5️⃣extension `A.B` {
866+
6️⃣@Test
867+
func `bar baz`() {
868+
#expect(1 == 2)
869+
}7️⃣
870+
}8️⃣
871+
""",
872+
uri: uri
873+
)
874+
875+
let tests = try await testClient.send(DocumentTestsRequest(textDocument: TextDocumentIdentifier(uri)))
876+
XCTAssertEqual(
877+
tests,
878+
[
879+
TestItem(
880+
id: "`A.B`/C/`D E`",
881+
label: "D E",
882+
style: TestStyle.swiftTesting,
883+
location: Location(uri: uri, range: positions["1️⃣"]..<positions["4️⃣"]),
884+
children: [
885+
TestItem(
886+
id: "`A.B`/C/`D E`/`foo bar`()",
887+
label: "foo bar",
888+
style: TestStyle.swiftTesting,
889+
location: Location(uri: uri, range: positions["2️⃣"]..<positions["3️⃣"])
890+
)
891+
]
892+
),
893+
TestItem(
894+
id: "`A.B`",
895+
label: "A.B",
896+
style: TestStyle.swiftTesting,
897+
location: Location(uri: uri, range: positions["5️⃣"]..<positions["8️⃣"]),
898+
children: [
899+
TestItem(
900+
id: "`A.B`/`bar baz`()",
901+
label: "bar baz",
902+
style: TestStyle.swiftTesting,
903+
location: Location(uri: uri, range: positions["6️⃣"]..<positions["7️⃣"])
904+
)
905+
]
906+
),
907+
]
908+
)
909+
}
910+
786911
func testSwiftTestingTestWithSlashRawIdentifiers() async throws {
787912
let testClient = try await TestSourceKitLSPClient()
788913
let uri = DocumentURI(for: .swift)

0 commit comments

Comments
 (0)