Skip to content

Commit 71b2466

Browse files
committed
[ASTDumper] Dump DeclContext
* Include `DeclContext` of the node where possible * Add 'default-with-decl-contexts' dump style that dumps the dect context hierarchy in addition to the AST * Support `-dump-parse` with `-dump-ast-format json`
1 parent 04b2174 commit 71b2466

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
@@ -1019,6 +1019,10 @@ namespace {
10191019
return Writer.hasNonStandardOutput();
10201020
}
10211021

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

1620+
template <typename T>
1621+
void printDeclContext(const T *D) {
1622+
printField(static_cast<void *>(D->getDeclContext()),
1623+
Label::always("decl_context"));
1624+
}
1625+
16161626
/// Prints a field containing the name or the USR (based on parsability of
16171627
/// the output) of a decl that is being referenced elsewhere.
16181628
template <typename T>
16191629
void printReferencedDeclField(const T *D, Label label) {
1620-
if (Writer.isParsable()) {
1630+
if (Writer.isParsable() && isTypeChecked()) {
16211631
printFieldQuoted(declUSR(D), label);
16221632
} else {
16231633
printFieldQuoted(D->getName(), label);
@@ -1629,7 +1639,7 @@ namespace {
16291639
template <typename T>
16301640
void printReferencedDeclWithContextField(const T *D, Label label,
16311641
TerminalColor Color = DeclColor) {
1632-
if (Writer.isParsable()) {
1642+
if (Writer.isParsable() && isTypeChecked()) {
16331643
printFieldQuoted(declUSR(D), label, Color);
16341644
} else {
16351645
printFieldQuoted(D->printRef(), label, Color);
@@ -1639,7 +1649,7 @@ namespace {
16391649
/// Print a field containing a concrete reference to a declaration.
16401650
void printDeclRefField(ConcreteDeclRef declRef, Label label,
16411651
TerminalColor Color = DeclColor) {
1642-
if (Writer.isParsable()) {
1652+
if (Writer.isParsable() && isTypeChecked()) {
16431653
// Just omit the key/value for parsable formats if there's no decl.
16441654
if (!declRef.getDecl())
16451655
return;
@@ -1808,6 +1818,7 @@ namespace {
18081818
}
18091819
void visitExprPattern(ExprPattern *P, Label label) {
18101820
printCommon(P, "pattern_expr", label);
1821+
printDeclContext(P);
18111822
switch (P->getCachedMatchOperandOwnership()) {
18121823
case ValueOwnership::Default:
18131824
break;
@@ -1838,6 +1849,7 @@ namespace {
18381849
}
18391850
void visitEnumElementPattern(EnumElementPattern *P, Label label) {
18401851
printCommon(P, "pattern_enum_element", label);
1852+
printDeclContext(P);
18411853

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

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

@@ -1918,7 +1932,7 @@ namespace {
19181932
printFlag(D->TrailingSemiLoc.isValid(), "trailing_semi",
19191933
DeclModifierColor);
19201934

1921-
if (Writer.isParsable()) {
1935+
if (Writer.isParsable() && isTypeChecked()) {
19221936
// Print just the USRs of any auxiliary decls associated with this decl,
19231937
// which lets us relate macro expansions back to their originating decl
19241938
// if desired.
@@ -2097,13 +2111,15 @@ namespace {
20972111

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

21092125
printAttributes(decl);
@@ -2213,15 +2229,18 @@ namespace {
22132229

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

22272246
auto VarD = dyn_cast<VarDecl>(VD);
@@ -2423,6 +2442,8 @@ namespace {
24232442
printHead("parameter", ParameterColor, label);
24242443

24252444
printDeclName(PD, Label::optional("name"));
2445+
2446+
printDeclContext(PD);
24262447
if (!PD->getArgumentName().empty())
24272448
printFieldQuoted(PD->getArgumentName(), Label::always("apiName"),
24282449
IdentifierColor);
@@ -2521,23 +2542,32 @@ namespace {
25212542
printCommon(PBD, "pattern_binding_decl", label);
25222543
printAttributes(PBD);
25232544

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

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

@@ -3094,14 +3124,17 @@ class PrintStmt : public StmtVisitor<PrintStmt, void, Label>,
30943124
}
30953125
void visitBreakStmt(BreakStmt *S, Label label) {
30963126
printCommon(S, "break_stmt", label);
3127+
printDeclContext(S);
30973128
printFoot();
30983129
}
30993130
void visitContinueStmt(ContinueStmt *S, Label label) {
31003131
printCommon(S, "continue_stmt", label);
3132+
printDeclContext(S);
31013133
printFoot();
31023134
}
31033135
void visitFallthroughStmt(FallthroughStmt *S, Label label) {
31043136
printCommon(S, "fallthrough_stmt", label);
3137+
printDeclContext(S);
31053138
printFoot();
31063139
}
31073140
void visitSwitchStmt(SwitchStmt *S, Label label) {
@@ -3185,6 +3218,7 @@ class PrintStmt : public StmtVisitor<PrintStmt, void, Label>,
31853218

31863219
void visitDoCatchStmt(DoCatchStmt *S, Label label) {
31873220
printCommon(S, "do_catch_stmt", label);
3221+
printDeclContext(S);
31883222
printThrowDest(S->rethrows(), /*wantNothrow=*/true);
31893223
printRec(S->getBody(), Label::always("body"));
31903224
printRecRange(S->getCatches(), Ctx, Label::always("catch_stmts"));
@@ -4347,6 +4381,7 @@ class PrintExpr : public ExprVisitor<PrintExpr, void, Label>,
43474381

43484382
void visitSingleValueStmtExpr(SingleValueStmtExpr *E, Label label) {
43494383
printCommon(E, "single_value_stmt_expr", label);
4384+
printDeclContext(E);
43504385
printRec(E->getStmt(), &E->getDeclContext()->getASTContext(),
43514386
Label::optional("stmt"));
43524387
printFoot();
@@ -4381,6 +4416,7 @@ class PrintExpr : public ExprVisitor<PrintExpr, void, Label>,
43814416

43824417
void visitMacroExpansionExpr(MacroExpansionExpr *E, Label label) {
43834418
printCommon(E, "macro_expansion_expr", label);
4419+
printDeclContext(E);
43844420

43854421
printFieldQuoted(E->getMacroName(), Label::always("name"), IdentifierColor);
43864422
printField(E->getRawDiscriminator(), Label::always("discriminator"),
@@ -4482,6 +4518,7 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr, void, Label>,
44824518
printFieldQuoted(T->getNameRef(), Label::always("id"), IdentifierColor);
44834519
if (T->isBound()) {
44844520
printReferencedDeclWithContextField(T->getBoundDecl(), Label::always("bind"));
4521+
printDeclContext(T);
44854522
} else {
44864523
printFlag("unbound");
44874524
}
@@ -4974,6 +5011,11 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
49745011
}
49755012
void visitCustomAttr(CustomAttr *Attr, Label label) {
49765013
printCommon(Attr, "custom_attr", label);
5014+
5015+
printField(
5016+
static_cast<void *>(static_cast<DeclContext *>(Attr->getInitContext())),
5017+
Label::always("init_context"));
5018+
49775019
if (Attr->getType()) {
49785020
printTypeField(Attr->getType(), Label::always("type"));
49795021
} else if (MemberLoading == ASTDumpMemberLoading::TypeChecked) {
@@ -5050,7 +5092,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
50505092
}
50515093
void visitImplementsAttr(ImplementsAttr *Attr, Label label) {
50525094
printCommon(Attr, "implements_attr", label);
5053-
if (Writer.isParsable()) {
5095+
if (Writer.isParsable() && isTypeChecked()) {
50545096
// Print the resolved protocol's USR in parsable outputs, not the
50555097
// TypeRepr.
50565098
if (auto PD = Attr->getCachedProtocol(DC); PD && *PD != nullptr) {
@@ -5212,7 +5254,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
52125254
Label label) {
52135255
printCommon(Attr, "restated_objc_conformance_attr", label);
52145256
if (Attr->Proto) {
5215-
if (Writer.isParsable()) {
5257+
if (Writer.isParsable() && isTypeChecked()) {
52165258
printFieldQuoted(declUSR(Attr->Proto), Label::optional("proto"));
52175259
} else {
52185260
printFieldRaw([&](auto &out) { Attr->Proto->dumpRef(out); },
@@ -5293,7 +5335,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
52935335
Label label) {
52945336
printCommon(Attr, "synthesized_protocol_attr", label);
52955337
printFlag(Attr->isUnchecked(), "unchecked");
5296-
if (Writer.isParsable()) {
5338+
if (Writer.isParsable() && isTypeChecked()) {
52975339
printFieldQuoted(declUSR(Attr->getProtocol()),
52985340
Label::optional("protocol"));
52995341
} else {
@@ -5490,7 +5532,7 @@ class PrintConformance : public PrintBase {
54905532
printFlag("no_witness");
54915533
else if (witness.getDecl() == req)
54925534
printFlag("dynamic_witness");
5493-
else if (Writer.isParsable()) {
5535+
else if (Writer.isParsable() && isTypeChecked()) {
54945536
printFieldQuoted(declUSR(witness.getDecl()),
54955537
Label::always("witness"));
54965538
} 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)