diff --git a/Sources/SourceKitLSP/Swift/SwiftTestingScanner.swift b/Sources/SourceKitLSP/Swift/SwiftTestingScanner.swift index 84b9e0316..bcb1ced1b 100644 --- a/Sources/SourceKitLSP/Swift/SwiftTestingScanner.swift +++ b/Sources/SourceKitLSP/Swift/SwiftTestingScanner.swift @@ -95,7 +95,18 @@ struct TestingAttributeData { return false } }.flatMap(\.arguments) - .compactMap { $0.expression.as(StringLiteralExprSyntax.self)?.representedLiteralValue } + .compactMap { + if let memberAccess = $0.expression.as(MemberAccessExprSyntax.self) { + var components = memberAccess.components[...] + if components.starts(with: ["Testing", "Tag"]) { + components = components.dropFirst(2) + } else if components.starts(with: ["Tag"]) { + components = components.dropFirst(1) + } + return components.joined(separator: ".") + } + return nil + } self.isDisabled = traitArguments.lazy .compactMap { $0.as(FunctionCallExprSyntax.self) } @@ -328,36 +339,32 @@ fileprivate extension AttributeSyntax { } fileprivate extension MemberAccessExprSyntax { - /// The base name of this instance, i.e. the string value of `base` joined - /// with any preceding base names. + /// The fully-qualified name of this instance (subject to available + /// information.) /// - /// For example, if this instance represents the expression `x.y.z(123)`, - /// the value of this property is `"x.y"`. If the value of `base` is `nil`, - /// the value of this property is also `nil`. - var baseName: String? { - if let declReferenceExpr = base?.as(DeclReferenceExprSyntax.self) { - return declReferenceExpr.baseName.text - } else if let baseMemberAccessExpr = base?.as(MemberAccessExprSyntax.self) { - if let baseBaseName = baseMemberAccessExpr.baseName { - return "\(baseBaseName).\(baseMemberAccessExpr.declName.baseName.text)" - } - return baseMemberAccessExpr.declName.baseName.text - } - - return nil + /// The value of this property are all the components of the based name + /// name joined together with `.`. + var fullyQualifiedName: String { + components.joined(separator: ".") } - /// The fully-qualified name of this instance (subject to available + /// The name components of this instance (subject to available /// information.) /// - /// The value of this property is this instance's `baseName` property joined - /// with its `name` property. For example, if this instance represents the - /// expression `x.y.z(123)`, the value of this property is `"x.y.z"`. - var fullyQualifiedName: String { - if let baseName { - return "\(baseName).\(declName.baseName.text)" + /// The value of this property is this base name of this instance, + /// i.e. the string value of `base` preceeded with any preceding base names + /// and followed by its `name` property. + /// + /// For example, if this instance represents + /// the expression `x.y.z(123)`, the value of this property is + /// `["x", "y", "z"]`. + var components: [String] { + if let declReferenceExpr = base?.as(DeclReferenceExprSyntax.self) { + return [declReferenceExpr.baseName.text, declName.baseName.text] + } else if let baseMemberAccessExpr = base?.as(MemberAccessExprSyntax.self) { + return baseMemberAccessExpr.components + [declName.baseName.text] } - return declName.baseName.text + return [declName.baseName.text] } } diff --git a/Tests/SourceKitLSPTests/DocumentTestDiscoveryTests.swift b/Tests/SourceKitLSPTests/DocumentTestDiscoveryTests.swift index 69162d652..3da0cebc2 100644 --- a/Tests/SourceKitLSPTests/DocumentTestDiscoveryTests.swift +++ b/Tests/SourceKitLSPTests/DocumentTestDiscoveryTests.swift @@ -593,9 +593,9 @@ final class DocumentTestDiscoveryTests: XCTestCase { """ import Testing - 1️⃣@Suite(.tags("Suites")) + 1️⃣@Suite(.tags(.green)) struct MyTests { - 2️⃣@Test(.tags("one", "two")) + 2️⃣@Test(.tags(.red, .blue)) func oneIsTwo() { #expect(1 == 2) }3️⃣ @@ -622,10 +622,72 @@ final class DocumentTestDiscoveryTests: XCTestCase { style: TestStyle.swiftTesting, location: Location(uri: uri, range: positions["2️⃣"]..