Skip to content

Commit 9d3bcca

Browse files
committed
Ensure that top-level macro expansions are in the JSON AST dump.
1 parent 3804110 commit 9d3bcca

File tree

4 files changed

+113
-17
lines changed

4 files changed

+113
-17
lines changed

lib/AST/ASTDumper.cpp

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1905,6 +1905,21 @@ namespace {
19051905
printSourceRange(D->getSourceRange(), &D->getASTContext());
19061906
printFlag(D->TrailingSemiLoc.isValid(), "trailing_semi",
19071907
DeclModifierColor);
1908+
1909+
if (Writer.isParsable()) {
1910+
// Print just the USRs of any auxiliary decls associated with this decl,
1911+
// which lets us relate macro expansions back to their originating decl
1912+
// if desired.
1913+
std::vector<std::string> auxiliaryUSRs;
1914+
D->visitAuxiliaryDecls([&auxiliaryUSRs](Decl *auxDecl) {
1915+
if (auto usr = declUSR(auxDecl); !usr.empty()) {
1916+
auxiliaryUSRs.push_back(usr);
1917+
}
1918+
});
1919+
printStringListField(
1920+
auxiliaryUSRs, [&](auto usr) { return usr; },
1921+
Label::always("auxiliary_decl_usrs"));
1922+
}
19081923
}
19091924

19101925
void printInherited(InheritedTypes Inherited) {
@@ -2274,31 +2289,50 @@ namespace {
22742289
}, Label::always("compiler_version"));
22752290
}
22762291

2277-
std::optional<std::vector<ASTNode>> items;
2292+
std::vector<ASTNode> items;
2293+
bool shouldPrintImplicit;
2294+
22782295
switch (MemberLoading) {
22792296
case ASTDumpMemberLoading::None:
2280-
items = SF.getCachedTopLevelItems();
2297+
shouldPrintImplicit = false;
2298+
if (auto cached = SF.getCachedTopLevelItems()) {
2299+
items = *cached;
2300+
}
22812301
break;
22822302
case ASTDumpMemberLoading::Parsed:
2283-
case ASTDumpMemberLoading::TypeChecked:
2303+
shouldPrintImplicit = false;
22842304
items = SF.getTopLevelItems();
22852305
break;
2286-
}
2287-
if (items) {
2288-
printList(*items, [&](ASTNode item, Label label) {
2289-
if (item.isImplicit())
2290-
return;
2306+
case ASTDumpMemberLoading::TypeChecked:
2307+
shouldPrintImplicit = true;
2308+
for (ASTNode item : SF.getTopLevelItems()) {
2309+
items.push_back(item);
22912310

2311+
// If the item is a decl, also collect any auxiliary decls associated
2312+
// with it so that we get macro expansions.
22922313
if (auto decl = item.dyn_cast<Decl *>()) {
2293-
printRec(decl, label);
2294-
} else if (auto stmt = item.dyn_cast<Stmt *>()) {
2295-
printRec(stmt, &SF.getASTContext(), label);
2296-
} else {
2297-
auto expr = item.get<Expr *>();
2298-
printRec(expr, label);
2314+
decl->visitAuxiliaryDecls(
2315+
[&items](Decl *auxDecl) { items.push_back(auxDecl); });
22992316
}
2300-
}, Label::optional("items"));
2317+
}
2318+
break;
23012319
}
2320+
printList(
2321+
items,
2322+
[&](ASTNode item, Label label) {
2323+
if (!shouldPrintImplicit && item.isImplicit())
2324+
return;
2325+
2326+
if (auto decl = item.dyn_cast<Decl *>()) {
2327+
printRec(decl, label);
2328+
} else if (auto stmt = item.dyn_cast<Stmt *>()) {
2329+
printRec(stmt, &SF.getASTContext(), label);
2330+
} else {
2331+
auto expr = item.get<Expr *>();
2332+
printRec(expr, label);
2333+
}
2334+
},
2335+
Label::optional("items"));
23022336
printFoot();
23032337
}
23042338

test/Frontend/Inputs/json_ast_macro_definitions.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,32 @@ struct MemberInjectingMacro: MemberMacro {
1717
return [member]
1818
}
1919
}
20+
21+
struct PeerInjectingMacro: PeerMacro {
22+
public static func expansion(
23+
of node: AttributeSyntax,
24+
providingPeersOf decl: some DeclSyntaxProtocol,
25+
in context: some MacroExpansionContext
26+
) throws -> [DeclSyntax] {
27+
let peer: DeclSyntax =
28+
"""
29+
struct FixedNamePeer {}
30+
"""
31+
32+
return [peer]
33+
}
34+
}
35+
36+
struct FreestandingInjectingMacro: DeclarationMacro {
37+
public static func expansion(
38+
of node: some FreestandingMacroExpansionSyntax,
39+
in context: some MacroExpansionContext
40+
) throws -> [DeclSyntax] {
41+
let peer: DeclSyntax =
42+
"""
43+
struct FixedNameFreestander {}
44+
"""
45+
46+
return [peer]
47+
}
48+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
@attached(member, names: named(_macroInjectedMember))
22
public macro InjectMember() = #externalMacro(module: "MacroDefinition", type: "MemberInjectingMacro")
3+
4+
@attached(peer, names: named(FixedNamePeer))
5+
public macro InjectPeer() = #externalMacro(module: "MacroDefinition", type: "PeerInjectingMacro")
6+
7+
@freestanding(declaration, names: named(FixedNameFreestander))
8+
public macro injectFreestanding() = #externalMacro(module: "MacroDefinition", type: "FreestandingInjectingMacro")

test/Frontend/ast-dump-json-macros.swift

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,42 @@
66
// RUN: %empty-directory(%t)
77
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/json_ast_macro_definitions.swift -g -no-toolchain-stdlib-rpath
88
// RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/json_ast_macro_library.swiftmodule %S/Inputs/json_ast_macro_library.swift -module-name json_ast_macro_library -load-plugin-library %t/%target-library-name(MacroDefinition)
9-
// RUN: %target-swift-frontend -target %target-swift-5.9-abi-triple -I %t -load-plugin-library %t/%target-library-name(MacroDefinition) -parse-as-library -dump-ast -dump-ast-format json %s -module-name main -o - | %FileCheck %s
9+
// RUN: %target-swift-frontend -target %target-swift-5.9-abi-triple -I %t -load-plugin-library %t/%target-library-name(MacroDefinition) -parse-as-library -dump-ast -dump-ast-format json %s -module-name main -o -
10+
// | %FileCheck %s
1011

1112
import json_ast_macro_library
1213

1314
@InjectMember
1415
struct X {
1516
var y: Int
1617
}
17-
1818
// CHECK: "_kind":"pattern_binding_decl"
1919
// CHECK-SAME: "buffer_id":"@__swiftmacro_4main1X12InjectMemberfMm_.swift"
2020
// CHECK-SAME: "name":"_macroInjectedMember"
21+
22+
struct Z {
23+
#injectFreestanding
24+
}
25+
// NOTE: For freestanding members (as opposed to top-level), we get the expanded
26+
// decl before we see the MacroExpansionDecl.
27+
// CHECK-SAME: "_kind":"struct_decl",
28+
// CHECK-SAME: "usr":"s:4main1ZV20FixedNameFreestanderV",
29+
// CHECK-SAME: "buffer_id":"@__swiftmacro_4main0033astdumpjsonmacrosswift_GwAFheaeGafMX{{\d+}}_{{\d+}}_33_{{[0-9A-F]+}}Ll18injectFreestandingfMf_.swift"
30+
// CHECK-SAME: "_kind": "macro_expansion_decl",
31+
// CHECK-SAME: "auxiliary_decl_usrs":["s:4main1ZV20FixedNameFreestanderV"]
32+
33+
@InjectPeer
34+
struct ThisWillBePeered {}
35+
// CHECK-SAME: "_kind":"struct_decl",
36+
// CHECK-SAME: "usr":"s:4main16ThisWillBePeeredV",
37+
// CHECK-SAME: "auxiliary_decl_usrs":["s:4main13FixedNamePeerV"],
38+
// CHECK-SAME: "_kind":"struct_decl",
39+
// CHECK-SAME: "usr":"s:4main13FixedNamePeerV",
40+
// CHECK-SAME: "buffer_id":"@__swiftmacro_4main16ThisWillBePeered10InjectPeerfMp_.swift"
41+
42+
#injectFreestanding
43+
// CHECK-SAME: "_kind":"macro_expansion_decl",
44+
// CHECK-SAME: "auxiliary_decl_usrs":["s:4main20FixedNameFreestanderV"],
45+
// CHECK-SAME: "_kind":"struct_decl",
46+
// CHECK-SAME: "usr":"s:4main20FixedNameFreestanderV",
47+
// CHECK-SAME: "buffer_id":"@__swiftmacro_4main0033astdumpjsonmacrosswift_GwAFheaeGafMX{{\d+}}_{{\d+}}_33_{{[0-9A-F]+}}Ll18injectFreestandingfMf_.swift"

0 commit comments

Comments
 (0)