@@ -111,6 +111,11 @@ private final class _ContextInserter<C, M>: SyntaxRewriter where C: MacroExpansi
111111 /// The nodes in this array are the _original_ nodes, not the rewritten nodes.
112112 var rewrittenNodes = Set < Syntax > ( )
113113
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+
114119 /// Any postflight code the caller should insert into the closure containing
115120 /// the rewritten syntax tree.
116121 var teardownItems = [ CodeBlockItemSyntax ] ( )
@@ -261,6 +266,7 @@ private final class _ContextInserter<C, M>: SyntaxRewriter where C: MacroExpansi
261266 ExprSyntax ( node ) == memberAccessExpr . base ,
262267 let functionCallExpr = memberAccessExpr . parent ? . as ( FunctionCallExprSyntax . self ) ,
263268 ExprSyntax ( memberAccessExpr ) == functionCallExpr . calledExpression {
269+ possibleModuleNames . insert ( node . baseName )
264270 return _rewrite (
265271 MemberAccessExprSyntax (
266272 base : node . trimmed ,
@@ -556,19 +562,69 @@ private final class _ContextInserter<C, M>: SyntaxRewriter where C: MacroExpansi
556562/// the nodes within `node` (possibly including `node` itself) that were
557563/// rewritten, and a code block containing code that should be inserted into
558564/// 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.
559570func insertCalls (
560571 toExpressionContextNamed expressionContextName : TokenSyntax ,
561- into node : some SyntaxProtocol ,
572+ into node : some ExprSyntaxProtocol ,
562573 for macro : some FreestandingMacroExpansionSyntax ,
563574 rootedAt effectiveRootNode : some SyntaxProtocol ,
564575 in context : some MacroExpansionContext
565576) -> ( 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 )
569578
570579 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+
572628 let rewrittenNodes = contextInserter . rewrittenNodes
573629
574630 let prefixCodeBlockItems = CodeBlockItemListSyntax {
0 commit comments