Skip to content

Commit 153421f

Browse files
authored
Merge pull request #79311 from rintaro/dump-declcontext
[ASTDumper] Dump DeclContext
2 parents da02cd0 + 71b2466 commit 153421f

18 files changed

+341
-100
lines changed

include/swift/Frontend/FrontendOptions.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -449,9 +449,10 @@ class FrontendOptions {
449449

450450
/// The possible output formats supported for dumping ASTs.
451451
enum class ASTFormat {
452-
Default, ///< S-expressions for debugging
453-
JSON, ///< Structured JSON for analysis
454-
JSONZlib, ///< Like JSON, but zlib-compressed
452+
Default, ///< S-expressions for debugging
453+
DefaultWithDeclContext, ///< S-expressions with DeclContext hierarchy
454+
JSON, ///< Structured JSON for analysis
455+
JSONZlib, ///< Like JSON, but zlib-compressed
455456
};
456457

457458
/// The output format generated by the `-dump-ast` flag.

include/swift/Subsystems.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,9 @@ namespace swift {
325325
/// Dump YAML describing all fixed-size types imported from the given module.
326326
bool performDumpTypeInfo(const IRGenOptions &Opts, SILModule &SILMod);
327327

328+
/// Dump DeclContext hierarchy of the all nodes in \c SF .
329+
void dumpDeclContextHierarchy(llvm::raw_ostream &OS, SourceFile &SF);
330+
328331
/// Creates a TargetMachine from the IRGen opts and AST Context.
329332
std::unique_ptr<llvm::TargetMachine>
330333
createTargetMachine(const IRGenOptions &Opts, ASTContext &Ctx);

lib/AST/ASTDumper.cpp

Lines changed: 83 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,10 @@ namespace {
10201020
return Writer.hasNonStandardOutput();
10211021
}
10221022

1023+
bool isTypeChecked() const {
1024+
return MemberLoading == ASTDumpMemberLoading::TypeChecked;
1025+
}
1026+
10231027
/// Call `Body` in a context where the printer is ready for a child to be
10241028
/// printed.
10251029
void printRecArbitrary(std::function<void(Label)> body, Label label) {
@@ -1614,11 +1618,17 @@ namespace {
16141618
}
16151619
}
16161620

1621+
template <typename T>
1622+
void printDeclContext(const T *D) {
1623+
printField(static_cast<void *>(D->getDeclContext()),
1624+
Label::always("decl_context"));
1625+
}
1626+
16171627
/// Prints a field containing the name or the USR (based on parsability of
16181628
/// the output) of a decl that is being referenced elsewhere.
16191629
template <typename T>
16201630
void printReferencedDeclField(const T *D, Label label) {
1621-
if (Writer.isParsable()) {
1631+
if (Writer.isParsable() && isTypeChecked()) {
16221632
printFieldQuoted(declUSR(D), label);
16231633
} else {
16241634
printFieldQuoted(D->getName(), label);
@@ -1630,7 +1640,7 @@ namespace {
16301640
template <typename T>
16311641
void printReferencedDeclWithContextField(const T *D, Label label,
16321642
TerminalColor Color = DeclColor) {
1633-
if (Writer.isParsable()) {
1643+
if (Writer.isParsable() && isTypeChecked()) {
16341644
printFieldQuoted(declUSR(D), label, Color);
16351645
} else {
16361646
printFieldQuoted(D->printRef(), label, Color);
@@ -1640,7 +1650,7 @@ namespace {
16401650
/// Print a field containing a concrete reference to a declaration.
16411651
void printDeclRefField(ConcreteDeclRef declRef, Label label,
16421652
TerminalColor Color = DeclColor) {
1643-
if (Writer.isParsable()) {
1653+
if (Writer.isParsable() && isTypeChecked()) {
16441654
// Just omit the key/value for parsable formats if there's no decl.
16451655
if (!declRef.getDecl())
16461656
return;
@@ -1809,6 +1819,7 @@ namespace {
18091819
}
18101820
void visitExprPattern(ExprPattern *P, Label label) {
18111821
printCommon(P, "pattern_expr", label);
1822+
printDeclContext(P);
18121823
switch (P->getCachedMatchOperandOwnership()) {
18131824
case ValueOwnership::Default:
18141825
break;
@@ -1839,6 +1850,7 @@ namespace {
18391850
}
18401851
void visitEnumElementPattern(EnumElementPattern *P, Label label) {
18411852
printCommon(P, "pattern_enum_element", label);
1853+
printDeclContext(P);
18421854

18431855
if (Writer.isParsable()) {
18441856
printName(P->getName().getFullName(), Label::always("element"));
@@ -1895,12 +1907,14 @@ namespace {
18951907
// Parsable outputs include the USR for each decl since they can be used
18961908
// to cross-reference them (within the AST dump itself and with other data
18971909
// sources like indexstore and SourceKit).
1898-
if (Writer.isParsable()) {
1910+
if (Writer.isParsable() && isTypeChecked()) {
18991911
if (auto usr = declUSR(D); !usr.empty()) {
19001912
printFieldQuoted(usr, Label::always("usr"));
19011913
}
19021914
}
19031915

1916+
printDeclContext(D);
1917+
19041918
printFlag(D->isImplicit(), "implicit", DeclModifierColor);
19051919
printFlag(D->isHoisted(), "hoisted", DeclModifierColor);
19061920

@@ -1919,7 +1933,7 @@ namespace {
19191933
printFlag(D->TrailingSemiLoc.isValid(), "trailing_semi",
19201934
DeclModifierColor);
19211935

1922-
if (Writer.isParsable()) {
1936+
if (Writer.isParsable() && isTypeChecked()) {
19231937
// Print just the USRs of any auxiliary decls associated with this decl,
19241938
// which lets us relate macro expansions back to their originating decl
19251939
// if desired.
@@ -2098,13 +2112,15 @@ namespace {
20982112

20992113
printWhereRequirements(decl);
21002114
if (decl->overriddenDeclsComputed()) {
2101-
printStringListField(decl->getOverriddenDecls(),
2102-
[&](AssociatedTypeDecl *overridden) {
2103-
if (Writer.isParsable()) {
2104-
return declUSR(overridden->getProtocol());
2105-
}
2106-
return std::string(overridden->getProtocol()->getName().str());
2107-
}, Label::always("overridden"), /*delimiter=*/ ", ");
2115+
printStringListField(
2116+
decl->getOverriddenDecls(),
2117+
[&](AssociatedTypeDecl *overridden) {
2118+
if (Writer.isParsable() && isTypeChecked()) {
2119+
return declUSR(overridden->getProtocol());
2120+
}
2121+
return std::string(overridden->getProtocol()->getName().str());
2122+
},
2123+
Label::always("overridden"), /*delimiter=*/", ");
21082124
}
21092125

21102126
printAttributes(decl);
@@ -2214,15 +2230,18 @@ namespace {
22142230

22152231
if (VD->overriddenDeclsComputed()) {
22162232
auto overridden = VD->getOverriddenDecls();
2217-
printStringListField(overridden, [&](ValueDecl *overridden) {
2218-
if (Writer.isParsable()) {
2219-
return declUSR(overridden);
2220-
}
2221-
std::string value;
2222-
llvm::raw_string_ostream SOS(value);
2223-
overridden->dumpRef(SOS);
2224-
return value;
2225-
}, Label::always("override"), /*delimiter=*/ ", ", OverrideColor);
2233+
printStringListField(
2234+
overridden,
2235+
[&](ValueDecl *overridden) {
2236+
if (Writer.isParsable() && isTypeChecked()) {
2237+
return declUSR(overridden);
2238+
}
2239+
std::string value;
2240+
llvm::raw_string_ostream SOS(value);
2241+
overridden->dumpRef(SOS);
2242+
return value;
2243+
},
2244+
Label::always("override"), /*delimiter=*/", ", OverrideColor);
22262245
}
22272246

22282247
auto VarD = dyn_cast<VarDecl>(VD);
@@ -2424,6 +2443,8 @@ namespace {
24242443
printHead("parameter", ParameterColor, label);
24252444

24262445
printDeclName(PD, Label::optional("name"));
2446+
2447+
printDeclContext(PD);
24272448
if (!PD->getArgumentName().empty())
24282449
printFieldQuoted(PD->getArgumentName(), Label::always("apiName"),
24292450
IdentifierColor);
@@ -2522,23 +2543,32 @@ namespace {
25222543
printCommon(PBD, "pattern_binding_decl", label);
25232544
printAttributes(PBD);
25242545

2525-
printList(range(PBD->getNumPatternEntries()), [&](auto idx, Label label) {
2526-
// Ensure that we have an object structure printed in parsable modes
2527-
// so that the children aren't directly rendered as array elements.
2528-
if (Writer.isParsable())
2529-
printHead("pattern_entry", FieldLabelColor, label);
2530-
2531-
printRec(PBD->getPattern(idx), Label::optional("pattern"));
2532-
if (PBD->getOriginalInit(idx)) {
2533-
printRec(PBD->getOriginalInit(idx), Label::always("original_init"));
2534-
}
2535-
if (PBD->getInit(idx)) {
2536-
printRec(PBD->getInit(idx), Label::always("processed_init"));
2537-
}
2546+
printList(
2547+
range(PBD->getNumPatternEntries()),
2548+
[&](auto idx, Label label) {
2549+
printRecArbitrary(
2550+
[&](Label label) {
2551+
printHead("pattern_entry", FieldLabelColor, label);
2552+
2553+
if (PBD->getInitContext(idx))
2554+
printField(PBD->getInitContext(idx),
2555+
Label::always("init_context"));
2556+
2557+
printRec(PBD->getPattern(idx), Label::optional("pattern"));
2558+
if (PBD->getOriginalInit(idx)) {
2559+
printRec(PBD->getOriginalInit(idx),
2560+
Label::always("original_init"));
2561+
}
2562+
if (PBD->getInit(idx)) {
2563+
printRec(PBD->getInit(idx),
2564+
Label::always("processed_init"));
2565+
}
25382566

2539-
if (Writer.isParsable())
2540-
printFoot();
2541-
}, Label::optional("pattern_entries"));
2567+
printFoot();
2568+
},
2569+
Label::optional("pattern_entry"));
2570+
},
2571+
Label::optional("pattern_entries"));
25422572
printFoot();
25432573
}
25442574

@@ -3095,14 +3125,17 @@ class PrintStmt : public StmtVisitor<PrintStmt, void, Label>,
30953125
}
30963126
void visitBreakStmt(BreakStmt *S, Label label) {
30973127
printCommon(S, "break_stmt", label);
3128+
printDeclContext(S);
30983129
printFoot();
30993130
}
31003131
void visitContinueStmt(ContinueStmt *S, Label label) {
31013132
printCommon(S, "continue_stmt", label);
3133+
printDeclContext(S);
31023134
printFoot();
31033135
}
31043136
void visitFallthroughStmt(FallthroughStmt *S, Label label) {
31053137
printCommon(S, "fallthrough_stmt", label);
3138+
printDeclContext(S);
31063139
printFoot();
31073140
}
31083141
void visitSwitchStmt(SwitchStmt *S, Label label) {
@@ -3186,6 +3219,7 @@ class PrintStmt : public StmtVisitor<PrintStmt, void, Label>,
31863219

31873220
void visitDoCatchStmt(DoCatchStmt *S, Label label) {
31883221
printCommon(S, "do_catch_stmt", label);
3222+
printDeclContext(S);
31893223
printThrowDest(S->rethrows(), /*wantNothrow=*/true);
31903224
printRec(S->getBody(), Label::always("body"));
31913225
printRecRange(S->getCatches(), Ctx, Label::always("catch_stmts"));
@@ -4348,6 +4382,7 @@ class PrintExpr : public ExprVisitor<PrintExpr, void, Label>,
43484382

43494383
void visitSingleValueStmtExpr(SingleValueStmtExpr *E, Label label) {
43504384
printCommon(E, "single_value_stmt_expr", label);
4385+
printDeclContext(E);
43514386
printRec(E->getStmt(), &E->getDeclContext()->getASTContext(),
43524387
Label::optional("stmt"));
43534388
printFoot();
@@ -4382,6 +4417,7 @@ class PrintExpr : public ExprVisitor<PrintExpr, void, Label>,
43824417

43834418
void visitMacroExpansionExpr(MacroExpansionExpr *E, Label label) {
43844419
printCommon(E, "macro_expansion_expr", label);
4420+
printDeclContext(E);
43854421

43864422
printFieldQuoted(E->getMacroName(), Label::always("name"), IdentifierColor);
43874423
printField(E->getRawDiscriminator(), Label::always("discriminator"),
@@ -4483,6 +4519,7 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr, void, Label>,
44834519
printFieldQuoted(T->getNameRef(), Label::always("id"), IdentifierColor);
44844520
if (T->isBound()) {
44854521
printReferencedDeclWithContextField(T->getBoundDecl(), Label::always("bind"));
4522+
printDeclContext(T);
44864523
} else {
44874524
printFlag("unbound");
44884525
}
@@ -4975,6 +5012,11 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
49755012
}
49765013
void visitCustomAttr(CustomAttr *Attr, Label label) {
49775014
printCommon(Attr, "custom_attr", label);
5015+
5016+
printField(
5017+
static_cast<void *>(static_cast<DeclContext *>(Attr->getInitContext())),
5018+
Label::always("init_context"));
5019+
49785020
if (Attr->getType()) {
49795021
printTypeField(Attr->getType(), Label::always("type"));
49805022
} else if (MemberLoading == ASTDumpMemberLoading::TypeChecked) {
@@ -5051,7 +5093,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
50515093
}
50525094
void visitImplementsAttr(ImplementsAttr *Attr, Label label) {
50535095
printCommon(Attr, "implements_attr", label);
5054-
if (Writer.isParsable()) {
5096+
if (Writer.isParsable() && isTypeChecked()) {
50555097
// Print the resolved protocol's USR in parsable outputs, not the
50565098
// TypeRepr.
50575099
if (auto PD = Attr->getCachedProtocol(DC); PD && *PD != nullptr) {
@@ -5213,7 +5255,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
52135255
Label label) {
52145256
printCommon(Attr, "restated_objc_conformance_attr", label);
52155257
if (Attr->Proto) {
5216-
if (Writer.isParsable()) {
5258+
if (Writer.isParsable() && isTypeChecked()) {
52175259
printFieldQuoted(declUSR(Attr->Proto), Label::optional("proto"));
52185260
} else {
52195261
printFieldRaw([&](auto &out) { Attr->Proto->dumpRef(out); },
@@ -5294,7 +5336,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
52945336
Label label) {
52955337
printCommon(Attr, "synthesized_protocol_attr", label);
52965338
printFlag(Attr->isUnchecked(), "unchecked");
5297-
if (Writer.isParsable()) {
5339+
if (Writer.isParsable() && isTypeChecked()) {
52985340
printFieldQuoted(declUSR(Attr->getProtocol()),
52995341
Label::optional("protocol"));
53005342
} else {
@@ -5491,7 +5533,7 @@ class PrintConformance : public PrintBase {
54915533
printFlag("no_witness");
54925534
else if (witness.getDecl() == req)
54935535
printFlag("dynamic_witness");
5494-
else if (Writer.isParsable()) {
5536+
else if (Writer.isParsable() && isTypeChecked()) {
54955537
printFieldQuoted(declUSR(witness.getDecl()),
54965538
Label::always("witness"));
54975539
} else {

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ add_swift_host_library(swiftAST STATIC
4242
ConformanceLookupTable.cpp
4343
Decl.cpp
4444
DeclContext.cpp
45+
DeclContextDumper.cpp
4546
DeclNameLoc.cpp
4647
DiagnosticBridge.cpp
4748
DiagnosticConsumer.cpp

lib/AST/DeclContext.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,8 @@ unsigned DeclContext::printContext(raw_ostream &OS, const unsigned indent,
760760
case DeclContextKind::EnumElementDecl: Kind = "EnumElementDecl"; break;
761761
case DeclContextKind::MacroDecl: Kind = "MacroDecl"; break;
762762
}
763-
OS.indent(Depth*2 + indent) << (void*)this << " " << Kind;
763+
OS.indent(Depth * 2 + indent)
764+
<< static_cast<const void *>(this) << " " << Kind;
764765

765766
switch (getContextKind()) {
766767
case DeclContextKind::Package:

0 commit comments

Comments
 (0)