@@ -17,38 +17,43 @@ import SwiftSyntaxMacros
17
17
/// If the developer specified Self.something as an argument to the `@Test` or
18
18
/// `@Suite` attribute, we will currently incorrectly infer Self as equalling
19
19
/// the `__TestContainer` type we emit rather than the type containing the
20
- /// test. This class strips off `Self.` wherever that occurs.
20
+ /// test. This class strips off `Self.` wherever that occurs and, if possible,
21
+ /// replaces it with the actual containing type name.
21
22
///
22
23
/// Note that this operation is technically incorrect if a subexpression of the
23
24
/// attribute declares a type and refers to it with `Self`. We accept this
24
25
/// constraint as it is unlikely to pose real-world issues and is generally
25
26
/// solvable by using an explicit type name instead of `Self`.
26
- ///
27
- /// This class should instead replace `Self` with the name of the containing
28
- /// type when rdar://105470382 is resolved.
29
27
private final class _SelfRemover < C> : SyntaxRewriter where C: MacroExpansionContext {
30
28
/// The macro context in which the expression is being parsed.
31
29
let context : C
32
30
31
+ /// The type with which to replace `Self`.
32
+ let typeExpr : TypeExprSyntax ?
33
+
33
34
/// Initialize an instance of this class.
34
35
///
35
36
/// - Parameters:
36
37
/// - context: The macro context in which the expression is being parsed.
37
38
/// - viewMode: The view mode to use when walking the syntax tree.
38
39
init ( in context: C ) {
39
40
self . context = context
41
+ self . typeExpr = context. typeOfLexicalContext. map { TypeExprSyntax ( type: $0) }
40
42
}
41
43
42
44
override func visit( _ node: MemberAccessExprSyntax ) -> ExprSyntax {
43
45
if let base = node. base? . as ( DeclReferenceExprSyntax . self) {
44
46
if base. baseName. tokenKind == . keyword( . Self) {
45
- // We cannot currently correctly convert Self.self into the expected
46
- // type name, but once rdar://105470382 is resolved we can replace the
47
- // base expression with the typename here (at which point Self.self
48
- // ceases to be an interesting case anyway.)
47
+ if let typeExpr {
48
+ // Replace Self with the actual type name.
49
+ return ExprSyntax ( node. with ( \. base, ExprSyntax ( typeExpr) ) )
50
+ }
51
+ // We don't know the enclosing type name, so just strip Self and hope
52
+ // the compiler is happy with the leading dot syntax.
49
53
return ExprSyntax ( node. declName)
50
54
}
51
55
} else if let base = node. base? . as ( MemberAccessExprSyntax . self) {
56
+ // Recursively walk into the base expression.
52
57
return ExprSyntax ( node. with ( \. base, visit ( base) ) )
53
58
}
54
59
return ExprSyntax ( node)
0 commit comments