Change parseIfNeeded to an enum to control member loading behavior.

This commit is contained in:
Tony Allevato
2025-01-30 09:08:20 -05:00
parent 5fe10ce86a
commit 3804110db8
4 changed files with 99 additions and 34 deletions

View File

@@ -0,0 +1,41 @@
//===--- ASTDumper.h - Swift AST Dumper flags -------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines types that are used to control the level of detail printed
// by the AST dumper.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_AST_DUMPER_H
#define SWIFT_AST_AST_DUMPER_H
namespace swift {
/// Describes the nature of requests that should be kicked off, if any, to
/// compute members and top-level decls when dumping an AST.
enum class ASTDumpMemberLoading {
/// Dump cached members if available; if they are not, do not kick off any
/// parsing or type-checking requests.
None,
/// Dump parsed members, kicking off a parsing request if necessary to compute
/// them, but not performing additional type-checking.
Parsed,
/// Dump all fully-type checked members, kicking off any requests necessary to
/// compute them.
TypeChecked,
};
} // namespace swift
#endif // SWIFT_AST_AST_DUMPER_H

View File

@@ -13,6 +13,7 @@
#ifndef SWIFT_AST_SOURCEFILE_H
#define SWIFT_AST_SOURCEFILE_H
#include "swift/AST/ASTDumper.h"
#include "swift/AST/ASTNode.h"
#include "swift/AST/FileUnit.h"
#include "swift/AST/IfConfigClauseRangeInfo.h"
@@ -20,9 +21,9 @@
#include "swift/AST/SynthesizedFileUnit.h"
#include "swift/Basic/Debug.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/STLExtras.h"
namespace swift {
@@ -684,7 +685,9 @@ public:
}
SWIFT_DEBUG_DUMP;
void dump(raw_ostream &os, bool parseIfNeeded = false) const;
void
dump(raw_ostream &os,
ASTDumpMemberLoading memberLoading = ASTDumpMemberLoading::None) const;
/// Dumps this source file's AST in JSON format to the given output stream.
void dumpJSON(raw_ostream &os) const;

View File

@@ -14,6 +14,7 @@
//
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTDumper.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/ASTVisitor.h"
@@ -984,7 +985,7 @@ namespace {
protected:
PrintWriterBase &Writer;
public:
bool ParseIfNeeded;
ASTDumpMemberLoading MemberLoading;
llvm::function_ref<Type(Expr *)> GetTypeOfExpr;
llvm::function_ref<Type(TypeRepr *)> GetTypeOfTypeRepr;
llvm::function_ref<Type(KeyPathExpr *E, unsigned index)>
@@ -992,12 +993,13 @@ namespace {
char quote = '"';
explicit PrintBase(
PrintWriterBase &writer, bool parseIfNeeded = false,
PrintWriterBase &writer,
ASTDumpMemberLoading memberLoading = ASTDumpMemberLoading::None,
llvm::function_ref<Type(Expr *)> getTypeOfExpr = defaultGetTypeOfExpr,
llvm::function_ref<Type(TypeRepr *)> getTypeOfTypeRepr = nullptr,
llvm::function_ref<Type(KeyPathExpr *E, unsigned index)>
getTypeOfKeyPathComponent = defaultGetTypeOfKeyPathComponent)
: Writer(writer), ParseIfNeeded(parseIfNeeded),
: Writer(writer), MemberLoading(memberLoading),
GetTypeOfExpr(getTypeOfExpr), GetTypeOfTypeRepr(getTypeOfTypeRepr),
GetTypeOfKeyPathComponent(getTypeOfKeyPathComponent) {}
@@ -2224,18 +2226,26 @@ namespace {
printAttributes(IDC->getDecl());
if (Writer.isParsable()) {
// Parsable outputs are meant to be used for semantic analysis, so we
// want the full list of members, including macro-generated ones.
printList(IDC->getAllMembers(), [&](Decl *D, Label label) {
printRec(D, label);
}, Label::optional("members"));
} else {
auto members = ParseIfNeeded ? IDC->getMembers()
: IDC->getCurrentMembersWithoutLoading();
switch (MemberLoading) {
case ASTDumpMemberLoading::None:
case ASTDumpMemberLoading::Parsed: {
auto members = (MemberLoading == ASTDumpMemberLoading::Parsed)
? IDC->getMembers()
: IDC->getCurrentMembersWithoutLoading();
printList(members, [&](Decl *D, Label label) {
printRec(D, label);
}, Label::optional("members"));
break;
}
case ASTDumpMemberLoading::TypeChecked:
// This mode is used for semantic analysis, so we want the full list of
// members, including macro-generated ones.
printList(
IDC->getAllMembers(),
[&](Decl *D, Label label) { printRec(D, label); },
Label::optional("members"));
break;
}
printFoot();
}
@@ -2264,8 +2274,16 @@ namespace {
}, Label::always("compiler_version"));
}
auto items =
ParseIfNeeded ? SF.getTopLevelItems() : SF.getCachedTopLevelItems();
std::optional<std::vector<ASTNode>> items;
switch (MemberLoading) {
case ASTDumpMemberLoading::None:
items = SF.getCachedTopLevelItems();
break;
case ASTDumpMemberLoading::Parsed:
case ASTDumpMemberLoading::TypeChecked:
items = SF.getTopLevelItems();
break;
}
if (items) {
printList(*items, [&](ASTNode item, Label label) {
if (item.isImplicit())
@@ -2531,7 +2549,8 @@ namespace {
}, Label::optional("foreign_error_convention"));
}
auto canParse = ParseIfNeeded && !D->isBodySkipped();
auto canParse =
(MemberLoading != ASTDumpMemberLoading::None) && !D->isBodySkipped();
if (auto Body = D->getBody(canParse)) {
printRec(Body, &D->getASTContext(), Label::optional("body"));
}
@@ -2845,15 +2864,16 @@ void SourceFile::dump() const {
dump(llvm::errs());
}
void SourceFile::dump(llvm::raw_ostream &OS, bool parseIfNeeded) const {
void SourceFile::dump(llvm::raw_ostream &OS,
ASTDumpMemberLoading memberLoading) const {
DefaultWriter writer(OS, /*indent*/ 0);
PrintDecl(writer, parseIfNeeded).visitSourceFile(*this);
PrintDecl(writer, memberLoading).visitSourceFile(*this);
llvm::errs() << '\n';
}
void SourceFile::dumpJSON(llvm::raw_ostream &OS) const {
JSONWriter writer(OS, /*indent*/ 0);
PrintDecl(writer, /*parseIfNeeded*/ true).visitSourceFile(*this);
PrintDecl(writer, ASTDumpMemberLoading::TypeChecked).visitSourceFile(*this);
}
void Pattern::dump() const {
@@ -2880,12 +2900,12 @@ public:
PrintStmt(
PrintWriterBase &writer, const ASTContext *ctx,
bool parseIfNeeded = false,
ASTDumpMemberLoading memberLoading = ASTDumpMemberLoading::None,
llvm::function_ref<Type(Expr *)> getTypeOfExpr = defaultGetTypeOfExpr,
llvm::function_ref<Type(TypeRepr *)> getTypeOfTypeRepr = nullptr,
llvm::function_ref<Type(KeyPathExpr *E, unsigned index)>
getTypeOfKeyPathComponent = defaultGetTypeOfKeyPathComponent)
: PrintBase(writer, parseIfNeeded, getTypeOfExpr, getTypeOfTypeRepr,
: PrintBase(writer, memberLoading, getTypeOfExpr, getTypeOfTypeRepr,
getTypeOfKeyPathComponent),
Ctx(ctx) {}
@@ -4328,7 +4348,7 @@ void Expr::dump(raw_ostream &OS, llvm::function_ref<Type(Expr *)> getTypeOfExpr,
getTypeOfKeyPathComponent,
unsigned Indent) const {
DefaultWriter writer(OS, Indent);
PrintExpr(writer, /*parseIfNeeded*/ false, getTypeOfExpr,
PrintExpr(writer, ASTDumpMemberLoading::None, getTypeOfExpr,
getTypeOfTypeRepr, getTypeOfKeyPathComponent)
.visit(const_cast<Expr *>(this), Label::optional(""));
}
@@ -4652,12 +4672,12 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
public:
PrintAttribute(
PrintWriterBase &writer, const ASTContext *ctx, DeclContext *dc,
bool parseIfNeeded = false,
ASTDumpMemberLoading memberLoading = ASTDumpMemberLoading::None,
llvm::function_ref<Type(Expr *)> getTypeOfExpr = defaultGetTypeOfExpr,
llvm::function_ref<Type(TypeRepr *)> getTypeOfTypeRepr = nullptr,
llvm::function_ref<Type(KeyPathExpr *E, unsigned index)>
getTypeOfKeyPathComponent = defaultGetTypeOfKeyPathComponent)
: PrintBase(writer, parseIfNeeded, getTypeOfExpr, getTypeOfTypeRepr,
: PrintBase(writer, memberLoading, getTypeOfExpr, getTypeOfTypeRepr,
getTypeOfKeyPathComponent),
Ctx(ctx), DC(dc) {}
@@ -5224,7 +5244,7 @@ void PrintBase::printRec(Decl *D, Label label) {
printHead("<null decl>", DeclColor, label);
printFoot();
} else {
PrintDecl(Writer, ParseIfNeeded, GetTypeOfExpr, GetTypeOfTypeRepr,
PrintDecl(Writer, MemberLoading, GetTypeOfExpr, GetTypeOfTypeRepr,
GetTypeOfKeyPathComponent)
.visit(D, label);
}
@@ -5236,7 +5256,7 @@ void PrintBase::printRec(Expr *E, Label label) {
printHead("<null expr>", ExprColor, label);
printFoot();
} else {
PrintExpr(Writer, ParseIfNeeded, GetTypeOfExpr, GetTypeOfTypeRepr,
PrintExpr(Writer, MemberLoading, GetTypeOfExpr, GetTypeOfTypeRepr,
GetTypeOfKeyPathComponent)
.visit(E, label);
}
@@ -5248,8 +5268,8 @@ void PrintBase::printRec(Stmt *S, const ASTContext *Ctx, Label label) {
printHead("<null stmt>", ExprColor, label);
printFoot();
} else {
PrintStmt(Writer, Ctx, ParseIfNeeded, GetTypeOfExpr,
GetTypeOfTypeRepr, GetTypeOfKeyPathComponent)
PrintStmt(Writer, Ctx, MemberLoading, GetTypeOfExpr, GetTypeOfTypeRepr,
GetTypeOfKeyPathComponent)
.visit(S, label);
}
}, label);
@@ -5260,7 +5280,7 @@ void PrintBase::printRec(TypeRepr *T, Label label) {
printHead("<null typerepr>", TypeReprColor, label);
printFoot();
} else {
PrintTypeRepr(Writer, ParseIfNeeded, GetTypeOfExpr, GetTypeOfTypeRepr,
PrintTypeRepr(Writer, MemberLoading, GetTypeOfExpr, GetTypeOfTypeRepr,
GetTypeOfKeyPathComponent)
.visit(T, label);
}
@@ -5272,7 +5292,7 @@ void PrintBase::printRec(const Pattern *P, Label label) {
printHead("<null pattern>", PatternColor, label);
printFoot();
} else {
PrintPattern(Writer, ParseIfNeeded, GetTypeOfExpr, GetTypeOfTypeRepr,
PrintPattern(Writer, MemberLoading, GetTypeOfExpr, GetTypeOfTypeRepr,
GetTypeOfKeyPathComponent)
.visit(const_cast<Pattern *>(P), label);
}
@@ -5286,7 +5306,7 @@ void PrintBase::printRec(const DeclAttribute *Attr, const ASTContext *Ctx,
printHead("<null attribute>", DeclAttributeColor, label);
printFoot();
} else {
PrintAttribute(Writer, Ctx, DC, ParseIfNeeded, GetTypeOfExpr,
PrintAttribute(Writer, Ctx, DC, MemberLoading, GetTypeOfExpr,
GetTypeOfTypeRepr, GetTypeOfKeyPathComponent)
.visit(const_cast<DeclAttribute *>(Attr), label);
}
@@ -6292,7 +6312,7 @@ namespace {
printHead("<null type>", DeclColor, label);
printFoot();
} else {
PrintType(Writer, ParseIfNeeded, GetTypeOfExpr, GetTypeOfTypeRepr,
PrintType(Writer, MemberLoading, GetTypeOfExpr, GetTypeOfTypeRepr,
GetTypeOfKeyPathComponent)
.visit(type, label);
}

View File

@@ -23,6 +23,7 @@
#include "swift/FrontendTool/FrontendTool.h"
#include "Dependencies.h"
#include "TBD.h"
#include "swift/AST/ASTDumper.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/AvailabilityScope.h"
#include "swift/AST/DiagnosticsFrontend.h"
@@ -468,7 +469,7 @@ static bool dumpAST(CompilerInstance &Instance) {
auto dumpAST = [&](SourceFile *SF, raw_ostream &out) {
switch (opts.DumpASTFormat) {
case FrontendOptions::ASTFormat::Default:
SF->dump(out, /*parseIfNeeded*/ true);
SF->dump(out, ASTDumpMemberLoading::Parsed);
break;
case FrontendOptions::ASTFormat::JSON:
SF->dumpJSON(out);