@@ -111,6 +111,11 @@ private final class _ContextInserter<C, M>: SyntaxRewriter where C: MacroExpansi
111
111
/// The nodes in this array are the _original_ nodes, not the rewritten nodes.
112
112
var rewrittenNodes = Set < Syntax > ( )
113
113
114
+ /// The set of expanded tokens (primarily from instances of
115
+ /// `DeclReferenceExprSyntax`) that may represent module names instead of type
116
+ /// or variable names.
117
+ var possibleModuleNames = Set < TokenSyntax > ( )
118
+
114
119
/// Any postflight code the caller should insert into the closure containing
115
120
/// the rewritten syntax tree.
116
121
var teardownItems = [ CodeBlockItemSyntax] ( )
@@ -261,6 +266,7 @@ private final class _ContextInserter<C, M>: SyntaxRewriter where C: MacroExpansi
261
266
ExprSyntax ( node) == memberAccessExpr. base,
262
267
let functionCallExpr = memberAccessExpr. parent? . as ( FunctionCallExprSyntax . self) ,
263
268
ExprSyntax ( memberAccessExpr) == functionCallExpr. calledExpression {
269
+ possibleModuleNames. insert ( node. baseName)
264
270
return _rewrite (
265
271
MemberAccessExprSyntax (
266
272
base: node. trimmed,
@@ -556,19 +562,69 @@ private final class _ContextInserter<C, M>: SyntaxRewriter where C: MacroExpansi
556
562
/// the nodes within `node` (possibly including `node` itself) that were
557
563
/// rewritten, and a code block containing code that should be inserted into
558
564
/// the lexical scope of `node` _before_ its rewritten equivalent.
565
+ ///
566
+ /// The resulting copy of `node` may not be of the same type as `node`. In
567
+ /// particular, it may not be an expression. Calling code should not assume its
568
+ /// type beyond conformance to `Syntax` and should check its type with `is()` or
569
+ /// `as()` before operating over it.
559
570
func insertCalls(
560
571
toExpressionContextNamed expressionContextName: TokenSyntax ,
561
- into node: some SyntaxProtocol ,
572
+ into node: some ExprSyntaxProtocol ,
562
573
for macro: some FreestandingMacroExpansionSyntax ,
563
574
rootedAt effectiveRootNode: some SyntaxProtocol ,
564
575
in context: some MacroExpansionContext
565
576
) -> ( Syntax , rewrittenNodes: Set < Syntax > , prefixCodeBlockItems: CodeBlockItemListSyntax ) {
566
- if let node = node. as ( ExprSyntax . self) {
567
- _diagnoseTrivialBooleanValue ( from: node, for: macro, in: context)
568
- }
577
+ _diagnoseTrivialBooleanValue ( from: ExprSyntax ( node) , for: macro, in: context)
569
578
570
579
let contextInserter = _ContextInserter ( in: context, for: macro, rootedAt: Syntax ( effectiveRootNode) , expressionContextName: expressionContextName)
571
- let result = contextInserter. rewrite ( node)
580
+
581
+ var result = contextInserter. rewrite ( ExprSyntax ( node) )
582
+ if !contextInserter. possibleModuleNames. isEmpty {
583
+ let canImportNameExpr = DeclReferenceExprSyntax ( baseName: . identifier( " canImport " ) )
584
+ let canImportExprs = contextInserter. possibleModuleNames. map { moduleName in
585
+ FunctionCallExprSyntax ( calledExpression: canImportNameExpr) {
586
+ LabeledExprSyntax ( expression: DeclReferenceExprSyntax ( baseName: moduleName. trimmed) )
587
+ }
588
+ }
589
+ // FIXME: do better
590
+ let anyCanImportExpr : ExprSyntax = """
591
+ \(
592
+ raw: canImportExprs
593
+ . map ( \. description)
594
+ . joined ( separator: " || " )
595
+ )
596
+ """
597
+
598
+ guard let resultExpr = result. as ( ExprSyntax . self) else {
599
+ fatalError ( " Result was of kind \( result. kind) , expected some expression " )
600
+ }
601
+
602
+ result = Syntax (
603
+ IfConfigDeclSyntax (
604
+ clauses: IfConfigClauseListSyntax {
605
+ IfConfigClauseSyntax (
606
+ poundKeyword: . poundIfKeyword( ) ,
607
+ condition: anyCanImportExpr,
608
+ elements: . statements(
609
+ CodeBlockItemListSyntax {
610
+ CodeBlockItemSyntax ( item: CodeBlockItemSyntax . Item ( node) )
611
+ }
612
+ )
613
+ )
614
+ IfConfigClauseSyntax (
615
+ poundKeyword: . poundElseKeyword( ) ,
616
+ condition: anyCanImportExpr,
617
+ elements: . statements(
618
+ CodeBlockItemListSyntax {
619
+ CodeBlockItemSyntax ( item: CodeBlockItemSyntax . Item ( resultExpr) )
620
+ }
621
+ )
622
+ )
623
+ }
624
+ )
625
+ )
626
+ }
627
+
572
628
let rewrittenNodes = contextInserter. rewrittenNodes
573
629
574
630
let prefixCodeBlockItems = CodeBlockItemListSyntax {
0 commit comments