@@ -21,7 +21,9 @@ public struct TestDeclarationMacro: PeerMacro, Sendable {
2121 providingPeersOf declaration: some DeclSyntaxProtocol ,
2222 in context: some MacroExpansionContext
2323 ) throws -> [ DeclSyntax ] {
24- _diagnoseIssues ( with: declaration, testAttribute: node, in: context)
24+ guard _diagnoseIssues ( with: declaration, testAttribute: node, in: context) else {
25+ return [ ]
26+ }
2527
2628 guard let function = declaration. as ( FunctionDeclSyntax . self) else {
2729 return [ ]
@@ -45,6 +47,17 @@ public struct TestDeclarationMacro: PeerMacro, Sendable {
4547 testAttribute: AttributeSyntax ,
4648 in context: some MacroExpansionContext
4749 ) -> TypeSyntax ? {
50+ #if canImport(SwiftSyntax600)
51+ let types = context. lexicalContext
52+ . compactMap { $0. asProtocol ( ( any DeclGroupSyntax ) . self) }
53+ . map ( \. type)
54+ . reversed ( )
55+ if types. isEmpty {
56+ return nil
57+ }
58+ let typeName = types. map ( \. trimmedDescription) . joined ( separator: " . " )
59+ return " \( raw: typeName) "
60+ #else
4861 // Find the beginning of the first attribute on the declaration, including
4962 // those embedded in #if statements, to account for patterns like
5063 // `@MainActor @Test func` where there's a space ahead of @Test, but the
@@ -79,6 +92,7 @@ public struct TestDeclarationMacro: PeerMacro, Sendable {
7992 return TypeSyntax ( IdentifierTypeSyntax ( name: . keyword( . Self) ) )
8093 }
8194 return nil
95+ #endif
8296 }
8397
8498 /// Diagnose issues with a `@Test` declaration.
@@ -87,22 +101,30 @@ public struct TestDeclarationMacro: PeerMacro, Sendable {
87101 /// - declaration: The function declaration to diagnose.
88102 /// - testAttribute: The `@Test` attribute applied to `declaration`.
89103 /// - context: The macro context in which the expression is being parsed.
104+ ///
105+ /// - Returns: Whether or not macro expansion should continue (i.e. stopping
106+ /// if a fatal error was diagnosed.)
90107 private static func _diagnoseIssues(
91108 with declaration: some DeclSyntaxProtocol ,
92109 testAttribute: AttributeSyntax ,
93110 in context: some MacroExpansionContext
94- ) {
111+ ) -> Bool {
95112 var diagnostics = [ DiagnosticMessage] ( )
96113 defer {
97- diagnostics . forEach ( context. diagnose)
114+ context. diagnose ( diagnostics )
98115 }
99116
100117 // The @Test attribute is only supported on function declarations.
101118 guard let function = declaration. as ( FunctionDeclSyntax . self) else {
102119 diagnostics. append ( . attributeNotSupported( testAttribute, on: declaration) )
103- return
120+ return false
104121 }
105122
123+ #if canImport(SwiftSyntax600)
124+ // Check if the lexical context is appropriate for a suite or test.
125+ diagnostics += diagnoseIssuesWithLexicalContext ( containing: declaration, attribute: testAttribute, in: context)
126+ #endif
127+
106128 // Only one @Test attribute is supported.
107129 let suiteAttributes = function. attributes ( named: " Test " , in: context)
108130 if suiteAttributes. count > 1 {
@@ -144,6 +166,8 @@ public struct TestDeclarationMacro: PeerMacro, Sendable {
144166 }
145167 }
146168 }
169+
170+ return !diagnostics. lazy. map ( \. severity) . contains ( . error)
147171 }
148172
149173 /// Create a function call parameter list used to call a function from its
@@ -406,6 +430,11 @@ public struct TestDeclarationMacro: PeerMacro, Sendable {
406430 ) -> [ DeclSyntax ] {
407431 var result = [ DeclSyntax] ( )
408432
433+ #if canImport(SwiftSyntax600)
434+ // Get the name of the type containing the function for passing to the test
435+ // factory function later.
436+ let typealiasExpr : ExprSyntax = typeName. map { " \( $0) .self " } ?? " nil "
437+ #else
409438 // We cannot directly refer to Self here because it will end up being
410439 // resolved as the __TestContainer type we generate. Create a uniquely-named
411440 // reference to Self outside the context of the generated type, and use it
@@ -415,7 +444,7 @@ public struct TestDeclarationMacro: PeerMacro, Sendable {
415444 // inside a static computed property instead of a typealias (where covariant
416445 // Self is disallowed.)
417446 //
418- // This "typealias" will not be necessary when rdar://105470382 is resolved .
447+ // This "typealias" is not necessary when swift-syntax-6.0.0 is available .
419448 var typealiasExpr : ExprSyntax = " nil "
420449 if let typeName {
421450 let typealiasName = context. makeUniqueName ( thunking: functionDecl)
@@ -430,6 +459,7 @@ public struct TestDeclarationMacro: PeerMacro, Sendable {
430459
431460 typealiasExpr = " \( typealiasName) "
432461 }
462+ #endif
433463
434464 // Parse the @Test attribute.
435465 let attributeInfo = AttributeInfo ( byParsing: testAttribute, on: functionDecl, in: context)
0 commit comments