mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This PR refactors the ASTDumper to make it more structured, less mistake-prone, and more amenable to future changes. For example:
```cpp
// Before:
void visitUnresolvedDotExpr(UnresolvedDotExpr *E) {
printCommon(E, "unresolved_dot_expr")
<< " field '" << E->getName() << "'";
PrintWithColorRAII(OS, ExprModifierColor)
<< " function_ref=" << getFunctionRefKindStr(E->getFunctionRefKind());
if (E->getBase()) {
OS << '\n';
printRec(E->getBase());
}
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
// After:
void visitUnresolvedDotExpr(UnresolvedDotExpr *E, StringRef label) {
printCommon(E, "unresolved_dot_expr", label);
printFieldQuoted(E->getName(), "field");
printField(E->getFunctionRefKind(), "function_ref", ExprModifierColor);
if (E->getBase()) {
printRec(E->getBase());
}
printFoot();
}
```
* Values are printed through calls to base class methods, rather than direct access to the underlying `raw_ostream`.
* These methods tend to reduce the chances of bugs like missing/extra spaces or newlines, too much/too little indentation, etc.
* More values are quoted, and unprintable/non-ASCII characters in quoted values are escaped before printing.
* Infrastructure to label child nodes now exists.
* Some weird breaks from the normal "style", like `PatternBindingDecl`'s original and processed initializers, have been brought into line.
* Some types that previously used ad-hoc dumping functions, like conformances and substitution maps, are now structured similarly to the dumper classes.
* I've fixed the odd dumping bug along the way. For example, distributed actors were only marked `actor`, not `distributed actor`.
This PR doesn't change the overall style of AST dumps; they're still pseudo-S-expressions. But the logic that implements this style is now isolated into a relatively small base class, making it feasible to introduce e.g. JSON dumping in the future.
4483 lines
141 KiB
C++
4483 lines
141 KiB
C++
//===--- ASTDumper.cpp - Swift Language AST Dumper ------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2020 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 implements dumping for the Swift ASTs.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/AST/ASTContext.h"
|
|
#include "swift/AST/ASTPrinter.h"
|
|
#include "swift/AST/ASTVisitor.h"
|
|
#include "swift/AST/Attr.h"
|
|
#include "swift/AST/ClangModuleLoader.h"
|
|
#include "swift/AST/ForeignAsyncConvention.h"
|
|
#include "swift/AST/ForeignErrorConvention.h"
|
|
#include "swift/AST/GenericEnvironment.h"
|
|
#include "swift/AST/Initializer.h"
|
|
#include "swift/AST/PackConformance.h"
|
|
#include "swift/AST/ParameterList.h"
|
|
#include "swift/AST/ProtocolConformance.h"
|
|
#include "swift/AST/SourceFile.h"
|
|
#include "swift/AST/TypeVisitor.h"
|
|
#include "swift/Basic/Defer.h"
|
|
#include "swift/Basic/QuotedString.h"
|
|
#include "swift/Basic/STLExtras.h"
|
|
#include "clang/AST/Type.h"
|
|
#include "llvm/ADT/APFloat.h"
|
|
#include "llvm/ADT/Optional.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/ADT/StringExtras.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Support/Process.h"
|
|
#include "llvm/Support/SaveAndRestore.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
//
|
|
// AST DUMPING TIPS
|
|
// ================
|
|
//
|
|
// * Pass values before names (because names are often optional and can be
|
|
// omitted or empty).
|
|
//
|
|
// * Put all `printField*()` and `printFlag*()` calls before `printRec()` calls.
|
|
// `printRec()` variants print a child node, and all fields of the current
|
|
// node need to be printed before any child node is printed.
|
|
//
|
|
// * `printField()` expects a "simple" argument that will be converted to a
|
|
// keyword string by passing it through `getDumpString()`. For values that are
|
|
// at all complicated, use `printFieldQuoted()`, which will automatically
|
|
// quote and escape the value.
|
|
//
|
|
// * Confine all direct formatting for the console (e.g. printing quotes or
|
|
// parentheses) in `PrintBase`. Eventually we want to allow e.g. JSON dumping;
|
|
// limiting the amount of direct I/O helps us with that.
|
|
//
|
|
|
|
using namespace swift;
|
|
|
|
struct TerminalColor {
|
|
llvm::raw_ostream::Colors Color;
|
|
bool Bold;
|
|
};
|
|
|
|
#define DEF_COLOR(NAME, COLOR, BOLD) \
|
|
static const TerminalColor NAME##Color = { llvm::raw_ostream::COLOR, BOLD };
|
|
|
|
DEF_COLOR(Func, YELLOW, false)
|
|
DEF_COLOR(Range, YELLOW, false)
|
|
DEF_COLOR(AccessLevel, YELLOW, false)
|
|
DEF_COLOR(ASTNode, YELLOW, true)
|
|
DEF_COLOR(Parameter, YELLOW, false)
|
|
DEF_COLOR(Extension, MAGENTA, false)
|
|
DEF_COLOR(Pattern, RED, true)
|
|
DEF_COLOR(Override, RED, false)
|
|
DEF_COLOR(Stmt, RED, true)
|
|
DEF_COLOR(Captures, RED, false)
|
|
DEF_COLOR(Arguments, RED, false)
|
|
DEF_COLOR(TypeRepr, GREEN, false)
|
|
DEF_COLOR(LiteralValue, GREEN, false)
|
|
DEF_COLOR(Decl, GREEN, true)
|
|
DEF_COLOR(Parenthesis, BLUE, false)
|
|
DEF_COLOR(Type, BLUE, false)
|
|
DEF_COLOR(Discriminator, BLUE, false)
|
|
DEF_COLOR(InterfaceType, GREEN, false)
|
|
DEF_COLOR(Identifier, GREEN, false)
|
|
DEF_COLOR(Expr, MAGENTA, true)
|
|
DEF_COLOR(ExprModifier, CYAN, false)
|
|
DEF_COLOR(DeclModifier, CYAN, false)
|
|
DEF_COLOR(ArgModifier, CYAN, false)
|
|
DEF_COLOR(ClosureModifier, CYAN, false)
|
|
DEF_COLOR(FieldLabel, CYAN, false)
|
|
DEF_COLOR(Location, CYAN, false)
|
|
|
|
#undef DEF_COLOR
|
|
|
|
namespace {
|
|
/// RAII object that prints with the given color, if color is supported on the
|
|
/// given stream.
|
|
class PrintWithColorRAII {
|
|
raw_ostream &OS;
|
|
bool ShowColors;
|
|
|
|
public:
|
|
PrintWithColorRAII(raw_ostream &os, TerminalColor color)
|
|
: OS(os), ShowColors(false)
|
|
{
|
|
ShowColors = os.has_colors();
|
|
|
|
if (ShowColors)
|
|
OS.changeColor(color.Color, color.Bold);
|
|
}
|
|
|
|
~PrintWithColorRAII() {
|
|
if (ShowColors) {
|
|
OS.resetColor();
|
|
}
|
|
}
|
|
|
|
raw_ostream &getOS() const { return OS; }
|
|
|
|
template<typename T>
|
|
friend raw_ostream &operator<<(PrintWithColorRAII &&printer,
|
|
const T &value){
|
|
printer.OS << value;
|
|
return printer.OS;
|
|
}
|
|
|
|
};
|
|
|
|
/// Wraps a \c raw_ostream so that anything printed through it is automatically
|
|
/// escaped appropriately for a double-quoted string.
|
|
class escaping_ostream : public raw_ostream {
|
|
raw_ostream &base_os;
|
|
|
|
public:
|
|
escaping_ostream(raw_ostream &base_os)
|
|
: raw_ostream(/*unbuffered=*/true), base_os(base_os)
|
|
{}
|
|
|
|
virtual ~escaping_ostream() {}
|
|
|
|
virtual void reserveExtraSpace(uint64_t ExtraSize) override {
|
|
base_os.reserveExtraSpace(ExtraSize);
|
|
}
|
|
|
|
virtual raw_ostream &changeColor(enum Colors Color, bool Bold = false,
|
|
bool BG = false) override {
|
|
return base_os.changeColor(Color, Bold, BG);
|
|
}
|
|
|
|
virtual raw_ostream &resetColor() override {
|
|
return base_os.resetColor();
|
|
}
|
|
|
|
virtual raw_ostream &reverseColor() override {
|
|
return base_os.reverseColor();
|
|
}
|
|
|
|
virtual bool is_displayed() const override {
|
|
return base_os.is_displayed();
|
|
}
|
|
|
|
virtual bool has_colors() const override {
|
|
return base_os.has_colors();
|
|
}
|
|
|
|
virtual void enable_colors(bool enable) override {
|
|
base_os.enable_colors(enable);
|
|
}
|
|
|
|
private:
|
|
virtual void write_impl(const char *Ptr, size_t Size) override {
|
|
base_os.write_escaped(StringRef(Ptr, Size), /*UseHexEscapes=*/true);
|
|
}
|
|
|
|
virtual uint64_t current_pos() const override {
|
|
return base_os.tell();
|
|
}
|
|
|
|
virtual void anchor() override {}
|
|
};
|
|
} // end anonymous namespace
|
|
|
|
static StringRef getDumpString(SILFunctionType::Representation value) {
|
|
switch (value) {
|
|
case SILFunctionType::Representation::Thick: return "thick";
|
|
case SILFunctionType::Representation::Block: return "block";
|
|
case SILFunctionType::Representation::CFunctionPointer: return "c";
|
|
case SILFunctionType::Representation::CXXMethod:
|
|
return "cxx_method";
|
|
case SILFunctionType::Representation::Thin: return "thin";
|
|
case SILFunctionType::Representation::Method: return "method";
|
|
case SILFunctionType::Representation::ObjCMethod: return "objc_method";
|
|
case SILFunctionType::Representation::WitnessMethod: return "witness_method";
|
|
case SILFunctionType::Representation::Closure: return "closure";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
|
|
}
|
|
|
|
static StringRef getDumpString(ReadImplKind kind) {
|
|
switch (kind) {
|
|
case ReadImplKind::Stored:
|
|
return "stored";
|
|
case ReadImplKind::Inherited:
|
|
return "inherited";
|
|
case ReadImplKind::Get:
|
|
return "getter";
|
|
case ReadImplKind::Address:
|
|
return "addressor";
|
|
case ReadImplKind::Read:
|
|
return "read_coroutine";
|
|
}
|
|
llvm_unreachable("bad kind");
|
|
}
|
|
|
|
static StringRef getDumpString(WriteImplKind kind) {
|
|
switch (kind) {
|
|
case WriteImplKind::Immutable:
|
|
return "immutable";
|
|
case WriteImplKind::Stored:
|
|
return "stored";
|
|
case WriteImplKind::StoredWithObservers:
|
|
return "stored_with_observers";
|
|
case WriteImplKind::InheritedWithObservers:
|
|
return "inherited_with_observers";
|
|
case WriteImplKind::Set:
|
|
return "setter";
|
|
case WriteImplKind::MutableAddress:
|
|
return "mutable_addressor";
|
|
case WriteImplKind::Modify:
|
|
return "modify_coroutine";
|
|
}
|
|
llvm_unreachable("bad kind");
|
|
}
|
|
|
|
static StringRef getDumpString(ReadWriteImplKind kind) {
|
|
switch (kind) {
|
|
case ReadWriteImplKind::Immutable:
|
|
return "immutable";
|
|
case ReadWriteImplKind::Stored:
|
|
return "stored";
|
|
case ReadWriteImplKind::MutableAddress:
|
|
return "mutable_addressor";
|
|
case ReadWriteImplKind::MaterializeToTemporary:
|
|
return "materialize_to_temporary";
|
|
case ReadWriteImplKind::Modify:
|
|
return "modify_coroutine";
|
|
case ReadWriteImplKind::StoredWithDidSet:
|
|
return "stored_with_didset";
|
|
case ReadWriteImplKind::InheritedWithDidSet:
|
|
return "inherited_with_didset";
|
|
}
|
|
llvm_unreachable("bad kind");
|
|
}
|
|
|
|
static StringRef getDumpString(ImportKind value) {
|
|
switch (value) {
|
|
case ImportKind::Module: return "module";
|
|
case ImportKind::Type: return "type";
|
|
case ImportKind::Struct: return "struct";
|
|
case ImportKind::Class: return "class";
|
|
case ImportKind::Enum: return "enum";
|
|
case ImportKind::Protocol: return "protocol";
|
|
case ImportKind::Var: return "var";
|
|
case ImportKind::Func: return "func";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled ImportKind in switch.");
|
|
}
|
|
|
|
static StringRef getDumpString(ForeignErrorConvention::Kind value) {
|
|
switch (value) {
|
|
case ForeignErrorConvention::ZeroResult: return "ZeroResult";
|
|
case ForeignErrorConvention::NonZeroResult: return "NonZeroResult";
|
|
case ForeignErrorConvention::ZeroPreservedResult: return "ZeroPreservedResult";
|
|
case ForeignErrorConvention::NilResult: return "NilResult";
|
|
case ForeignErrorConvention::NonNilError: return "NonNilError";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled ForeignErrorConvention in switch.");
|
|
}
|
|
static StringRef getDumpString(DefaultArgumentKind value) {
|
|
switch (value) {
|
|
case DefaultArgumentKind::None: return "none";
|
|
#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \
|
|
case DefaultArgumentKind::NAME: return STRING;
|
|
#include "swift/AST/MagicIdentifierKinds.def"
|
|
case DefaultArgumentKind::Inherited: return "inherited";
|
|
case DefaultArgumentKind::NilLiteral: return "nil";
|
|
case DefaultArgumentKind::EmptyArray: return "[]";
|
|
case DefaultArgumentKind::EmptyDictionary: return "[:]";
|
|
case DefaultArgumentKind::Normal: return "normal";
|
|
case DefaultArgumentKind::StoredProperty: return "stored property";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled DefaultArgumentKind in switch.");
|
|
}
|
|
static StringRef getDumpString(ObjCSelectorExpr::ObjCSelectorKind value) {
|
|
switch (value) {
|
|
case ObjCSelectorExpr::Method: return "method";
|
|
case ObjCSelectorExpr::Getter: return "getter";
|
|
case ObjCSelectorExpr::Setter: return "setter";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled ObjCSelectorExpr in switch.");
|
|
}
|
|
static StringRef getDumpString(AccessSemantics value) {
|
|
switch (value) {
|
|
case AccessSemantics::Ordinary: return "ordinary";
|
|
case AccessSemantics::DirectToStorage: return "direct_to_storage";
|
|
case AccessSemantics::DirectToImplementation: return "direct_to_impl";
|
|
case AccessSemantics::DistributedThunk: return "distributed_thunk";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled AccessSemantics in switch.");
|
|
}
|
|
static StringRef getDumpString(MetatypeRepresentation value) {
|
|
switch (value) {
|
|
case MetatypeRepresentation::Thin: return "thin";
|
|
case MetatypeRepresentation::Thick: return "thick";
|
|
case MetatypeRepresentation::ObjC: return "@objc";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled MetatypeRepresentation in switch.");
|
|
}
|
|
static StringRef getDumpString(StringLiteralExpr::Encoding value) {
|
|
switch (value) {
|
|
case StringLiteralExpr::UTF8: return "utf8";
|
|
case StringLiteralExpr::OneUnicodeScalar: return "unicodeScalar";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled StringLiteral in switch.");
|
|
}
|
|
static StringRef getDumpString(CtorInitializerKind value) {
|
|
switch (value) {
|
|
case CtorInitializerKind::Designated: return "designated";
|
|
case CtorInitializerKind::Convenience: return "convenience";
|
|
case CtorInitializerKind::ConvenienceFactory: return "convenience_factory";
|
|
case CtorInitializerKind::Factory: return "factory";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled CtorInitializerKind in switch.");
|
|
}
|
|
static StringRef getDumpString(Associativity value) {
|
|
switch (value) {
|
|
case Associativity::None: return "none";
|
|
case Associativity::Left: return "left";
|
|
case Associativity::Right: return "right";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled Associativity in switch.");
|
|
}
|
|
static StringRef getDumpString(CheckedCastKind kind) {
|
|
return getCheckedCastKindName(kind);
|
|
}
|
|
static StringRef getDumpString(bool value) {
|
|
return value ? "true" : "false";
|
|
}
|
|
static StringRef getDumpString(AccessLevel level) {
|
|
return getAccessLevelSpelling(level);
|
|
}
|
|
static StringRef getDumpString(LifetimeAnnotation lifetime) {
|
|
switch (lifetime) {
|
|
case LifetimeAnnotation::EagerMove:
|
|
return "_eagerMove";
|
|
case LifetimeAnnotation::Lexical:
|
|
return "_lexical";
|
|
case LifetimeAnnotation::None:
|
|
return "";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled LifetimeAnnotation in switch.");
|
|
}
|
|
static StringRef getDumpString(AccessorKind kind) {
|
|
return getAccessorKindString(kind);
|
|
}
|
|
static StringRef getDumpString(MagicIdentifierLiteralExpr::Kind kind) {
|
|
return MagicIdentifierLiteralExpr::getKindString(kind);
|
|
}
|
|
static StringRef getDumpString(ObjectLiteralExpr::LiteralKind kind) {
|
|
return ObjectLiteralExpr::getLiteralKindPlainName(kind);
|
|
}
|
|
static StringRef getDumpString(FunctionRefKind kind) {
|
|
return getFunctionRefKindStr(kind);
|
|
}
|
|
static StringRef getDumpString(ParamSpecifier specifier) {
|
|
return ParamDecl::getSpecifierSpelling(specifier);
|
|
}
|
|
static StringRef getDumpString(ValueOwnership ownership) {
|
|
switch (ownership) {
|
|
case ValueOwnership::Default:
|
|
return "";
|
|
case ValueOwnership::Owned:
|
|
return "owned";
|
|
case ValueOwnership::Shared:
|
|
return "shared";
|
|
case ValueOwnership::InOut:
|
|
return "inout";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled ValueOwnership in switch.");
|
|
}
|
|
static StringRef getDumpString(ForeignErrorConvention::IsOwned_t owned) {
|
|
switch (owned) {
|
|
case swift::ForeignErrorConvention::IsNotOwned:
|
|
return "unowned";
|
|
case swift::ForeignErrorConvention::IsOwned:
|
|
return "owned";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled ForeignErrorConvention::IsOwned_t in switch.");
|
|
}
|
|
static StringRef getDumpString(RequirementKind kind) {
|
|
switch (kind) {
|
|
case RequirementKind::SameShape: return "same_shape";
|
|
case RequirementKind::Conformance: return "conforms_to";
|
|
case RequirementKind::Layout: return "has_layout";
|
|
case RequirementKind::Superclass: return "subclass_of";
|
|
case RequirementKind::SameType: return "same_type";
|
|
}
|
|
|
|
llvm_unreachable("Unhandled RequirementKind in switch.");
|
|
}
|
|
static unsigned getDumpString(unsigned value) {
|
|
return value;
|
|
}
|
|
static size_t getDumpString(size_t value) {
|
|
return value;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Decl printing.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Print a name.
|
|
static void printName(raw_ostream &os, DeclName name) {
|
|
if (!name)
|
|
os << "<anonymous>";
|
|
else
|
|
os << name;
|
|
}
|
|
|
|
static Type defaultGetTypeOfExpr(Expr *E) { return E->getType(); }
|
|
static Type defaultGetTypeOfKeyPathComponent(KeyPathExpr *E, unsigned index) {
|
|
return E->getComponents()[index].getComponentType();
|
|
}
|
|
|
|
using VisitedConformances = llvm::SmallPtrSetImpl<const ProtocolConformance *>;
|
|
|
|
namespace {
|
|
/// PrintBase - Base type for recursive structured dumps of AST nodes.
|
|
///
|
|
/// Please keep direct I/O, especially of structural elements like
|
|
/// parentheses and quote marks, confined to this base class. This will help
|
|
/// if we eventually support alternate output formats for AST dumps.
|
|
class PrintBase {
|
|
raw_ostream &OS;
|
|
unsigned Indent;
|
|
public:
|
|
llvm::function_ref<Type(Expr *)> GetTypeOfExpr;
|
|
llvm::function_ref<Type(TypeRepr *)> GetTypeOfTypeRepr;
|
|
llvm::function_ref<Type(KeyPathExpr *E, unsigned index)>
|
|
GetTypeOfKeyPathComponent;
|
|
char quote = '"';
|
|
|
|
explicit PrintBase(raw_ostream &os, unsigned indent = 0,
|
|
llvm::function_ref<Type(Expr *)> getTypeOfExpr = defaultGetTypeOfExpr,
|
|
llvm::function_ref<Type(TypeRepr *)> getTypeOfTypeRepr = nullptr,
|
|
llvm::function_ref<Type(KeyPathExpr *E, unsigned index)>
|
|
getTypeOfKeyPathComponent =
|
|
defaultGetTypeOfKeyPathComponent)
|
|
: OS(os), Indent(indent), GetTypeOfExpr(getTypeOfExpr),
|
|
GetTypeOfTypeRepr(getTypeOfTypeRepr),
|
|
GetTypeOfKeyPathComponent(getTypeOfKeyPathComponent) { }
|
|
|
|
bool hasNonStandardOutput() {
|
|
return &OS != &llvm::errs() && &OS != &llvm::dbgs();
|
|
}
|
|
|
|
/// Call `Body` in a context where the printer is ready for a child to be printed.
|
|
template <typename Fn>
|
|
void printRecArbitrary(Fn Body, StringRef label = "") {
|
|
Indent += 2;
|
|
OS << '\n';
|
|
Body(label);
|
|
Indent -= 2;
|
|
}
|
|
|
|
/// Print a declaration as a child node.
|
|
void printRec(Decl *D, StringRef label = "");
|
|
|
|
/// Print an expression as a child node.
|
|
void printRec(Expr *E, StringRef label = "");
|
|
|
|
/// Print a statement as a child node.
|
|
void printRec(Stmt *S, const ASTContext *Ctx, StringRef label = "");
|
|
|
|
/// Print a type representation as a child node.
|
|
void printRec(TypeRepr *T, StringRef label = "");
|
|
|
|
/// Print a pattern as a child node.
|
|
void printRec(const Pattern *P, StringRef label = "");
|
|
|
|
/// Print a type as a child node.
|
|
void printRec(Type ty, StringRef label = "");
|
|
|
|
/// Print an \c ASTNode as a child node.
|
|
void printRec(const ASTNode &Elt, const ASTContext *Ctx,
|
|
StringRef label = "") {
|
|
if (auto *SubExpr = Elt.dyn_cast<Expr*>())
|
|
printRec(SubExpr, label);
|
|
else if (auto *SubStmt = Elt.dyn_cast<Stmt*>())
|
|
printRec(SubStmt, Ctx, label);
|
|
else
|
|
printRec(Elt.get<Decl*>(), label);
|
|
}
|
|
|
|
/// Print a statement condition element as a child node.
|
|
void printRec(StmtConditionElement C, const ASTContext *Ctx,
|
|
StringRef Label = "") {
|
|
switch (C.getKind()) {
|
|
case StmtConditionElement::CK_Boolean:
|
|
return printRec(C.getBoolean());
|
|
case StmtConditionElement::CK_PatternBinding:
|
|
printRecArbitrary([&](StringRef Label) {
|
|
printHead("pattern", PatternColor, Label);
|
|
printRec(C.getPattern());
|
|
printRec(C.getInitializer());
|
|
printFoot();
|
|
}, Label);
|
|
break;
|
|
case StmtConditionElement::CK_Availability:
|
|
printRecArbitrary([&](StringRef Label) {
|
|
printHead("#available", PatternColor, Label);
|
|
for (auto *Query : C.getAvailability()->getQueries()) {
|
|
OS << '\n';
|
|
switch (Query->getKind()) {
|
|
case AvailabilitySpecKind::PlatformVersionConstraint:
|
|
cast<PlatformVersionConstraintAvailabilitySpec>(Query)->print(OS, Indent + 2);
|
|
break;
|
|
case AvailabilitySpecKind::LanguageVersionConstraint:
|
|
case AvailabilitySpecKind::PackageDescriptionVersionConstraint:
|
|
cast<PlatformVersionConstraintAvailabilitySpec>(Query)->print(OS, Indent + 2);
|
|
break;
|
|
case AvailabilitySpecKind::OtherPlatform:
|
|
cast<OtherPlatformAvailabilitySpec>(Query)->print(OS, Indent + 2);
|
|
break;
|
|
}
|
|
}
|
|
printFoot();
|
|
}, Label);
|
|
break;
|
|
case StmtConditionElement::CK_HasSymbol:
|
|
printRecArbitrary([&](StringRef Label) {
|
|
printHead("#_hasSymbol", PatternColor, Label);
|
|
printSourceRange(C.getSourceRange(), Ctx);
|
|
printRec(C.getHasSymbolInfo()->getSymbolExpr());
|
|
printFoot();
|
|
}, Label);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// Print a range of nodes as a single "array" child node.
|
|
template <typename NodeRange>
|
|
void printRecRange(const NodeRange &range, StringRef topLabel) {
|
|
printRecArbitrary([&](StringRef topLabel) {
|
|
printHead("array", ASTNodeColor, topLabel);
|
|
for (auto node : range) {
|
|
printRec(node, "");
|
|
}
|
|
printFoot();
|
|
}, topLabel);
|
|
}
|
|
|
|
/// Print a range of nodes as a single "array" child node.
|
|
template <typename NodeRange>
|
|
void printRecRange(const NodeRange &range, const ASTContext *Ctx, StringRef topLabel) {
|
|
printRecArbitrary([&](StringRef topLabel) {
|
|
printHead("array", ASTNodeColor, topLabel);
|
|
for (auto node : range) {
|
|
printRec(node, Ctx, "");
|
|
}
|
|
printFoot();
|
|
}, topLabel);
|
|
}
|
|
|
|
/// Print the beginning of a new node, including its type and an optional label for it.
|
|
void printHead(StringRef Name, TerminalColor Color,
|
|
StringRef Label = "") {
|
|
OS.indent(Indent);
|
|
PrintWithColorRAII(OS, ParenthesisColor) << '(';
|
|
if (!Label.empty()) {
|
|
PrintWithColorRAII(OS, FieldLabelColor) << Label;
|
|
OS << "=";
|
|
}
|
|
|
|
PrintWithColorRAII(OS, Color) << Name;
|
|
}
|
|
|
|
/// Print the end of a new node.
|
|
void printFoot() {
|
|
PrintWithColorRAII(OS, ParenthesisColor) << ')';
|
|
}
|
|
|
|
/// Print a single argument as a child node.
|
|
void printRec(const Argument &arg) {
|
|
printRecArbitrary([&](StringRef L) {
|
|
printHead("argument", ExprColor, L);
|
|
|
|
auto label = arg.getLabel();
|
|
if (!label.empty()) {
|
|
printFieldQuoted(label.str(), "label", ArgumentsColor);
|
|
}
|
|
printFlag(arg.isInOut(), "inout", ArgModifierColor);
|
|
|
|
printRec(arg.getExpr());
|
|
printFoot();
|
|
});
|
|
}
|
|
|
|
/// Print an argument list as a child node.
|
|
void printRec(const ArgumentList *argList, StringRef label = "") {
|
|
printRecArbitrary([&](StringRef label) {
|
|
visitArgumentList(argList, label);
|
|
}, label);
|
|
}
|
|
|
|
/// Print an argument list node.
|
|
void visitArgumentList(const ArgumentList *argList, StringRef label = "") {
|
|
printHead("argument_list", ExprColor, label);
|
|
|
|
printFlag(argList->isImplicit(), "implicit", ArgModifierColor);
|
|
|
|
if (argList->hasAnyArgumentLabels()) {
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
for (auto arg : *argList) {
|
|
auto label = arg.getLabel();
|
|
OS << (label.empty() ? "_" : label.str()) << ":";
|
|
}
|
|
}, "labels", ArgumentsColor);
|
|
}
|
|
|
|
for (auto arg : *argList) {
|
|
printRec(arg);
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
/// Print a parameter list as a child node.
|
|
void printRec(const ParameterList *params, const ASTContext *ctx = nullptr,
|
|
StringRef label = "") {
|
|
printRecArbitrary([&](StringRef label) {
|
|
visitParameterList(params, ctx, label);
|
|
}, label);
|
|
}
|
|
|
|
/// Print a parameter list node.
|
|
void visitParameterList(const ParameterList *params,
|
|
const ASTContext *ctx = nullptr,
|
|
StringRef label = "") {
|
|
printHead("parameter_list", ParameterColor, label);
|
|
|
|
if (!ctx && params->size() != 0 && params->get(0))
|
|
ctx = ¶ms->get(0)->getASTContext();
|
|
printSourceRange(params->getSourceRange(), ctx);
|
|
|
|
for (auto P : *params) {
|
|
printRec(const_cast<ParamDecl *>(P));
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
/// Print an \c IfConfigClause as a child node.
|
|
void printRec(const IfConfigClause &Clause, const ASTContext *Ctx = nullptr,
|
|
StringRef Label = "") {
|
|
printRecArbitrary([&](StringRef Label) {
|
|
printHead((Clause.Cond ? "#if:" : "#else:"), StmtColor, Label);
|
|
|
|
printFlag(Clause.isActive, "active", DeclModifierColor);
|
|
|
|
if (Clause.Cond) {
|
|
printRec(Clause.Cond);
|
|
}
|
|
printRecRange(Clause.Elements, Ctx, "elements");
|
|
|
|
printFoot();
|
|
}, Label);
|
|
}
|
|
|
|
/// Print a substitution map as a child node.
|
|
void printRec(SubstitutionMap map, StringRef label = "") {
|
|
SmallPtrSet<const ProtocolConformance *, 4> Dumped;
|
|
printRec(map, Dumped, label);
|
|
}
|
|
|
|
/// Print a substitution map as a child node.
|
|
void printRec(SubstitutionMap map, VisitedConformances &visited,
|
|
StringRef label = "");
|
|
|
|
/// Print a substitution map as a child node.
|
|
void printRec(const ProtocolConformanceRef &conf,
|
|
VisitedConformances &visited, StringRef label = "");
|
|
|
|
/// Print a conformance reference as a child node.
|
|
void printRec(const ProtocolConformanceRef &conf, StringRef label = "") {
|
|
SmallPtrSet<const ProtocolConformance *, 4> Dumped;
|
|
printRec(conf, Dumped, label);
|
|
}
|
|
|
|
/// Print a conformance reference as a child node.
|
|
void printRec(const ProtocolConformance *conformance,
|
|
VisitedConformances &visited, StringRef label = "");
|
|
|
|
/// Print a requirement node.
|
|
void visitRequirement(const Requirement &requirement, StringRef label = "") {
|
|
printHead("requirement", ASTNodeColor, label);
|
|
|
|
PrintOptions opts;
|
|
opts.ProtocolQualifiedDependentMemberTypes = true;
|
|
|
|
printFieldQuotedRaw([&](raw_ostream &out) {
|
|
requirement.getFirstType().print(out, opts);
|
|
}, "");
|
|
|
|
printField(requirement.getKind(), "");
|
|
|
|
if (requirement.getKind() != RequirementKind::Layout
|
|
&& requirement.getSecondType())
|
|
printFieldQuotedRaw([&](raw_ostream &out) {
|
|
requirement.getSecondType().print(out, opts);
|
|
}, "");
|
|
else if (requirement.getLayoutConstraint())
|
|
printFieldQuoted(requirement.getLayoutConstraint(), "");
|
|
|
|
printFoot();
|
|
}
|
|
|
|
/// Print a requirement as a child node.
|
|
void printRec(const Requirement &requirement, StringRef label = "") {
|
|
printRecArbitrary([&](StringRef label) {
|
|
visitRequirement(requirement);
|
|
});
|
|
}
|
|
|
|
/// Print a field with a short keyword-style value, printing the value by
|
|
/// passing a closure that takes a \c raw_ostream.
|
|
template<typename Fn>
|
|
void printFieldRaw(Fn body, StringRef name,
|
|
TerminalColor color = FieldLabelColor) {
|
|
OS << " ";
|
|
if (!name.empty())
|
|
PrintWithColorRAII(OS, color) << name << "=";
|
|
body(PrintWithColorRAII(OS, color).getOS());
|
|
}
|
|
|
|
/// Print a field with a short keyword-style value. The value will be
|
|
/// formatted using a \c getDumpString() overload.
|
|
template<typename T>
|
|
void printField(const T &value, StringRef name,
|
|
TerminalColor color = FieldLabelColor) {
|
|
printFieldRaw([&](raw_ostream &OS) { OS << getDumpString(value); },
|
|
name, color);
|
|
}
|
|
|
|
/// Print a field with a long value that will be automatically quoted and
|
|
/// escaped, printing the value by passing a closure that takes a
|
|
/// \c raw_ostream.
|
|
template<typename Fn>
|
|
void printFieldQuotedRaw(Fn body, StringRef name,
|
|
TerminalColor color = FieldLabelColor) {
|
|
printFieldRaw([&](raw_ostream &OS) {
|
|
OS << quote;
|
|
{ escaping_ostream escOS(OS); body(escOS); }
|
|
OS << quote;
|
|
}, name, color);
|
|
}
|
|
|
|
/// Print a field with a long value that will be automatically quoted and
|
|
/// escaped.
|
|
template<typename T>
|
|
void printFieldQuoted(const T &value, StringRef name,
|
|
TerminalColor color = FieldLabelColor) {
|
|
printFieldQuotedRaw([&](raw_ostream &OS) { OS << value; }, name, color);
|
|
}
|
|
|
|
/// Print a simple boolean value, printing the value by passing a closure
|
|
/// that takes a \c raw_ostream.
|
|
template<typename Fn>
|
|
void printFlagRaw(Fn body, TerminalColor color = FieldLabelColor) {
|
|
printFieldRaw(body, "", color);
|
|
}
|
|
|
|
/// Print a simple boolean value unconditionally.
|
|
void printFlag(StringRef name, TerminalColor color = FieldLabelColor) {
|
|
printFieldRaw([&](raw_ostream &OS) { OS << name; }, "", color);
|
|
}
|
|
|
|
/// Print a simple boolean value.
|
|
void printFlag(bool isSet, StringRef name,
|
|
TerminalColor color = FieldLabelColor) {
|
|
if (isSet)
|
|
printFlag(name, color);
|
|
}
|
|
|
|
/// Print a field containing a node's source location.
|
|
void printSourceLoc(const SourceLoc L, const ASTContext *Ctx,
|
|
StringRef label = "location") {
|
|
if (!L.isValid() || !Ctx)
|
|
return;
|
|
|
|
printFieldRaw([&](raw_ostream &OS) {
|
|
escaping_ostream escOS(OS);
|
|
L.print(escOS, Ctx->SourceMgr);
|
|
}, label, LocationColor);
|
|
}
|
|
|
|
/// Print a field containing a node's source range.
|
|
void printSourceRange(const SourceRange R, const ASTContext *Ctx) {
|
|
if (!R.isValid() || !Ctx)
|
|
return;
|
|
|
|
printFieldRaw([&](raw_ostream &OS) {
|
|
escaping_ostream escOS(OS);
|
|
R.print(escOS, Ctx->SourceMgr, /*PrintText=*/false);
|
|
}, "range", RangeColor);
|
|
}
|
|
|
|
/// Print a field containing a node's name, printing the node's name by
|
|
/// passing a closure that takes a \c raw_ostream.
|
|
template <typename Fn>
|
|
void printNameRaw(Fn body, bool leadingSpace = true) {
|
|
if (leadingSpace)
|
|
OS << ' ';
|
|
PrintWithColorRAII colored(OS, IdentifierColor);
|
|
OS << quote;
|
|
{
|
|
escaping_ostream escaping_os(OS);
|
|
body(escaping_os);
|
|
}
|
|
OS << quote;
|
|
}
|
|
|
|
/// Print a field containing a node's name.
|
|
void printName(DeclName name, bool leadingSpace = true) {
|
|
printNameRaw([&](raw_ostream &OS) {
|
|
::printName(OS, name);
|
|
}, leadingSpace);
|
|
}
|
|
|
|
/// Print an unnamed field containing a node's name, read from a declaration.
|
|
void printDeclName(const ValueDecl *D, bool leadingSpace = true) {
|
|
if (D->getName()) {
|
|
printName(D->getName(), leadingSpace);
|
|
} else {
|
|
if (leadingSpace)
|
|
OS << ' ';
|
|
PrintWithColorRAII(OS, IdentifierColor)
|
|
<< "<anonymous @ " << (const void*)D << '>';
|
|
}
|
|
}
|
|
|
|
/// Print a field containing a node's name, read from a declaration.
|
|
void printDeclNameField(const ValueDecl *D, StringRef name) {
|
|
printFieldRaw([&](raw_ostream &os) {
|
|
printDeclName(D, /*leadingSpace=*/false);
|
|
}, name);
|
|
}
|
|
|
|
/// Print a field containing a concrete reference to a declaration.
|
|
void printDeclRefField(ConcreteDeclRef declRef, StringRef label,
|
|
TerminalColor Color = DeclColor) {
|
|
printFieldQuotedRaw([&](raw_ostream &OS) { declRef.dump(OS); }, label,
|
|
Color);
|
|
}
|
|
};
|
|
|
|
class PrintPattern : public PatternVisitor<PrintPattern, void, StringRef>,
|
|
public PrintBase {
|
|
public:
|
|
using PrintBase::PrintBase;
|
|
|
|
void printCommon(Pattern *P, const char *Name, StringRef Label) {
|
|
printHead(Name, PatternColor, Label);
|
|
|
|
printFlag(P->isImplicit(), "implicit", ExprModifierColor);
|
|
|
|
if (P->hasType()) {
|
|
printFieldQuoted(P->getType(), "type", TypeColor);
|
|
}
|
|
}
|
|
|
|
void visitParenPattern(ParenPattern *P, StringRef label) {
|
|
printCommon(P, "pattern_paren", label);
|
|
printRec(P->getSubPattern());
|
|
printFoot();
|
|
}
|
|
void visitTuplePattern(TuplePattern *P, StringRef label) {
|
|
printCommon(P, "pattern_tuple", label);
|
|
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
interleave(P->getElements(), OS,
|
|
[&](const TuplePatternElt &elt) {
|
|
auto name = elt.getLabel();
|
|
OS << (name.empty() ? "''" : name.str());
|
|
}, ",");
|
|
}, "names");
|
|
|
|
for (auto &elt : P->getElements()) {
|
|
printRec(elt.getPattern());
|
|
}
|
|
printFoot();
|
|
}
|
|
void visitNamedPattern(NamedPattern *P, StringRef label) {
|
|
printCommon(P, "pattern_named", label);
|
|
printDeclName(P->getDecl());
|
|
printFoot();
|
|
}
|
|
void visitAnyPattern(AnyPattern *P, StringRef label) {
|
|
if (P->isAsyncLet()) {
|
|
printCommon(P, "async_let ", label);
|
|
}
|
|
printCommon(P, "pattern_any", label);
|
|
printFoot();
|
|
}
|
|
void visitTypedPattern(TypedPattern *P, StringRef label) {
|
|
printCommon(P, "pattern_typed", label);
|
|
printRec(P->getSubPattern());
|
|
if (auto *repr = P->getTypeRepr()) {
|
|
printRec(repr);
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitIsPattern(IsPattern *P, StringRef label) {
|
|
printCommon(P, "pattern_is", label);
|
|
printField(P->getCastKind(), "cast_kind");
|
|
printFieldQuoted(P->getCastType(), "cast_to", TypeColor);
|
|
if (auto sub = P->getSubPattern()) {
|
|
printRec(sub);
|
|
}
|
|
printFoot();
|
|
}
|
|
void visitExprPattern(ExprPattern *P, StringRef label) {
|
|
printCommon(P, "pattern_expr", label);
|
|
if (auto m = P->getCachedMatchExpr())
|
|
printRec(m);
|
|
else
|
|
printRec(P->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitBindingPattern(BindingPattern *P, StringRef label) {
|
|
printCommon(P, P->isLet() ? "pattern_let" : "pattern_var", label);
|
|
printRec(P->getSubPattern());
|
|
printFoot();
|
|
}
|
|
void visitEnumElementPattern(EnumElementPattern *P, StringRef label) {
|
|
printCommon(P, "pattern_enum_element", label);
|
|
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
P->getParentType().print(PrintWithColorRAII(OS, TypeColor).getOS());
|
|
OS << '.';
|
|
PrintWithColorRAII(OS, IdentifierColor) << P->getName();
|
|
}, "element");
|
|
|
|
if (P->hasSubPattern()) {
|
|
printRec(P->getSubPattern());
|
|
}
|
|
printFoot();
|
|
}
|
|
void visitOptionalSomePattern(OptionalSomePattern *P, StringRef label) {
|
|
printCommon(P, "pattern_optional_some", label);
|
|
printRec(P->getSubPattern());
|
|
printFoot();
|
|
}
|
|
void visitBoolPattern(BoolPattern *P, StringRef label) {
|
|
printCommon(P, "pattern_bool", label);
|
|
printField(P->getValue(), "value");
|
|
printFoot();
|
|
}
|
|
|
|
};
|
|
|
|
/// PrintDecl - Visitor implementation of Decl::print.
|
|
class PrintDecl : public DeclVisitor<PrintDecl, void, StringRef>,
|
|
public PrintBase {
|
|
public:
|
|
using PrintBase::PrintBase;
|
|
|
|
private:
|
|
void printWhereRequirements(
|
|
PointerUnion<const AssociatedTypeDecl *, const GenericContext *> Owner
|
|
) {
|
|
const auto printWhere = [&](const TrailingWhereClause *Where) {
|
|
if (Where) {
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
Where->print(OS, /*printWhereKeyword*/ false);
|
|
}, "where_requirements");
|
|
}
|
|
};
|
|
|
|
if (const auto GC = Owner.dyn_cast<const GenericContext *>()) {
|
|
printWhere(GC->getTrailingWhereClause());
|
|
} else {
|
|
const auto ATD = Owner.get<const AssociatedTypeDecl *>();
|
|
printWhere(ATD->getTrailingWhereClause());
|
|
}
|
|
}
|
|
|
|
void printCommon(Decl *D, const char *Name, StringRef Label,
|
|
TerminalColor Color = DeclColor) {
|
|
printHead(Name, Color, Label);
|
|
|
|
printFlag(D->isImplicit(), "implicit", DeclModifierColor);
|
|
printFlag(D->isHoisted(), "hoisted", DeclModifierColor);
|
|
printSourceRange(D->getSourceRange(), &D->getASTContext());
|
|
printFlag(D->TrailingSemiLoc.isValid(), "trailing_semi",
|
|
DeclModifierColor);
|
|
}
|
|
|
|
void printInherited(InheritedTypes Inherited) {
|
|
if (Inherited.empty())
|
|
return;
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
interleave(Inherited.getEntries(), OS,
|
|
[&](InheritedEntry Super) { Super.getType().print(OS); },
|
|
", ");
|
|
}, "inherits");
|
|
}
|
|
|
|
public:
|
|
void visitImportDecl(ImportDecl *ID, StringRef label) {
|
|
printCommon(ID, "import_decl", label);
|
|
|
|
printFlag(ID->isExported(), "exported");
|
|
if (ID->getImportKind() != ImportKind::Module)
|
|
printField(ID->getImportKind(), "kind");
|
|
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
// Check if module aliasing was used for the given imported module; for
|
|
// example, if '-module-alias Foo=Bar' was passed and this module has
|
|
// 'import Foo', its corresponding real module name 'Bar' should be printed.
|
|
ImportPath::Builder scratch;
|
|
ID->getRealImportPath(scratch).print(OS);
|
|
}, "module", IdentifierColor);
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitExtensionDecl(ExtensionDecl *ED, StringRef label) {
|
|
printCommon(ED, "extension_decl", label, ExtensionColor);
|
|
printFlag(!ED->hasBeenBound(), "unbound");
|
|
printNameRaw([&](raw_ostream &OS) {
|
|
if (ED->hasBeenBound())
|
|
ED->getExtendedType().print(OS);
|
|
else
|
|
ED->getExtendedTypeRepr()->print(OS);
|
|
});
|
|
printCommonPost(ED);
|
|
}
|
|
|
|
void visitTypeAliasDecl(TypeAliasDecl *TAD, StringRef label) {
|
|
printCommon(TAD, "typealias", label);
|
|
|
|
if (auto underlying = TAD->getCachedUnderlyingType()) {
|
|
printFieldQuoted(underlying, "type", TypeColor);
|
|
} else {
|
|
printFlag("unresolved_type", TypeColor);
|
|
}
|
|
printWhereRequirements(TAD);
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitOpaqueTypeDecl(OpaqueTypeDecl *OTD, StringRef label) {
|
|
printCommon(OTD, "opaque_type", label);
|
|
|
|
printDeclNameField(OTD->getNamingDecl(), "naming_decl");
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
OS << OTD->getDeclaredInterfaceType() << " in "
|
|
<< OTD->getOpaqueInterfaceGenericSignature()->getAsString();
|
|
|
|
}, "opaque_interface", TypeColor);
|
|
|
|
if (auto underlyingSubs = OTD->getUniqueUnderlyingTypeSubstitutions()) {
|
|
printRec(*underlyingSubs);
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitGenericTypeParamDecl(GenericTypeParamDecl *decl, StringRef label) {
|
|
printCommon(decl, "generic_type_param", label);
|
|
printField(decl->getDepth(), "depth");
|
|
printField(decl->getIndex(), "index");
|
|
printFoot();
|
|
}
|
|
|
|
void visitAssociatedTypeDecl(AssociatedTypeDecl *decl, StringRef label) {
|
|
printCommon(decl, "associated_type_decl", label);
|
|
if (auto defaultDef = decl->getDefaultDefinitionType()) {
|
|
printFieldQuoted(defaultDef, "default");
|
|
}
|
|
printWhereRequirements(decl);
|
|
if (decl->overriddenDeclsComputed()) {
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
interleave(decl->getOverriddenDecls(), OS,
|
|
[&](AssociatedTypeDecl *overridden) {
|
|
OS << overridden->getProtocol()->getName();
|
|
}, ", ");
|
|
}, "overridden");
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitProtocolDecl(ProtocolDecl *PD, StringRef label) {
|
|
printCommon(PD, "protocol", label);
|
|
|
|
if (PD->isRequirementSignatureComputed()) {
|
|
auto requirements = PD->getRequirementSignatureAsGenericSignature();
|
|
std::string reqSigStr = requirements->getAsString();
|
|
printFieldQuoted(reqSigStr, "requirement_signature");
|
|
} else {
|
|
printFlag("uncomputed_requirement_signature");
|
|
}
|
|
|
|
printCommonPost(PD);
|
|
}
|
|
|
|
void printGenericParameters(GenericParamList *Params) {
|
|
if (!Params)
|
|
return;
|
|
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
Params->print(OS);
|
|
}, "", TypeColor);
|
|
}
|
|
|
|
void printCommon(ValueDecl *VD, const char *Name, StringRef Label,
|
|
TerminalColor Color = DeclColor) {
|
|
printCommon((Decl*)VD, Name, Label, Color);
|
|
|
|
printDeclName(VD);
|
|
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(VD))
|
|
printGenericParameters(AFD->getParsedGenericParams());
|
|
if (auto *GTD = dyn_cast<GenericTypeDecl>(VD))
|
|
printGenericParameters(GTD->getParsedGenericParams());
|
|
if (auto *MD = dyn_cast<MacroDecl>(VD))
|
|
printGenericParameters(MD->getParsedGenericParams());
|
|
|
|
if (VD->hasInterfaceType()) {
|
|
printFieldQuoted(VD->getInterfaceType(), "interface type",
|
|
InterfaceTypeColor);
|
|
}
|
|
|
|
if (VD->hasAccess()) {
|
|
printField(VD->getFormalAccess(), "access", AccessLevelColor);
|
|
}
|
|
|
|
if (VD->overriddenDeclsComputed()) {
|
|
auto overridden = VD->getOverriddenDecls();
|
|
if (!overridden.empty()) {
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
interleave(overridden, OS,
|
|
[&](ValueDecl *overridden) {
|
|
overridden->dumpRef(OS);
|
|
}, ", ");
|
|
}, "override", OverrideColor);
|
|
}
|
|
}
|
|
|
|
auto VarD = dyn_cast<VarDecl>(VD);
|
|
const auto &attrs = VD->getAttrs();
|
|
printFlag(attrs.hasAttribute<FinalAttr>() && !(VarD && VarD->isLet()),
|
|
"final");
|
|
printFlag(attrs.hasAttribute<ObjCAttr>(), "@objc");
|
|
printFlag(attrs.hasAttribute<DynamicAttr>(), "dynamic");
|
|
if (auto *attr = attrs.getAttribute<DynamicReplacementAttr>()) {
|
|
printFlagRaw([&](raw_ostream &OS) {
|
|
OS << "@_dynamicReplacement(for: \"";
|
|
OS << attr->getReplacedFunctionName();
|
|
OS << "\")";
|
|
});
|
|
}
|
|
auto lifetimeString = getDumpString(VD->getLifetimeAnnotation());
|
|
if (!lifetimeString.empty())
|
|
printFlag(lifetimeString);
|
|
}
|
|
|
|
void printCommon(NominalTypeDecl *NTD, const char *Name, StringRef Label,
|
|
TerminalColor Color = DeclColor) {
|
|
printCommon((ValueDecl *)NTD, Name, Label, Color);
|
|
|
|
if (NTD->hasInterfaceType())
|
|
printFlag(NTD->isResilient() ? "resilient" : "non_resilient");
|
|
}
|
|
|
|
void printCommonPost(const IterableDeclContext *IDC) {
|
|
switch (IDC->getIterableContextKind()) {
|
|
case IterableDeclContextKind::NominalTypeDecl: {
|
|
const auto NTD = cast<NominalTypeDecl>(IDC);
|
|
printInherited(NTD->getInherited());
|
|
printWhereRequirements(NTD);
|
|
break;
|
|
}
|
|
case IterableDeclContextKind::ExtensionDecl:
|
|
const auto ED = cast<ExtensionDecl>(IDC);
|
|
printInherited(ED->getInherited());
|
|
printWhereRequirements(ED);
|
|
break;
|
|
}
|
|
|
|
for (Decl *D : IDC->getMembers()) {
|
|
printRec(D);
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitSourceFile(const SourceFile &SF) {
|
|
printHead("source_file", ASTNodeColor);
|
|
printNameRaw([&](raw_ostream &OS) {
|
|
OS << SF.getFilename();
|
|
});
|
|
|
|
if (auto items = SF.getCachedTopLevelItems()) {
|
|
for (auto item : *items) {
|
|
if (item.isImplicit())
|
|
continue;
|
|
|
|
if (auto decl = item.dyn_cast<Decl *>()) {
|
|
printRec(decl);
|
|
} else if (auto stmt = item.dyn_cast<Stmt *>()) {
|
|
printRec(stmt, &SF.getASTContext());
|
|
} else {
|
|
auto expr = item.get<Expr *>();
|
|
printRec(expr);
|
|
}
|
|
}
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitVarDecl(VarDecl *VD, StringRef label) {
|
|
printCommon(VD, "var_decl", label);
|
|
|
|
printFlag(VD->isDistributed(), "distributed", DeclModifierColor);
|
|
printFlag(VD->isLet(), "let", DeclModifierColor);
|
|
printFlag(VD->getAttrs().hasAttribute<LazyAttr>(), "lazy",
|
|
DeclModifierColor);
|
|
printStorageImpl(VD);
|
|
printFlag(VD->getAttrs().hasAttribute<KnownToBeLocalAttr>(),
|
|
"known_to_be_local", DeclModifierColor);
|
|
|
|
printAccessors(VD);
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void printStorageImpl(AbstractStorageDecl *D) {
|
|
printFlag(D->isStatic(), "type", DeclModifierColor);
|
|
|
|
if (D->hasInterfaceType()) {
|
|
auto impl = D->getImplInfo();
|
|
printField(impl.getReadImpl(), "readImpl", DeclModifierColor);
|
|
if (!impl.supportsMutation()) {
|
|
printFlag("immutable", DeclModifierColor);
|
|
} else {
|
|
printField(impl.getWriteImpl(), "writeImpl", DeclModifierColor);
|
|
printField(impl.getReadWriteImpl(), "readWriteImpl",
|
|
DeclModifierColor);
|
|
}
|
|
}
|
|
}
|
|
|
|
void printAccessors(AbstractStorageDecl *D) {
|
|
for (auto accessor : D->getAllAccessors()) {
|
|
printRec(accessor);
|
|
}
|
|
}
|
|
|
|
void visitParamDecl(ParamDecl *PD, StringRef label) {
|
|
printHead("parameter", ParameterColor, label);
|
|
|
|
printDeclName(PD);
|
|
if (!PD->getArgumentName().empty())
|
|
printFieldQuoted(PD->getArgumentName(), "apiName", IdentifierColor);
|
|
if (PD->hasInterfaceType()) {
|
|
printFieldQuoted(PD->getInterfaceType(), "interface type",
|
|
InterfaceTypeColor);
|
|
}
|
|
|
|
if (auto specifier = PD->getCachedSpecifier()) {
|
|
if (*specifier != ParamDecl::Specifier::Default) {
|
|
printFlag(ParamDecl::getSpecifierSpelling(*specifier));
|
|
}
|
|
}
|
|
|
|
if (PD->hasInterfaceType())
|
|
printFlag(PD->isVariadic(), "variadic");
|
|
printFlag(PD->isAutoClosure(), "autoclosure");
|
|
printFlag(PD->getAttrs().hasAttribute<NonEphemeralAttr>(),"nonEphemeral");
|
|
|
|
auto lifetimeString =
|
|
getDumpString(PD->getLifetimeAnnotationFromAttributes());
|
|
if (!lifetimeString.empty())
|
|
printFlag(lifetimeString);
|
|
|
|
printFlag(PD->isNoImplicitCopy(), "noImplicitCopy");
|
|
|
|
if (PD->getDefaultArgumentKind() != DefaultArgumentKind::None) {
|
|
printField(PD->getDefaultArgumentKind(), "default_arg");
|
|
}
|
|
if (PD->hasDefaultExpr() &&
|
|
!PD->getDefaultArgumentCaptureInfo().isTrivial()) {
|
|
printFieldRaw([&](raw_ostream &OS) {
|
|
PD->getDefaultArgumentCaptureInfo().print(OS);
|
|
}, "", CapturesColor);
|
|
}
|
|
|
|
printFlag(PD->getAttrs().hasAttribute<KnownToBeLocalAttr>(),
|
|
"known_to_be_local", DeclModifierColor);
|
|
|
|
if (auto init = PD->getStructuralDefaultExpr()) {
|
|
printRec(init, "expression");
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitParameterList(ParameterList *PL, StringRef label) {
|
|
PrintBase::visitParameterList(PL, /*ctx=*/nullptr, label);
|
|
}
|
|
|
|
void visitEnumCaseDecl(EnumCaseDecl *ECD, StringRef label) {
|
|
printCommon(ECD, "enum_case_decl", label);
|
|
for (EnumElementDecl *D : ECD->getElements()) {
|
|
printRec(D);
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitEnumDecl(EnumDecl *ED, StringRef label) {
|
|
printCommon(ED, "enum_decl", label);
|
|
printCommonPost(ED);
|
|
}
|
|
|
|
void visitEnumElementDecl(EnumElementDecl *EED, StringRef label) {
|
|
printCommon(EED, "enum_element_decl", label);
|
|
if (auto *paramList = EED->getParameterList()) {
|
|
printRec(paramList);
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitStructDecl(StructDecl *SD, StringRef label) {
|
|
printCommon(SD, "struct_decl", label);
|
|
printCommonPost(SD);
|
|
}
|
|
|
|
void visitClassDecl(ClassDecl *CD, StringRef label) {
|
|
printCommon(CD, "class_decl", label);
|
|
|
|
printFlag(CD->isExplicitDistributedActor(), "distributed");
|
|
printFlag(CD->isExplicitActor(), "actor");
|
|
printFlag(CD->getAttrs().hasAttribute<StaticInitializeObjCMetadataAttr>(),
|
|
"@_staticInitializeObjCMetadata");
|
|
|
|
printCommonPost(CD);
|
|
}
|
|
|
|
void visitBuiltinTupleDecl(BuiltinTupleDecl *BTD, StringRef label) {
|
|
printCommon(BTD, "builtin_tuple_decl", label);
|
|
printCommonPost(BTD);
|
|
}
|
|
|
|
void visitPatternBindingDecl(PatternBindingDecl *PBD, StringRef label) {
|
|
printCommon(PBD, "pattern_binding_decl", label);
|
|
|
|
for (auto idx : range(PBD->getNumPatternEntries())) {
|
|
printRec(PBD->getPattern(idx));
|
|
if (PBD->getOriginalInit(idx)) {
|
|
printRec(PBD->getOriginalInit(idx), "original_init");
|
|
}
|
|
if (PBD->getInit(idx)) {
|
|
printRec(PBD->getInit(idx), "processed_init");
|
|
}
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitSubscriptDecl(SubscriptDecl *SD, StringRef label) {
|
|
printCommon(SD, "subscript_decl", label);
|
|
printStorageImpl(SD);
|
|
printAccessors(SD);
|
|
printFoot();
|
|
}
|
|
|
|
void printCommonAFD(AbstractFunctionDecl *D, const char *Type, StringRef Label) {
|
|
printCommon(D, Type, Label, FuncColor);
|
|
if (!D->getCaptureInfo().isTrivial()) {
|
|
printFlagRaw([&](raw_ostream &OS) {
|
|
D->getCaptureInfo().print(OS);
|
|
});
|
|
}
|
|
|
|
printFlag(D->getAttrs().hasAttribute<NonisolatedAttr>(), "nonisolated",
|
|
ExprModifierColor);
|
|
printFlag(D->isDistributed(), "distributed", ExprModifierColor);
|
|
printFlag(D->isDistributedThunk(), "distributed_thunk",ExprModifierColor);
|
|
}
|
|
|
|
void printAbstractFunctionDecl(AbstractFunctionDecl *D) {
|
|
if (auto *P = D->getImplicitSelfDecl()) {
|
|
printRec(P);
|
|
}
|
|
printRec(D->getParameters(), &D->getASTContext());
|
|
|
|
if (auto FD = dyn_cast<FuncDecl>(D)) {
|
|
if (FD->getResultTypeRepr()) {
|
|
printRec(FD->getResultTypeRepr(), "result");
|
|
if (auto opaque = FD->getOpaqueResultTypeDecl()) {
|
|
printRec(opaque, "opaque_result_decl");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (auto fac = D->getForeignAsyncConvention()) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("foreign_async_convention", ASTNodeColor, label);
|
|
if (auto type = fac->completionHandlerType())
|
|
printFieldQuoted(type, "completion_handler_type", TypeColor);
|
|
printField(fac->completionHandlerParamIndex(),
|
|
"completion_handler_param");
|
|
if (auto errorParamIndex = fac->completionHandlerErrorParamIndex())
|
|
printField(*errorParamIndex, "error_param");
|
|
printFoot();
|
|
});
|
|
}
|
|
|
|
if (auto fec = D->getForeignErrorConvention()) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("foreign_error_convention", ASTNodeColor, label);
|
|
printField(fec->getKind(), "kind");
|
|
|
|
bool wantResultType = (
|
|
fec->getKind() == ForeignErrorConvention::ZeroResult ||
|
|
fec->getKind() == ForeignErrorConvention::NonZeroResult);
|
|
|
|
printFlag(getDumpString(fec->isErrorOwned()));
|
|
|
|
printField(fec->getErrorParameterIndex(), "param");
|
|
printFieldQuoted(fec->getErrorParameterType(), "paramtype");
|
|
if (wantResultType)
|
|
printFieldQuoted(fec->getResultType(), "resulttype");
|
|
printFoot();
|
|
});
|
|
}
|
|
|
|
if (D->hasSingleExpressionBody()) {
|
|
// There won't be an expression if this is an initializer that was
|
|
// originally spelled "init?(...) { nil }", because "nil" is modeled
|
|
// via FailStmt in this context.
|
|
if (auto *Body = D->getSingleExpressionBody()) {
|
|
printRec(Body);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (auto Body = D->getBody(/*canSynthesize=*/false)) {
|
|
printRec(Body, &D->getASTContext());
|
|
}
|
|
}
|
|
|
|
void printCommonFD(FuncDecl *FD, const char *type, StringRef Label) {
|
|
printCommonAFD(FD, type, Label);
|
|
printFlag(FD->isStatic(), "type");
|
|
}
|
|
|
|
void visitFuncDecl(FuncDecl *FD, StringRef label) {
|
|
printCommonFD(FD, "func_decl", label);
|
|
printAbstractFunctionDecl(FD);
|
|
printFoot();
|
|
}
|
|
|
|
void visitAccessorDecl(AccessorDecl *AD, StringRef label) {
|
|
printCommonFD(AD, "accessor_decl", label);
|
|
printFlag(getDumpString(AD->getAccessorKind()));
|
|
printDeclNameField(AD->getStorage(), "for");
|
|
printAbstractFunctionDecl(AD);
|
|
printFoot();
|
|
}
|
|
|
|
void visitConstructorDecl(ConstructorDecl *CD, StringRef label) {
|
|
printCommonAFD(CD, "constructor_decl", label);
|
|
printFlag(CD->isRequired(), "required", DeclModifierColor);
|
|
printFlag(getDumpString(CD->getInitKind()), DeclModifierColor);
|
|
if (CD->isFailable())
|
|
printField((CD->isImplicitlyUnwrappedOptional()
|
|
? "ImplicitlyUnwrappedOptional"
|
|
: "Optional"), "failable", DeclModifierColor);
|
|
printAbstractFunctionDecl(CD);
|
|
printFoot();
|
|
}
|
|
|
|
void visitDestructorDecl(DestructorDecl *DD, StringRef label) {
|
|
printCommonAFD(DD, "destructor_decl", label);
|
|
printAbstractFunctionDecl(DD);
|
|
printFoot();
|
|
}
|
|
|
|
void visitTopLevelCodeDecl(TopLevelCodeDecl *TLCD, StringRef label) {
|
|
printCommon(TLCD, "top_level_code_decl", label);
|
|
if (TLCD->getBody()) {
|
|
printRec(TLCD->getBody(), &static_cast<Decl *>(TLCD)->getASTContext());
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitIfConfigDecl(IfConfigDecl *ICD, StringRef label) {
|
|
printCommon(ICD, "if_config_decl", label);
|
|
printRecRange(ICD->getClauses(), &ICD->getASTContext(), "clauses");
|
|
printFoot();
|
|
}
|
|
|
|
void visitPoundDiagnosticDecl(PoundDiagnosticDecl *PDD, StringRef label) {
|
|
printCommon(PDD, "pound_diagnostic_decl", label);
|
|
printField(PDD->isError() ? "error" : "warning", "kind");
|
|
printRec(PDD->getMessage());
|
|
printFoot();
|
|
}
|
|
|
|
void visitPrecedenceGroupDecl(PrecedenceGroupDecl *PGD, StringRef label) {
|
|
printCommon(PGD, "precedence_group_decl", label);
|
|
printName(PGD->getName());
|
|
printField(PGD->getAssociativity(), "associativity");
|
|
printField(PGD->isAssignment(), "assignment");
|
|
|
|
auto printRelationsRec =
|
|
[&](ArrayRef<PrecedenceGroupDecl::Relation> rels, StringRef name) {
|
|
if (rels.empty()) return;
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead(name, FieldLabelColor, label);
|
|
for (auto &rel : rels)
|
|
printFlag(rel.Name.str());
|
|
printFoot();
|
|
});
|
|
};
|
|
printRelationsRec(PGD->getHigherThan(), "higherThan");
|
|
printRelationsRec(PGD->getLowerThan(), "lowerThan");
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitInfixOperatorDecl(InfixOperatorDecl *IOD, StringRef label) {
|
|
printCommon(IOD, "infix_operator_decl", label);
|
|
printName(IOD->getName());
|
|
if (!IOD->getPrecedenceGroupName().empty())
|
|
printFieldQuoted(IOD->getPrecedenceGroupName(),
|
|
"precedence_group_name");
|
|
printFoot();
|
|
}
|
|
|
|
void visitPrefixOperatorDecl(PrefixOperatorDecl *POD, StringRef label) {
|
|
printCommon(POD, "prefix_operator_decl", label);
|
|
printName(POD->getName());
|
|
printFoot();
|
|
}
|
|
|
|
void visitPostfixOperatorDecl(PostfixOperatorDecl *POD, StringRef label) {
|
|
printCommon(POD, "postfix_operator_decl", label);
|
|
printName(POD->getName());
|
|
printFoot();
|
|
}
|
|
|
|
void visitModuleDecl(ModuleDecl *MD, StringRef label) {
|
|
printCommon(MD, "module", label);
|
|
printFlag(MD->isNonSwiftModule(), "non_swift");
|
|
printFoot();
|
|
}
|
|
|
|
void visitMissingDecl(MissingDecl *missing, StringRef label) {
|
|
printCommon(missing, "missing_decl", label);
|
|
printFoot();
|
|
}
|
|
|
|
void visitMissingMemberDecl(MissingMemberDecl *MMD, StringRef label) {
|
|
printCommon(MMD, "missing_member_decl ", label);
|
|
printName(MMD->getName());
|
|
printFoot();
|
|
}
|
|
|
|
void visitMacroDecl(MacroDecl *MD, StringRef label) {
|
|
printCommon(MD, "macro_decl", label);
|
|
// TODO: Fill this in?
|
|
printFoot();
|
|
}
|
|
|
|
void visitMacroExpansionDecl(MacroExpansionDecl *MED, StringRef label) {
|
|
printCommon(MED, "macro_expansion_decl", label);
|
|
printName(MED->getMacroName().getFullName());
|
|
printRec(MED->getArgs());
|
|
printFoot();
|
|
}
|
|
};
|
|
} // end anonymous namespace
|
|
|
|
void ParameterList::dump() const {
|
|
dump(llvm::errs(), 0);
|
|
llvm::errs() << '\n';
|
|
}
|
|
|
|
void ParameterList::dump(raw_ostream &OS, unsigned Indent) const {
|
|
PrintDecl(OS, Indent)
|
|
.visitParameterList(const_cast<ParameterList *>(this), "");
|
|
}
|
|
|
|
void Decl::dump() const {
|
|
dump(llvm::errs(), 0);
|
|
}
|
|
|
|
void Decl::dump(const char *filename) const {
|
|
std::error_code ec;
|
|
llvm::raw_fd_ostream stream(filename, ec, llvm::sys::fs::FA_Read |
|
|
llvm::sys::fs::FA_Write);
|
|
// In assert builds, we blow up. Otherwise, we just return.
|
|
assert(!ec && "Failed to open file for dumping?!");
|
|
if (ec)
|
|
return;
|
|
dump(stream, 0);
|
|
}
|
|
|
|
void Decl::dump(raw_ostream &OS, unsigned Indent) const {
|
|
PrintDecl(OS, Indent).visit(const_cast<Decl *>(this), "");
|
|
OS << '\n';
|
|
}
|
|
|
|
/// Print the given declaration context (with its parents).
|
|
void swift::printContext(raw_ostream &os, DeclContext *dc) {
|
|
if (auto parent = dc->getParent()) {
|
|
printContext(os, parent);
|
|
os << '.';
|
|
}
|
|
|
|
switch (dc->getContextKind()) {
|
|
case DeclContextKind::Package:
|
|
printName(os, cast<PackageUnit>(dc)->getName());
|
|
break;
|
|
|
|
case DeclContextKind::Module:
|
|
printName(os, cast<ModuleDecl>(dc)->getRealName());
|
|
break;
|
|
|
|
case DeclContextKind::FileUnit:
|
|
// FIXME: print the file's basename?
|
|
os << "(file)";
|
|
break;
|
|
|
|
case DeclContextKind::SerializedLocal:
|
|
os << "local context";
|
|
break;
|
|
|
|
case DeclContextKind::AbstractClosureExpr: {
|
|
auto *ACE = cast<AbstractClosureExpr>(dc);
|
|
if (isa<ClosureExpr>(ACE)) {
|
|
PrintWithColorRAII(os, DiscriminatorColor)
|
|
<< "explicit closure discriminator=";
|
|
}
|
|
if (isa<AutoClosureExpr>(ACE)) {
|
|
PrintWithColorRAII(os, DiscriminatorColor)
|
|
<< "autoclosure discriminator=";
|
|
}
|
|
|
|
// If we aren't printing to standard error or the debugger output stream,
|
|
// this client expects to see the computed discriminator. Compute it now.
|
|
if (&os != &llvm::errs() && &os != &llvm::dbgs())
|
|
(void)ACE->getDiscriminator();
|
|
|
|
PrintWithColorRAII(os, DiscriminatorColor) << ACE->getRawDiscriminator();
|
|
break;
|
|
}
|
|
|
|
case DeclContextKind::GenericTypeDecl:
|
|
printName(os, cast<GenericTypeDecl>(dc)->getName());
|
|
break;
|
|
|
|
case DeclContextKind::ExtensionDecl:
|
|
if (auto extendedNominal = cast<ExtensionDecl>(dc)->getExtendedNominal()) {
|
|
printName(os, extendedNominal->getName());
|
|
}
|
|
os << " extension";
|
|
break;
|
|
|
|
case DeclContextKind::Initializer:
|
|
switch (cast<Initializer>(dc)->getInitializerKind()) {
|
|
case InitializerKind::PatternBinding:
|
|
os << "pattern binding initializer";
|
|
break;
|
|
case InitializerKind::DefaultArgument:
|
|
os << "default argument initializer";
|
|
break;
|
|
case InitializerKind::PropertyWrapper:
|
|
os << "property wrapper initializer";
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case DeclContextKind::TopLevelCodeDecl:
|
|
os << "top-level code";
|
|
break;
|
|
|
|
case DeclContextKind::AbstractFunctionDecl:
|
|
printName(os, cast<AbstractFunctionDecl>(dc)->getName());
|
|
break;
|
|
|
|
case DeclContextKind::SubscriptDecl:
|
|
printName(os, cast<SubscriptDecl>(dc)->getName());
|
|
break;
|
|
|
|
case DeclContextKind::EnumElementDecl:
|
|
printName(os, cast<EnumElementDecl>(dc)->getName());
|
|
break;
|
|
|
|
case DeclContextKind::MacroDecl:
|
|
printName(os, cast<MacroDecl>(dc)->getName());
|
|
break;
|
|
}
|
|
}
|
|
|
|
std::string ValueDecl::printRef() const {
|
|
std::string result;
|
|
llvm::raw_string_ostream os(result);
|
|
dumpRef(os);
|
|
return os.str();
|
|
}
|
|
|
|
void ValueDecl::dumpRef(raw_ostream &os) const {
|
|
if (!isa<ModuleDecl>(this)) {
|
|
// Print the context.
|
|
printContext(os, getDeclContext());
|
|
os << ".";
|
|
// Print name.
|
|
getName().printPretty(os);
|
|
} else {
|
|
auto moduleName = cast<ModuleDecl>(this)->getRealName();
|
|
os << moduleName;
|
|
}
|
|
|
|
if (getAttrs().hasAttribute<KnownToBeLocalAttr>()) {
|
|
os << " known-to-be-local";
|
|
}
|
|
|
|
// Print location.
|
|
auto &srcMgr = getASTContext().SourceMgr;
|
|
if (getLoc().isValid()) {
|
|
os << '@';
|
|
getLoc().print(os, srcMgr);
|
|
}
|
|
}
|
|
|
|
void LLVM_ATTRIBUTE_USED ValueDecl::dumpRef() const {
|
|
dumpRef(llvm::errs());
|
|
llvm::errs() << "\n";
|
|
}
|
|
|
|
void SourceFile::dump() const {
|
|
dump(llvm::errs());
|
|
}
|
|
|
|
void SourceFile::dump(llvm::raw_ostream &OS, bool parseIfNeeded) const {
|
|
// If we're allowed to parse the SourceFile, do so now. We need to force the
|
|
// parsing request as by default the dumping logic tries not to kick any
|
|
// requests.
|
|
if (parseIfNeeded)
|
|
(void)getTopLevelItems();
|
|
|
|
PrintDecl(OS).visitSourceFile(*this);
|
|
llvm::errs() << '\n';
|
|
}
|
|
|
|
void Pattern::dump() const {
|
|
dump(llvm::errs());
|
|
}
|
|
|
|
void Pattern::dump(raw_ostream &OS, unsigned Indent) const {
|
|
PrintPattern(OS, Indent).visit(const_cast<Pattern*>(this), "");
|
|
OS << '\n';
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Printing for Stmt and all subclasses.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
/// PrintStmt - Visitor implementation of Stmt::dump.
|
|
class PrintStmt : public StmtVisitor<PrintStmt, void, StringRef>,
|
|
public PrintBase {
|
|
public:
|
|
using PrintBase::PrintBase;
|
|
const ASTContext *Ctx;
|
|
|
|
PrintStmt(raw_ostream &os, const ASTContext *ctx, unsigned indent = 0,
|
|
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(os, indent, getTypeOfExpr, getTypeOfTypeRepr,
|
|
getTypeOfKeyPathComponent), Ctx(ctx) { }
|
|
|
|
using PrintBase::printRec;
|
|
|
|
void printRec(Stmt *S, StringRef Label = "") {
|
|
PrintBase::printRec(S, Ctx, Label);
|
|
}
|
|
|
|
void printCommon(Stmt *S, const char *Name, StringRef Label) {
|
|
printHead(Name, StmtColor, Label);
|
|
|
|
printFlag(S->isImplicit(), "implicit");
|
|
printSourceRange(S->getSourceRange(), Ctx);
|
|
printFlag(S->TrailingSemiLoc.isValid(), "trailing_semi");
|
|
}
|
|
|
|
void visitBraceStmt(BraceStmt *S, StringRef label) {
|
|
printCommon(S, "brace_stmt", label);
|
|
for (auto &Elt : S->getElements())
|
|
printRec(Elt, Ctx);
|
|
printFoot();
|
|
}
|
|
|
|
void visitReturnStmt(ReturnStmt *S, StringRef label) {
|
|
printCommon(S, "return_stmt", label);
|
|
if (S->hasResult()) {
|
|
printRec(S->getResult());
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitYieldStmt(YieldStmt *S, StringRef label) {
|
|
printCommon(S, "yield_stmt", label);
|
|
for (auto yield : S->getYields()) {
|
|
printRec(yield);
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitThenStmt(ThenStmt *S, StringRef label) {
|
|
printCommon(S, "then_stmt", label);
|
|
printRec(S->getResult());
|
|
printFoot();
|
|
}
|
|
|
|
void visitDeferStmt(DeferStmt *S, StringRef label) {
|
|
printCommon(S, "defer_stmt", label);
|
|
printRec(S->getTempDecl());
|
|
printRec(S->getCallExpr());
|
|
printFoot();
|
|
}
|
|
|
|
void visitIfStmt(IfStmt *S, StringRef label) {
|
|
printCommon(S, "if_stmt", label);
|
|
printRecRange(S->getCond(), Ctx, "conditions");
|
|
printRec(S->getThenStmt());
|
|
if (S->getElseStmt()) {
|
|
printRec(S->getElseStmt());
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitGuardStmt(GuardStmt *S, StringRef label) {
|
|
printCommon(S, "guard_stmt", label);
|
|
printRecRange(S->getCond(), Ctx, "conditions");
|
|
printRec(S->getBody());
|
|
printFoot();
|
|
}
|
|
|
|
void visitDoStmt(DoStmt *S, StringRef label) {
|
|
printCommon(S, "do_stmt", label);
|
|
printRec(S->getBody());
|
|
printFoot();
|
|
}
|
|
|
|
void visitWhileStmt(WhileStmt *S, StringRef label) {
|
|
printCommon(S, "while_stmt", label);
|
|
printRecRange(S->getCond(), Ctx, "conditions");
|
|
printRec(S->getBody());
|
|
printFoot();
|
|
}
|
|
|
|
void visitRepeatWhileStmt(RepeatWhileStmt *S, StringRef label) {
|
|
printCommon(S, "repeat_while_stmt", label);
|
|
printRec(S->getBody());
|
|
printRec(S->getCond());
|
|
printFoot();
|
|
}
|
|
void visitForEachStmt(ForEachStmt *S, StringRef label) {
|
|
printCommon(S, "for_each_stmt", label);
|
|
printRec(S->getPattern());
|
|
if (S->getWhere()) {
|
|
printRec(S->getWhere(), "where");
|
|
}
|
|
printRec(S->getParsedSequence());
|
|
if (S->getIteratorVar()) {
|
|
printRec(S->getIteratorVar());
|
|
}
|
|
if (S->getNextCall()) {
|
|
printRec(S->getNextCall());
|
|
}
|
|
if (S->getConvertElementExpr()) {
|
|
printRec(S->getConvertElementExpr());
|
|
}
|
|
if (S->getElementExpr()) {
|
|
printRec(S->getElementExpr());
|
|
}
|
|
printRec(S->getBody());
|
|
printFoot();
|
|
}
|
|
void visitBreakStmt(BreakStmt *S, StringRef label) {
|
|
printCommon(S, "break_stmt", label);
|
|
printFoot();
|
|
}
|
|
void visitContinueStmt(ContinueStmt *S, StringRef label) {
|
|
printCommon(S, "continue_stmt", label);
|
|
printFoot();
|
|
}
|
|
void visitFallthroughStmt(FallthroughStmt *S, StringRef label) {
|
|
printCommon(S, "fallthrough_stmt", label);
|
|
printFoot();
|
|
}
|
|
void visitSwitchStmt(SwitchStmt *S, StringRef label) {
|
|
printCommon(S, "switch_stmt", label);
|
|
printRec(S->getSubjectExpr());
|
|
for (auto N : S->getRawCases()) {
|
|
if (N.is<Stmt*>())
|
|
printRec(N.get<Stmt*>());
|
|
else
|
|
printRec(N.get<Decl*>());
|
|
}
|
|
printFoot();
|
|
}
|
|
void visitCaseStmt(CaseStmt *S, StringRef label) {
|
|
printCommon(S, "case_stmt", label);
|
|
printFlag(S->hasUnknownAttr(), "@unknown");
|
|
|
|
if (S->hasCaseBodyVariables()) {
|
|
printRecRange(S->getCaseBodyVariables(), "case_body_variables");
|
|
}
|
|
|
|
for (const auto &LabelItem : S->getCaseLabelItems()) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("case_label_item", StmtColor, label);
|
|
printFlag(LabelItem.isDefault(), "default");
|
|
|
|
if (auto *CasePattern = LabelItem.getPattern()) {
|
|
printRec(CasePattern);
|
|
}
|
|
if (auto *Guard = LabelItem.getGuardExpr()) {
|
|
printRec(const_cast<Expr *>(Guard));
|
|
}
|
|
|
|
printFoot();
|
|
});
|
|
}
|
|
|
|
printRec(S->getBody());
|
|
printFoot();
|
|
}
|
|
void visitFailStmt(FailStmt *S, StringRef label) {
|
|
printCommon(S, "fail_stmt", label);
|
|
printFoot();
|
|
}
|
|
|
|
void visitThrowStmt(ThrowStmt *S, StringRef label) {
|
|
printCommon(S, "throw_stmt", label);
|
|
printRec(S->getSubExpr());
|
|
printFoot();
|
|
}
|
|
|
|
void visitDiscardStmt(DiscardStmt *S, StringRef label) {
|
|
printCommon(S, "discard_stmt", label);
|
|
printRec(S->getSubExpr());
|
|
printFoot();
|
|
}
|
|
|
|
void visitPoundAssertStmt(PoundAssertStmt *S, StringRef label) {
|
|
printCommon(S, "pound_assert", label);
|
|
printFieldQuoted(S->getMessage(), "message");
|
|
printRec(S->getCondition());
|
|
printFoot();
|
|
}
|
|
|
|
void visitDoCatchStmt(DoCatchStmt *S, StringRef label) {
|
|
printCommon(S, "do_catch_stmt", label);
|
|
printRec(S->getBody(), "body");
|
|
printRecRange(S->getCatches(), Ctx, "catch_stmts");
|
|
printFoot();
|
|
}
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
void Stmt::dump() const {
|
|
dump(llvm::errs());
|
|
llvm::errs() << '\n';
|
|
}
|
|
|
|
void Stmt::dump(raw_ostream &OS, const ASTContext *Ctx, unsigned Indent) const {
|
|
PrintStmt(OS, Ctx, Indent).visit(const_cast<Stmt*>(this), "");
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Printing for Expr and all subclasses.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
/// PrintExpr - Visitor implementation of Expr::dump.
|
|
class PrintExpr : public ExprVisitor<PrintExpr, void, StringRef>,
|
|
public PrintBase {
|
|
public:
|
|
using PrintBase::PrintBase;
|
|
|
|
/// FIXME: This should use ExprWalker to print children.
|
|
|
|
void printCommon(Expr *E, const char *C, StringRef label) {
|
|
PrintOptions PO;
|
|
PO.PrintTypesForDebugging = true;
|
|
|
|
printHead(C, ExprColor, label);
|
|
|
|
printFlag(E->isImplicit(), "implicit", ExprModifierColor);
|
|
printFieldQuoted(GetTypeOfExpr(E).getString(PO), "type", TypeColor);
|
|
|
|
// If we have a source range and an ASTContext, print the source range.
|
|
if (auto Ty = GetTypeOfExpr(E)) {
|
|
auto &Ctx = Ty->getASTContext();
|
|
printSourceLoc(E->getLoc(), &Ctx);
|
|
printSourceRange(E->getSourceRange(), &Ctx);
|
|
}
|
|
|
|
printFlag(E->TrailingSemiLoc.isValid(), "trailing_semi");
|
|
}
|
|
|
|
void printSemanticExpr(Expr * semanticExpr) {
|
|
if (semanticExpr == nullptr) {
|
|
return;
|
|
}
|
|
|
|
printRec(semanticExpr, "semantic_expr");
|
|
}
|
|
|
|
void visitErrorExpr(ErrorExpr *E, StringRef label) {
|
|
printCommon(E, "error_expr", label);
|
|
printFoot();
|
|
}
|
|
|
|
void visitCodeCompletionExpr(CodeCompletionExpr *E, StringRef label) {
|
|
printCommon(E, "code_completion_expr", label);
|
|
if (E->getBase()) {
|
|
printRec(E->getBase());
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void printInitializerField(ConcreteDeclRef declRef, StringRef label) {
|
|
printFieldQuotedRaw([&](raw_ostream &OS) { declRef.dump(OS); }, label,
|
|
ExprModifierColor);
|
|
}
|
|
|
|
void visitNilLiteralExpr(NilLiteralExpr *E, StringRef label) {
|
|
printCommon(E, "nil_literal_expr", label);
|
|
printInitializerField(E->getInitializer(), "initializer");
|
|
printFoot();
|
|
}
|
|
|
|
void visitIntegerLiteralExpr(IntegerLiteralExpr *E, StringRef label) {
|
|
printCommon(E, "integer_literal_expr", label);
|
|
|
|
printFlag(E->isNegative(), "negative", LiteralValueColor);
|
|
Type T = GetTypeOfExpr(E);
|
|
if (T.isNull() || !T->is<BuiltinIntegerType>())
|
|
printFieldQuoted(E->getDigitsText(), "value", LiteralValueColor);
|
|
else
|
|
printFieldQuoted(E->getValue(), "value", LiteralValueColor);
|
|
printInitializerField(E->getBuiltinInitializer(), "builtin_initializer");
|
|
printInitializerField(E->getInitializer(), "initializer");
|
|
|
|
printFoot();
|
|
}
|
|
void visitFloatLiteralExpr(FloatLiteralExpr *E, StringRef label) {
|
|
printCommon(E, "float_literal_expr", label);
|
|
|
|
printFlag(E->isNegative(), "negative", LiteralValueColor);
|
|
printFieldQuoted(E->getDigitsText(), "value", LiteralValueColor);
|
|
printInitializerField(E->getBuiltinInitializer(), "builtin_initializer");
|
|
printInitializerField(E->getInitializer(), "initializer");
|
|
if (!E->getBuiltinType().isNull()) {
|
|
printFieldQuoted(E->getBuiltinType(), "builtin_type", ExprModifierColor);
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitBooleanLiteralExpr(BooleanLiteralExpr *E, StringRef label) {
|
|
printCommon(E, "boolean_literal_expr", label);
|
|
|
|
printField(E->getValue(), "value", LiteralValueColor);
|
|
printInitializerField(E->getBuiltinInitializer(), "builtin_initializer");
|
|
printInitializerField(E->getInitializer(), "initializer");
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitStringLiteralExpr(StringLiteralExpr *E, StringRef label) {
|
|
printCommon(E, "string_literal_expr", label);
|
|
|
|
printField(E->getEncoding(), "encoding", ExprModifierColor);
|
|
printFieldQuoted(E->getValue(), "value", LiteralValueColor);
|
|
printInitializerField(E->getBuiltinInitializer(), "builtin_initializer");
|
|
printInitializerField(E->getInitializer(), "initializer");
|
|
|
|
printFoot();
|
|
}
|
|
void visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *E, StringRef label) {
|
|
printCommon(E, "interpolated_string_literal_expr", label);
|
|
|
|
// Print the trailing quote location
|
|
if (auto Ty = GetTypeOfExpr(E)) {
|
|
auto &Ctx = Ty->getASTContext();
|
|
printSourceLoc(E->getTrailingQuoteLoc(), &Ctx, "trailing_quote_loc");
|
|
}
|
|
printField(E->getLiteralCapacity(), "literal_capacity", ExprModifierColor);
|
|
printField(E->getInterpolationCount(), "interpolation_count",
|
|
ExprModifierColor);
|
|
printInitializerField(E->getBuilderInit(), "builder_init");
|
|
printInitializerField(E->getInitializer(), "result_init");
|
|
|
|
printRec(E->getAppendingExpr());
|
|
|
|
printFoot();
|
|
}
|
|
void visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *E, StringRef label) {
|
|
printCommon(E, "magic_identifier_literal_expr", label);
|
|
|
|
printField(E->getKind(), "kind", ExprModifierColor);
|
|
|
|
if (E->isString()) {
|
|
printField(E->getStringEncoding(), "encoding", ExprModifierColor);
|
|
}
|
|
printInitializerField(E->getBuiltinInitializer(), "builtin_initializer");
|
|
printInitializerField(E->getInitializer(), "initializer");
|
|
|
|
printFoot();
|
|
}
|
|
void visitRegexLiteralExpr(RegexLiteralExpr *E, StringRef label) {
|
|
printCommon(E, "regex_literal_expr", label);
|
|
|
|
printFieldQuoted(E->getRegexText(), "text", LiteralValueColor);
|
|
printInitializerField(E->getInitializer(), "initializer");
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitObjectLiteralExpr(ObjectLiteralExpr *E, StringRef label) {
|
|
printCommon(E, "object_literal", label);
|
|
|
|
printField(E->getLiteralKind(), "kind");
|
|
printInitializerField(E->getInitializer(), "initializer");
|
|
|
|
printRec(E->getArgs());
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitDiscardAssignmentExpr(DiscardAssignmentExpr *E, StringRef label) {
|
|
printCommon(E, "discard_assignment_expr", label);
|
|
printFoot();
|
|
}
|
|
|
|
void visitDeclRefExpr(DeclRefExpr *E, StringRef label) {
|
|
printCommon(E, "declref_expr", label);
|
|
|
|
printDeclRefField(E->getDeclRef(), "decl");
|
|
if (E->getAccessSemantics() != AccessSemantics::Ordinary)
|
|
printFlag(getDumpString(E->getAccessSemantics()), AccessLevelColor);
|
|
printField(E->getFunctionRefKind(), "function_ref",
|
|
ExprModifierColor);
|
|
|
|
printFoot();
|
|
}
|
|
void visitSuperRefExpr(SuperRefExpr *E, StringRef label) {
|
|
printCommon(E, "super_ref_expr", label);
|
|
printFoot();
|
|
}
|
|
|
|
void visitTypeExpr(TypeExpr *E, StringRef label) {
|
|
printCommon(E, "type_expr", label);
|
|
|
|
if (E->getTypeRepr())
|
|
printFieldQuotedRaw([&](raw_ostream &OS) { E->getTypeRepr()->print(OS); },
|
|
"typerepr", TypeReprColor);
|
|
else
|
|
printFlag("null_typerepr");
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitOtherConstructorDeclRefExpr(OtherConstructorDeclRefExpr *E, StringRef label) {
|
|
printCommon(E, "other_constructor_ref_expr", label);
|
|
printDeclRefField(E->getDeclRef(), "decl");
|
|
printFoot();
|
|
}
|
|
void visitOverloadedDeclRefExpr(OverloadedDeclRefExpr *E, StringRef label) {
|
|
printCommon(E, "overloaded_decl_ref_expr", label);
|
|
|
|
printFieldQuoted(E->getDecls()[0]->getBaseName(), "name", IdentifierColor);
|
|
printField(E->getDecls().size(), "number_of_decls", ExprModifierColor);
|
|
printField(E->getFunctionRefKind(), "function_ref", ExprModifierColor);
|
|
|
|
if (!E->isForOperator()) {
|
|
for (auto D : E->getDecls()) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("candidate_decl", DeclModifierColor, label);
|
|
printNameRaw([&](raw_ostream &OS) { D->dumpRef(OS); });
|
|
printFoot();
|
|
});
|
|
}
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
void visitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E, StringRef label) {
|
|
printCommon(E, "unresolved_decl_ref_expr", label);
|
|
|
|
printFieldQuoted(E->getName(), "name", IdentifierColor);
|
|
printField(E->getFunctionRefKind(), "function_ref", ExprModifierColor);
|
|
|
|
printFoot();
|
|
}
|
|
void visitUnresolvedSpecializeExpr(UnresolvedSpecializeExpr *E, StringRef label) {
|
|
printCommon(E, "unresolved_specialize_expr", label);
|
|
|
|
printRec(E->getSubExpr());
|
|
for (TypeLoc T : E->getUnresolvedParams()) {
|
|
printRec(T.getTypeRepr());
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitMemberRefExpr(MemberRefExpr *E, StringRef label) {
|
|
printCommon(E, "member_ref_expr", label);
|
|
|
|
printDeclRefField(E->getMember(), "decl");
|
|
if (E->getAccessSemantics() != AccessSemantics::Ordinary)
|
|
printFlag(getDumpString(E->getAccessSemantics()), AccessLevelColor);
|
|
printFlag(E->isSuper(), "super");
|
|
|
|
printRec(E->getBase());
|
|
printFoot();
|
|
}
|
|
void visitDynamicMemberRefExpr(DynamicMemberRefExpr *E, StringRef label) {
|
|
printCommon(E, "dynamic_member_ref_expr", label);
|
|
|
|
printDeclRefField(E->getMember(), "decl");
|
|
|
|
printRec(E->getBase());
|
|
|
|
printFoot();
|
|
}
|
|
void visitUnresolvedMemberExpr(UnresolvedMemberExpr *E, StringRef label) {
|
|
printCommon(E, "unresolved_member_expr", label);
|
|
|
|
printFieldQuoted(E->getName(), "name", ExprModifierColor);
|
|
printField(E->getFunctionRefKind(), "function_ref", ExprModifierColor);
|
|
printFoot();
|
|
}
|
|
void visitDotSelfExpr(DotSelfExpr *E, StringRef label) {
|
|
printCommon(E, "dot_self_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitParenExpr(ParenExpr *E, StringRef label) {
|
|
printCommon(E, "paren_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitAwaitExpr(AwaitExpr *E, StringRef label) {
|
|
printCommon(E, "await_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitConsumeExpr(ConsumeExpr *E, StringRef label) {
|
|
printCommon(E, "consume_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitCopyExpr(CopyExpr *E, StringRef label) {
|
|
printCommon(E, "copy_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitBorrowExpr(BorrowExpr *E, StringRef label) {
|
|
printCommon(E, "borrow_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitUnresolvedMemberChainResultExpr(UnresolvedMemberChainResultExpr *E, StringRef label){
|
|
printCommon(E, "unresolved_member_chain_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitTupleExpr(TupleExpr *E, StringRef label) {
|
|
printCommon(E, "tuple_expr", label);
|
|
|
|
if (E->hasElementNames()) {
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
interleave(E->getElementNames(), OS,
|
|
[&](Identifier name) {
|
|
OS << (name.empty()?"''":name.str());
|
|
},
|
|
",");
|
|
}, "names", IdentifierColor);
|
|
}
|
|
|
|
for (unsigned i = 0, e = E->getNumElements(); i != e; ++i) {
|
|
if (E->getElement(i))
|
|
printRec(E->getElement(i));
|
|
else {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("<tuple element default value>", ExprColor);
|
|
printFoot();
|
|
});
|
|
}
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
void visitArrayExpr(ArrayExpr *E, StringRef label) {
|
|
printCommon(E, "array_expr", label);
|
|
|
|
printInitializerField(E->getInitializer(), "initializer");
|
|
|
|
for (auto elt : E->getElements()) {
|
|
printRec(elt);
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
void visitDictionaryExpr(DictionaryExpr *E, StringRef label) {
|
|
printCommon(E, "dictionary_expr", label);
|
|
|
|
printInitializerField(E->getInitializer(), "initializer");
|
|
|
|
for (auto elt : E->getElements()) {
|
|
printRec(elt);
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
void visitSubscriptExpr(SubscriptExpr *E, StringRef label) {
|
|
printCommon(E, "subscript_expr", label);
|
|
|
|
if (E->getAccessSemantics() != AccessSemantics::Ordinary)
|
|
printFlag(getDumpString(E->getAccessSemantics()), AccessLevelColor);
|
|
printFlag(E->isSuper(), "super");
|
|
if (E->hasDecl()) {
|
|
printDeclRefField(E->getDecl(), "decl");
|
|
}
|
|
|
|
printRec(E->getBase());
|
|
printRec(E->getArgs());
|
|
|
|
printFoot();
|
|
}
|
|
void visitKeyPathApplicationExpr(KeyPathApplicationExpr *E, StringRef label) {
|
|
printCommon(E, "keypath_application_expr", label);
|
|
printRec(E->getBase());
|
|
printRec(E->getKeyPath());
|
|
printFoot();
|
|
}
|
|
void visitDynamicSubscriptExpr(DynamicSubscriptExpr *E, StringRef label) {
|
|
printCommon(E, "dynamic_subscript_expr", label);
|
|
|
|
printDeclRefField(E->getMember(), "decl");
|
|
|
|
printRec(E->getBase());
|
|
printRec(E->getArgs());
|
|
|
|
printFoot();
|
|
}
|
|
void visitUnresolvedDotExpr(UnresolvedDotExpr *E, StringRef label) {
|
|
printCommon(E, "unresolved_dot_expr", label);
|
|
|
|
printFieldQuoted(E->getName(), "field");
|
|
printField(E->getFunctionRefKind(), "function_ref", ExprModifierColor);
|
|
|
|
if (E->getBase()) {
|
|
printRec(E->getBase());
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
void visitTupleElementExpr(TupleElementExpr *E, StringRef label) {
|
|
printCommon(E, "tuple_element_expr", label);
|
|
|
|
printField(E->getFieldNumber(), "field #");
|
|
|
|
printRec(E->getBase());
|
|
|
|
printFoot();
|
|
}
|
|
void visitDestructureTupleExpr(DestructureTupleExpr *E, StringRef label) {
|
|
printCommon(E, "destructure_tuple_expr", label);
|
|
|
|
printRecRange(E->getDestructuredElements(), "destructured");
|
|
printRec(E->getSubExpr());
|
|
printRec(E->getResultExpr());
|
|
|
|
printFoot();
|
|
}
|
|
void visitUnresolvedTypeConversionExpr(UnresolvedTypeConversionExpr *E, StringRef label) {
|
|
printCommon(E, "unresolvedtype_conversion_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitFunctionConversionExpr(FunctionConversionExpr *E, StringRef label) {
|
|
printCommon(E, "function_conversion_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitCovariantFunctionConversionExpr(CovariantFunctionConversionExpr *E, StringRef label){
|
|
printCommon(E, "covariant_function_conversion_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitCovariantReturnConversionExpr(CovariantReturnConversionExpr *E, StringRef label){
|
|
printCommon(E, "covariant_return_conversion_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitUnderlyingToOpaqueExpr(UnderlyingToOpaqueExpr *E, StringRef label){
|
|
printCommon(E, "underlying_to_opaque_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitErasureExpr(ErasureExpr *E, StringRef label) {
|
|
printCommon(E, "erasure_expr", label);
|
|
for (auto conf : E->getConformances()) {
|
|
printRec(conf);
|
|
}
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitAnyHashableErasureExpr(AnyHashableErasureExpr *E, StringRef label) {
|
|
printCommon(E, "any_hashable_erasure_expr", label);
|
|
printRec(E->getConformance());
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitConditionalBridgeFromObjCExpr(ConditionalBridgeFromObjCExpr *E, StringRef label) {
|
|
printCommon(E, "conditional_bridge_from_objc_expr", label);
|
|
|
|
printDeclRefField(E->getConversion(), "conversion");
|
|
|
|
printRec(E->getSubExpr());
|
|
|
|
printFoot();
|
|
}
|
|
void visitBridgeFromObjCExpr(BridgeFromObjCExpr *E, StringRef label) {
|
|
printCommon(E, "bridge_from_objc_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitBridgeToObjCExpr(BridgeToObjCExpr *E, StringRef label) {
|
|
printCommon(E, "bridge_to_objc_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitLoadExpr(LoadExpr *E, StringRef label) {
|
|
printCommon(E, "load_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitABISafeConversionExpr(ABISafeConversionExpr *E, StringRef label) {
|
|
printCommon(E, "abi_safe_conversion_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitMetatypeConversionExpr(MetatypeConversionExpr *E, StringRef label) {
|
|
printCommon(E, "metatype_conversion_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitCollectionUpcastConversionExpr(CollectionUpcastConversionExpr *E, StringRef label) {
|
|
printCommon(E, "collection_upcast_expr", label);
|
|
printRec(E->getSubExpr());
|
|
if (auto keyConversion = E->getKeyConversion()) {
|
|
printRec(keyConversion.Conversion, "key_conversion");
|
|
}
|
|
if (auto valueConversion = E->getValueConversion()) {
|
|
printRec(valueConversion.Conversion, "value_conversion");
|
|
}
|
|
printFoot();
|
|
}
|
|
void visitDerivedToBaseExpr(DerivedToBaseExpr *E, StringRef label) {
|
|
printCommon(E, "derived_to_base_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitArchetypeToSuperExpr(ArchetypeToSuperExpr *E, StringRef label) {
|
|
printCommon(E, "archetype_to_super_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitInjectIntoOptionalExpr(InjectIntoOptionalExpr *E, StringRef label) {
|
|
printCommon(E, "inject_into_optional", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitClassMetatypeToObjectExpr(ClassMetatypeToObjectExpr *E, StringRef label) {
|
|
printCommon(E, "class_metatype_to_object", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitExistentialMetatypeToObjectExpr(ExistentialMetatypeToObjectExpr *E, StringRef label) {
|
|
printCommon(E, "existential_metatype_to_object", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitProtocolMetatypeToObjectExpr(ProtocolMetatypeToObjectExpr *E, StringRef label) {
|
|
printCommon(E, "protocol_metatype_to_object", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitInOutToPointerExpr(InOutToPointerExpr *E, StringRef label) {
|
|
printCommon(E, "inout_to_pointer", label);
|
|
printFlag(E->isNonAccessing(), "nonaccessing");
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitArrayToPointerExpr(ArrayToPointerExpr *E, StringRef label) {
|
|
printCommon(E, "array_to_pointer", label);
|
|
printFlag(E->isNonAccessing(), "nonaccessing");
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitStringToPointerExpr(StringToPointerExpr *E, StringRef label) {
|
|
printCommon(E, "string_to_pointer", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitPointerToPointerExpr(PointerToPointerExpr *E, StringRef label) {
|
|
printCommon(E, "pointer_to_pointer", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitForeignObjectConversionExpr(ForeignObjectConversionExpr *E, StringRef label) {
|
|
printCommon(E, "foreign_object_conversion", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitUnevaluatedInstanceExpr(UnevaluatedInstanceExpr *E, StringRef label) {
|
|
printCommon(E, "unevaluated_instance", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitDifferentiableFunctionExpr(DifferentiableFunctionExpr *E, StringRef label) {
|
|
printCommon(E, "differentiable_function", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitLinearFunctionExpr(LinearFunctionExpr *E, StringRef label) {
|
|
printCommon(E, "linear_function", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitDifferentiableFunctionExtractOriginalExpr(
|
|
DifferentiableFunctionExtractOriginalExpr *E, StringRef label) {
|
|
printCommon(E, "differentiable_function_extract_original", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitLinearFunctionExtractOriginalExpr(
|
|
LinearFunctionExtractOriginalExpr *E, StringRef label) {
|
|
printCommon(E, "linear_function_extract_original", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitLinearToDifferentiableFunctionExpr(
|
|
LinearToDifferentiableFunctionExpr *E, StringRef label) {
|
|
printCommon(E, "linear_to_differentiable_function", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
|
|
void visitInOutExpr(InOutExpr *E, StringRef label) {
|
|
printCommon(E, "inout_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
|
|
void visitVarargExpansionExpr(VarargExpansionExpr *E, StringRef label) {
|
|
printCommon(E, "vararg_expansion_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
|
|
void visitPackExpansionExpr(PackExpansionExpr *E, StringRef label) {
|
|
printCommon(E, "pack_expansion_expr", label);
|
|
printRec(E->getPatternExpr());
|
|
printFoot();
|
|
}
|
|
|
|
void visitPackElementExpr(PackElementExpr *E, StringRef label) {
|
|
printCommon(E, "pack_element_expr", label);
|
|
printRec(E->getPackRefExpr());
|
|
printFoot();
|
|
}
|
|
|
|
void visitMaterializePackExpr(MaterializePackExpr *E, StringRef label) {
|
|
printCommon(E, "materialize_pack_expr", label);
|
|
printRec(E->getFromExpr());
|
|
printFoot();
|
|
}
|
|
|
|
void visitForceTryExpr(ForceTryExpr *E, StringRef label) {
|
|
printCommon(E, "force_try_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
|
|
void visitOptionalTryExpr(OptionalTryExpr *E, StringRef label) {
|
|
printCommon(E, "optional_try_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
|
|
void visitTryExpr(TryExpr *E, StringRef label) {
|
|
printCommon(E, "try_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
|
|
void visitSequenceExpr(SequenceExpr *E, StringRef label) {
|
|
printCommon(E, "sequence_expr", label);
|
|
for (unsigned i = 0, e = E->getNumElements(); i != e; ++i) {
|
|
printRec(E->getElement(i));
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitCaptureListExpr(CaptureListExpr *E, StringRef label) {
|
|
printCommon(E, "capture_list", label);
|
|
for (auto capture : E->getCaptureList()) {
|
|
printRec(capture.PBD);
|
|
}
|
|
printRec(E->getClosureBody());
|
|
printFoot();
|
|
}
|
|
|
|
void printClosure(AbstractClosureExpr *E, char const *name,
|
|
StringRef label) {
|
|
printCommon(E, name, label);
|
|
|
|
// If we aren't printing to standard error or the debugger output stream,
|
|
// this client expects to see the computed discriminator. Compute it now.
|
|
if (hasNonStandardOutput())
|
|
(void)E->getDiscriminator();
|
|
|
|
printField(E->getRawDiscriminator(), "discriminator", DiscriminatorColor);
|
|
|
|
switch (auto isolation = E->getActorIsolation()) {
|
|
case ClosureActorIsolation::Nonisolated:
|
|
break;
|
|
|
|
case ClosureActorIsolation::ActorInstance:
|
|
printFieldQuoted(isolation.getActorInstance()->printRef(),
|
|
"actor_isolated", CapturesColor);
|
|
break;
|
|
|
|
case ClosureActorIsolation::GlobalActor:
|
|
printFieldQuoted(isolation.getGlobalActor().getString(),
|
|
"global_actor_isolated", CapturesColor);
|
|
break;
|
|
}
|
|
|
|
if (!E->getCaptureInfo().isTrivial()) {
|
|
printFieldRaw([&](raw_ostream &OS) {
|
|
E->getCaptureInfo().print(OS);
|
|
}, "", CapturesColor);
|
|
}
|
|
// Printing a function type doesn't indicate whether it's escaping because it doesn't
|
|
// matter in 99% of contexts. AbstractClosureExpr nodes are one of the only exceptions.
|
|
if (auto Ty = GetTypeOfExpr(E)) {
|
|
if (auto fType = Ty->getAs<AnyFunctionType>()) {
|
|
printFlag(!fType->getExtInfo().isNoEscape(), "escaping",
|
|
ClosureModifierColor);
|
|
printFlag(fType->getExtInfo().isSendable(), "sendable",
|
|
ClosureModifierColor);
|
|
}
|
|
}
|
|
}
|
|
|
|
void visitClosureExpr(ClosureExpr *E, StringRef label) {
|
|
printClosure(E, "closure_expr", label);
|
|
printFlag(E->hasSingleExpressionBody(), "single_expression",
|
|
ClosureModifierColor);
|
|
printFlag(E->allowsImplicitSelfCapture(), "implicit_self",
|
|
ClosureModifierColor);
|
|
printFlag(E->inheritsActorContext(), "inherits_actor_context",
|
|
ClosureModifierColor);
|
|
|
|
if (E->getParameters()) {
|
|
printRec(E->getParameters(), &E->getASTContext());
|
|
}
|
|
printRec(E->getBody(), &E->getASTContext());
|
|
|
|
printFoot();
|
|
}
|
|
void visitAutoClosureExpr(AutoClosureExpr *E, StringRef label) {
|
|
printClosure(E, "autoclosure_expr", label);
|
|
|
|
if (E->getParameters()) {
|
|
printRec(E->getParameters(), &E->getASTContext());
|
|
}
|
|
|
|
printRec(E->getSingleExpressionBody());
|
|
printFoot();
|
|
}
|
|
|
|
void visitDynamicTypeExpr(DynamicTypeExpr *E, StringRef label) {
|
|
printCommon(E, "metatype_expr", label);
|
|
printRec(E->getBase());
|
|
printFoot();
|
|
}
|
|
|
|
void visitOpaqueValueExpr(OpaqueValueExpr *E, StringRef label) {
|
|
printCommon(E, "opaque_value_expr", label);
|
|
printNameRaw([&](raw_ostream &OS) { OS << (void*)E; });
|
|
printFoot();
|
|
}
|
|
|
|
void visitPropertyWrapperValuePlaceholderExpr(
|
|
PropertyWrapperValuePlaceholderExpr *E, StringRef label) {
|
|
printCommon(E, "property_wrapper_value_placeholder_expr", label);
|
|
printRec(E->getOpaqueValuePlaceholder());
|
|
if (auto *value = E->getOriginalWrappedValue()) {
|
|
printRec(value);
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitAppliedPropertyWrapperExpr(AppliedPropertyWrapperExpr *E, StringRef label) {
|
|
printCommon(E, "applied_property_wrapper_expr", label);
|
|
printRec(E->getValue());
|
|
printFoot();
|
|
}
|
|
|
|
void visitDefaultArgumentExpr(DefaultArgumentExpr *E, StringRef label) {
|
|
printCommon(E, "default_argument_expr", label);
|
|
printDeclRefField(E->getDefaultArgsOwner(), "default_args_owner");
|
|
printField(E->getParamIndex(), "param");
|
|
printFoot();
|
|
}
|
|
|
|
void printApplyExpr(ApplyExpr *E, const char *NodeName, StringRef label) {
|
|
printCommon(E, NodeName, label);
|
|
if (E->isThrowsSet()) {
|
|
printFlag(E->throws() ? "throws" : "nothrow", ExprModifierColor);
|
|
}
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
auto isolationCrossing = E->getIsolationCrossing();
|
|
if (isolationCrossing.has_value()) {
|
|
OS << "{caller='";
|
|
simple_display(OS, isolationCrossing.value().getCallerIsolation());
|
|
OS << "', callee='";
|
|
simple_display(OS, isolationCrossing.value().getCalleeIsolation());
|
|
OS << "'}";
|
|
} else {
|
|
OS << "none";
|
|
}
|
|
}, "isolation_crossing", ExprModifierColor);
|
|
|
|
printRec(E->getFn());
|
|
printRec(E->getArgs());
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitCallExpr(CallExpr *E, StringRef label) {
|
|
printApplyExpr(E, "call_expr", label);
|
|
}
|
|
void visitPrefixUnaryExpr(PrefixUnaryExpr *E, StringRef label) {
|
|
printApplyExpr(E, "prefix_unary_expr", label);
|
|
}
|
|
void visitPostfixUnaryExpr(PostfixUnaryExpr *E, StringRef label) {
|
|
printApplyExpr(E, "postfix_unary_expr", label);
|
|
}
|
|
void visitBinaryExpr(BinaryExpr *E, StringRef label) {
|
|
printApplyExpr(E, "binary_expr", label);
|
|
}
|
|
void visitDotSyntaxCallExpr(DotSyntaxCallExpr *E, StringRef label) {
|
|
printApplyExpr(E, "dot_syntax_call_expr", label);
|
|
}
|
|
void visitConstructorRefCallExpr(ConstructorRefCallExpr *E, StringRef label) {
|
|
printApplyExpr(E, "constructor_ref_call_expr", label);
|
|
}
|
|
void visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *E, StringRef label) {
|
|
printCommon(E, "dot_syntax_base_ignored", label);
|
|
printRec(E->getLHS());
|
|
printRec(E->getRHS());
|
|
printFoot();
|
|
}
|
|
|
|
void printExplicitCastExpr(ExplicitCastExpr *E, const char *name, StringRef label) {
|
|
printCommon(E, name, label);
|
|
|
|
if (auto checkedCast = dyn_cast<CheckedCastExpr>(E))
|
|
printFlag(getDumpString(checkedCast->getCastKind()));
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
if (GetTypeOfTypeRepr)
|
|
GetTypeOfTypeRepr(E->getCastTypeRepr()).print(OS);
|
|
else
|
|
E->getCastType().print(OS);
|
|
}, "written_type", TypeReprColor);
|
|
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitForcedCheckedCastExpr(ForcedCheckedCastExpr *E, StringRef label) {
|
|
printExplicitCastExpr(E, "forced_checked_cast_expr", label);
|
|
}
|
|
void visitConditionalCheckedCastExpr(ConditionalCheckedCastExpr *E, StringRef label) {
|
|
printExplicitCastExpr(E, "conditional_checked_cast_expr", label);
|
|
}
|
|
void visitIsExpr(IsExpr *E, StringRef label) {
|
|
printExplicitCastExpr(E, "is_subtype_expr", label);
|
|
}
|
|
void visitCoerceExpr(CoerceExpr *E, StringRef label) {
|
|
printExplicitCastExpr(E, "coerce_expr", label);
|
|
}
|
|
void visitArrowExpr(ArrowExpr *E, StringRef label) {
|
|
printCommon(E, "arrow", label);
|
|
|
|
printFlag(E->getAsyncLoc().isValid(), "async");
|
|
printFlag(E->getThrowsLoc().isValid(), "throws");
|
|
|
|
printRec(E->getArgsExpr());
|
|
printRec(E->getResultExpr());
|
|
|
|
printFoot();
|
|
}
|
|
void visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *E, StringRef label) {
|
|
printCommon(E, "rebind_self_in_constructor_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitTernaryExpr(TernaryExpr *E, StringRef label) {
|
|
printCommon(E, "ternary_expr", label);
|
|
printRec(E->getCondExpr());
|
|
printRec(E->getThenExpr());
|
|
printRec(E->getElseExpr());
|
|
printFoot();
|
|
}
|
|
void visitAssignExpr(AssignExpr *E, StringRef label) {
|
|
printCommon(E, "assign_expr", label);
|
|
printRec(E->getDest());
|
|
printRec(E->getSrc());
|
|
printFoot();
|
|
}
|
|
void visitEnumIsCaseExpr(EnumIsCaseExpr *E, StringRef label) {
|
|
printCommon(E, "enum_is_case_expr", label);
|
|
printName(E->getEnumElement()->getBaseIdentifier());
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitUnresolvedPatternExpr(UnresolvedPatternExpr *E, StringRef label) {
|
|
printCommon(E, "unresolved_pattern_expr", label);
|
|
printRec(E->getSubPattern());
|
|
printFoot();
|
|
}
|
|
void visitBindOptionalExpr(BindOptionalExpr *E, StringRef label) {
|
|
printCommon(E, "bind_optional_expr", label);
|
|
printField(E->getDepth(), "depth");
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitOptionalEvaluationExpr(OptionalEvaluationExpr *E, StringRef label) {
|
|
printCommon(E, "optional_evaluation_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitForceValueExpr(ForceValueExpr *E, StringRef label) {
|
|
printCommon(E, "force_value_expr", label);
|
|
|
|
printFlag(E->isForceOfImplicitlyUnwrappedOptional(), "implicit_iuo_unwrap",
|
|
ExprModifierColor);
|
|
|
|
printRec(E->getSubExpr());
|
|
|
|
printFoot();
|
|
}
|
|
void visitOpenExistentialExpr(OpenExistentialExpr *E, StringRef label) {
|
|
printCommon(E, "open_existential_expr", label);
|
|
printRec(E->getOpaqueValue());
|
|
printRec(E->getExistentialValue());
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitMakeTemporarilyEscapableExpr(MakeTemporarilyEscapableExpr *E, StringRef label) {
|
|
printCommon(E, "make_temporarily_escapable_expr", label);
|
|
printRec(E->getOpaqueValue());
|
|
printRec(E->getNonescapingClosureValue());
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitEditorPlaceholderExpr(EditorPlaceholderExpr *E, StringRef label) {
|
|
printCommon(E, "editor_placeholder_expr", label);
|
|
|
|
// Print the trailing angle bracket location
|
|
if (auto Ty = GetTypeOfExpr(E)) {
|
|
auto &Ctx = Ty->getASTContext();
|
|
printSourceLoc(E->getTrailingAngleBracketLoc(), &Ctx,
|
|
"trailing_angle_bracket_loc");
|
|
}
|
|
auto *TyR = E->getPlaceholderTypeRepr();
|
|
auto *ExpTyR = E->getTypeForExpansion();
|
|
if (TyR)
|
|
printRec(TyR);
|
|
if (ExpTyR && ExpTyR != TyR) {
|
|
printRec(ExpTyR);
|
|
}
|
|
printSemanticExpr(E->getSemanticExpr());
|
|
printFoot();
|
|
}
|
|
void visitLazyInitializerExpr(LazyInitializerExpr *E, StringRef label) {
|
|
printCommon(E, "lazy_initializer_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
void visitObjCSelectorExpr(ObjCSelectorExpr *E, StringRef label) {
|
|
printCommon(E, "objc_selector_expr", label);
|
|
|
|
printField(E->getSelectorKind(), "kind");
|
|
printDeclRefField(E->getMethod(), "decl");
|
|
|
|
printRec(E->getSubExpr());
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitKeyPathExpr(KeyPathExpr *E, StringRef label) {
|
|
printCommon(E, "keypath_expr", label);
|
|
|
|
printFlag(E->isObjC(), "objc");
|
|
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("components", ExprColor, label);
|
|
for (unsigned i : indices(E->getComponents())) {
|
|
auto &component = E->getComponents()[i];
|
|
printRecArbitrary([&](StringRef label) {
|
|
switch (component.getKind()) {
|
|
case KeyPathExpr::Component::Kind::Invalid:
|
|
printHead("invalid", ASTNodeColor);
|
|
break;
|
|
|
|
case KeyPathExpr::Component::Kind::OptionalChain:
|
|
printHead("optional_chain", ASTNodeColor);
|
|
break;
|
|
|
|
case KeyPathExpr::Component::Kind::OptionalForce:
|
|
printHead("optional_force", ASTNodeColor);
|
|
break;
|
|
|
|
case KeyPathExpr::Component::Kind::OptionalWrap:
|
|
printHead("optional_wrap", ASTNodeColor);
|
|
break;
|
|
|
|
case KeyPathExpr::Component::Kind::Property:
|
|
printHead("property", ASTNodeColor);
|
|
printDeclRefField(component.getDeclRef(), "decl");
|
|
break;
|
|
|
|
case KeyPathExpr::Component::Kind::Subscript:
|
|
printHead("subscript", ASTNodeColor);
|
|
printDeclRefField(component.getDeclRef(), "decl");
|
|
break;
|
|
|
|
case KeyPathExpr::Component::Kind::UnresolvedProperty:
|
|
printHead("unresolved_property", ASTNodeColor);
|
|
printFieldQuoted(component.getUnresolvedDeclName(), "decl_name",
|
|
IdentifierColor);
|
|
break;
|
|
|
|
case KeyPathExpr::Component::Kind::UnresolvedSubscript:
|
|
printHead("unresolved_subscript", ASTNodeColor);
|
|
break;
|
|
case KeyPathExpr::Component::Kind::Identity:
|
|
printHead("identity", ASTNodeColor);
|
|
break;
|
|
|
|
case KeyPathExpr::Component::Kind::TupleElement:
|
|
printHead("tuple_element", ASTNodeColor);
|
|
printField(component.getTupleIndex(), "index", DiscriminatorColor);
|
|
break;
|
|
case KeyPathExpr::Component::Kind::DictionaryKey:
|
|
printHead("dict_key", ASTNodeColor);
|
|
printFieldQuoted(component.getUnresolvedDeclName(), "key",
|
|
IdentifierColor);
|
|
break;
|
|
case KeyPathExpr::Component::Kind::CodeCompletion:
|
|
printHead("completion", ASTNodeColor);
|
|
break;
|
|
}
|
|
printFieldQuoted(GetTypeOfKeyPathComponent(E, i), "type");
|
|
if (auto *args = component.getSubscriptArgs()) {
|
|
printRec(args);
|
|
}
|
|
printFoot();
|
|
});
|
|
}
|
|
|
|
printFoot();
|
|
});
|
|
|
|
if (auto stringLiteral = E->getObjCStringLiteralExpr()) {
|
|
printRec(stringLiteral, "objc_string_literal");
|
|
}
|
|
if (!E->isObjC()) {
|
|
if (auto root = E->getParsedRoot()) {
|
|
printRec(root, "parsed_root");
|
|
}
|
|
if (auto path = E->getParsedPath()) {
|
|
printRec(path, "parsed_path");
|
|
}
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitKeyPathDotExpr(KeyPathDotExpr *E, StringRef label) {
|
|
printCommon(E, "key_path_dot_expr", label);
|
|
printFoot();
|
|
}
|
|
|
|
void visitSingleValueStmtExpr(SingleValueStmtExpr *E, StringRef label) {
|
|
printCommon(E, "single_value_stmt_expr", label);
|
|
printRec(E->getStmt(), &E->getDeclContext()->getASTContext());
|
|
printFoot();
|
|
}
|
|
|
|
void visitOneWayExpr(OneWayExpr *E, StringRef label) {
|
|
printCommon(E, "one_way_expr", label);
|
|
printRec(E->getSubExpr());
|
|
printFoot();
|
|
}
|
|
|
|
void visitTapExpr(TapExpr *E, StringRef label) {
|
|
printCommon(E, "tap_expr", label);
|
|
printDeclRefField(E->getVar(), "var");
|
|
printRec(E->getSubExpr());
|
|
printRec(E->getBody(), &E->getVar()->getDeclContext()->getASTContext());
|
|
printFoot();
|
|
}
|
|
|
|
void visitTypeJoinExpr(TypeJoinExpr *E, StringRef label) {
|
|
printCommon(E, "type_join_expr", label);
|
|
|
|
if (auto *var = E->getVar()) {
|
|
printRec(var, "var");
|
|
}
|
|
|
|
if (auto *SVE = E->getSingleValueStmtExpr()) {
|
|
printRec(SVE, "single_value_stmt_expr");
|
|
}
|
|
|
|
for (auto *member : E->getElements()) {
|
|
printRec(member);
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitMacroExpansionExpr(MacroExpansionExpr *E, StringRef label) {
|
|
printCommon(E, "macro_expansion_expr", label);
|
|
|
|
printFieldQuoted(E->getMacroName(), "name", IdentifierColor);
|
|
printField(E->getRawDiscriminator(), "discriminator", DiscriminatorColor);
|
|
|
|
if (E->getArgs()) {
|
|
printRec(E->getArgs());
|
|
}
|
|
if (auto rewritten = E->getRewritten()) {
|
|
printRec(rewritten, "rewritten");
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
void Expr::dump() const {
|
|
dump(llvm::errs());
|
|
llvm::errs() << "\n";
|
|
}
|
|
|
|
void Expr::dump(raw_ostream &OS, llvm::function_ref<Type(Expr *)> getTypeOfExpr,
|
|
llvm::function_ref<Type(TypeRepr *)> getTypeOfTypeRepr,
|
|
llvm::function_ref<Type(KeyPathExpr *E, unsigned index)>
|
|
getTypeOfKeyPathComponent,
|
|
unsigned Indent) const {
|
|
PrintExpr(OS, Indent, getTypeOfExpr, getTypeOfTypeRepr,
|
|
getTypeOfKeyPathComponent)
|
|
.visit(const_cast<Expr *>(this), "");
|
|
}
|
|
|
|
void Expr::dump(raw_ostream &OS, unsigned Indent) const {
|
|
dump(OS, defaultGetTypeOfExpr, /*getTypeOfTypeRepr*/ nullptr,
|
|
defaultGetTypeOfKeyPathComponent, Indent);
|
|
}
|
|
|
|
void Expr::print(ASTPrinter &Printer, const PrintOptions &Opts) const {
|
|
// FIXME: Fully use the ASTPrinter.
|
|
llvm::SmallString<128> Str;
|
|
llvm::raw_svector_ostream OS(Str);
|
|
dump(OS);
|
|
Printer << OS.str();
|
|
}
|
|
|
|
void ArgumentList::dump() const {
|
|
dump(llvm::errs(), 0);
|
|
llvm::errs() << '\n';
|
|
}
|
|
|
|
void ArgumentList::dump(raw_ostream &OS, unsigned Indent) const {
|
|
PrintBase(OS, Indent).visitArgumentList(this);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Printing for TypeRepr and all subclasses.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr, void, StringRef>,
|
|
public PrintBase {
|
|
public:
|
|
using PrintBase::PrintBase;
|
|
|
|
void printCommon(const char *Name, StringRef Label) {
|
|
printHead(Name, TypeReprColor, Label);
|
|
}
|
|
|
|
void visitErrorTypeRepr(ErrorTypeRepr *T, StringRef label) {
|
|
printCommon("type_error", label);
|
|
}
|
|
|
|
void visitAttributedTypeRepr(AttributedTypeRepr *T, StringRef label) {
|
|
printCommon("type_attributed", label);
|
|
printFieldQuotedRaw([&](raw_ostream &OS) { T->printAttrs(OS); }, "attrs");
|
|
printRec(T->getTypeRepr());
|
|
}
|
|
|
|
void visitIdentTypeRepr(IdentTypeRepr *T, StringRef label) {
|
|
printCommon("type_ident", label);
|
|
|
|
printFieldQuoted(T->getNameRef(), "id", IdentifierColor);
|
|
if (T->isBound())
|
|
printFieldQuoted(T->getBoundDecl()->printRef(), "bind");
|
|
else
|
|
printFlag("unbound");
|
|
|
|
if (auto *GenIdT = dyn_cast<GenericIdentTypeRepr>(T)) {
|
|
for (auto genArg : GenIdT->getGenericArgs()) {
|
|
printRec(genArg);
|
|
}
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitMemberTypeRepr(MemberTypeRepr *T, StringRef label) {
|
|
printCommon("type_member", label);
|
|
|
|
printRec(T->getBaseComponent());
|
|
for (auto *comp : T->getMemberComponents()) {
|
|
printRec(comp);
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitFunctionTypeRepr(FunctionTypeRepr *T, StringRef label) {
|
|
printCommon("type_function", label);
|
|
|
|
printFlag(T->isAsync(), "async");
|
|
printFlag(T->isThrowing(), "throws");
|
|
|
|
printRec(T->getArgsTypeRepr());
|
|
printRec(T->getResultTypeRepr());
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitArrayTypeRepr(ArrayTypeRepr *T, StringRef label) {
|
|
printCommon("type_array", label);
|
|
printRec(T->getBase());
|
|
printFoot();
|
|
}
|
|
|
|
void visitDictionaryTypeRepr(DictionaryTypeRepr *T, StringRef label) {
|
|
printCommon("type_dictionary", label);
|
|
printRec(T->getKey());
|
|
printRec(T->getValue());
|
|
printFoot();
|
|
}
|
|
|
|
void visitVarargTypeRepr(VarargTypeRepr *T, StringRef label) {
|
|
printCommon("vararg", label);
|
|
printRec(T->getElementType());
|
|
printFoot();
|
|
}
|
|
|
|
void visitPackTypeRepr(PackTypeRepr *T, StringRef label) {
|
|
printCommon("pack", label);
|
|
for (auto elt : T->getElements())
|
|
printRec(elt);
|
|
printFoot();
|
|
}
|
|
|
|
void visitPackExpansionTypeRepr(PackExpansionTypeRepr *T, StringRef label) {
|
|
printCommon("pack_expansion", label);
|
|
printRec(T->getPatternType());
|
|
printFoot();
|
|
}
|
|
|
|
void visitPackElementTypeRepr(PackElementTypeRepr *T, StringRef label) {
|
|
printCommon("pack_element", label);
|
|
printRec(T->getPackType());
|
|
printFoot();
|
|
}
|
|
|
|
void visitTupleTypeRepr(TupleTypeRepr *T, StringRef label) {
|
|
printCommon("type_tuple", label);
|
|
|
|
if (T->hasElementNames()) {
|
|
printFieldQuotedRaw([&](raw_ostream &OS) {
|
|
llvm::interleave(T->getElements(), OS,
|
|
[&](const TupleTypeReprElement &Elt) {
|
|
auto name = Elt.Name;
|
|
if (Elt.UnderscoreLoc.isValid())
|
|
OS << (name.empty() ? "_" : "_ " + name.str());
|
|
else
|
|
OS << (name.empty() ? "''" : name.str());
|
|
}, ",");
|
|
}, "names");
|
|
}
|
|
|
|
for (auto elem : T->getElements()) {
|
|
printRec(elem.Type);
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitCompositionTypeRepr(CompositionTypeRepr *T, StringRef label) {
|
|
printCommon("type_composite", label);
|
|
for (auto elem : T->getTypes()) {
|
|
printRec(elem);
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitMetatypeTypeRepr(MetatypeTypeRepr *T, StringRef label) {
|
|
printCommon("type_metatype", label);
|
|
printRec(T->getBase());
|
|
printFoot();
|
|
}
|
|
|
|
void visitProtocolTypeRepr(ProtocolTypeRepr *T, StringRef label) {
|
|
printCommon("type_protocol", label);
|
|
printRec(T->getBase());
|
|
printFoot();
|
|
}
|
|
|
|
void visitOwnershipTypeRepr(OwnershipTypeRepr *T, StringRef label) {
|
|
printCommon("type_ownership", label);
|
|
printFlag(getDumpString(T->getSpecifier()));
|
|
printRec(T->getBase());
|
|
printFoot();
|
|
}
|
|
|
|
void visitIsolatedTypeRepr(IsolatedTypeRepr *T, StringRef label) {
|
|
printCommon("isolated", label);
|
|
printRec(T->getBase());
|
|
printFoot();
|
|
}
|
|
|
|
void visitCompileTimeConstTypeRepr(CompileTimeConstTypeRepr *T, StringRef label) {
|
|
printCommon("_const", label);
|
|
printRec(T->getBase());
|
|
printFoot();
|
|
}
|
|
|
|
void visitOptionalTypeRepr(OptionalTypeRepr *T, StringRef label) {
|
|
printCommon("type_optional", label);
|
|
printRec(T->getBase());
|
|
printFoot();
|
|
}
|
|
|
|
void visitImplicitlyUnwrappedOptionalTypeRepr(
|
|
ImplicitlyUnwrappedOptionalTypeRepr *T, StringRef label) {
|
|
printCommon("type_implicitly_unwrapped_optional", label);
|
|
printRec(T->getBase());
|
|
printFoot();
|
|
}
|
|
|
|
void visitOpaqueReturnTypeRepr(OpaqueReturnTypeRepr *T, StringRef label) {
|
|
printCommon("type_opaque_return", label);
|
|
printRec(T->getConstraint());
|
|
printFoot();
|
|
}
|
|
|
|
void visitNamedOpaqueReturnTypeRepr(NamedOpaqueReturnTypeRepr *T, StringRef label) {
|
|
printCommon("type_named_opaque_return", label);
|
|
printRec(T->getBase());
|
|
printFoot();
|
|
}
|
|
|
|
void visitExistentialTypeRepr(ExistentialTypeRepr *T, StringRef label) {
|
|
printCommon("type_existential", label);
|
|
printRec(T->getConstraint());
|
|
printFoot();
|
|
}
|
|
|
|
void visitPlaceholderTypeRepr(PlaceholderTypeRepr *T, StringRef label) {
|
|
printCommon("type_placeholder", label);
|
|
printFoot();
|
|
}
|
|
|
|
void visitFixedTypeRepr(FixedTypeRepr *T, StringRef label) {
|
|
printCommon("type_fixed", label);
|
|
|
|
auto Ty = T->getType();
|
|
if (Ty) {
|
|
printSourceLoc(T->getLoc(), &Ty->getASTContext());
|
|
}
|
|
|
|
printRec(Ty, "type");
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitSelfTypeRepr(SelfTypeRepr *T, StringRef label) {
|
|
printCommon("type_self", label);
|
|
|
|
auto Ty = T->getType();
|
|
if (Ty) {
|
|
printSourceLoc(T->getLoc(), &Ty->getASTContext());
|
|
}
|
|
|
|
printRec(Ty, "type");
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitSILBoxTypeRepr(SILBoxTypeRepr *T, StringRef label) {
|
|
printCommon("sil_box", label);
|
|
|
|
for (auto &Field : T->getFields()) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printCommon("sil_box_field", label);
|
|
printFlag(Field.isMutable(), "mutable");
|
|
|
|
printRec(Field.getFieldType());
|
|
printFoot();
|
|
});
|
|
}
|
|
|
|
printRecRange(T->getGenericArguments(), "generic_arguments");
|
|
|
|
printFoot();
|
|
}
|
|
};
|
|
|
|
void PrintBase::printRec(Decl *D, StringRef label) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
if (!D) {
|
|
printHead("<null decl>", DeclColor, label);
|
|
printFoot();
|
|
} else {
|
|
PrintDecl(OS, Indent, GetTypeOfExpr, GetTypeOfTypeRepr,
|
|
GetTypeOfKeyPathComponent).visit(D, label);
|
|
}
|
|
}, label);
|
|
}
|
|
void PrintBase::printRec(Expr *E, StringRef label) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
if (!E) {
|
|
printHead("<null expr>", ExprColor, label);
|
|
printFoot();
|
|
} else {
|
|
PrintExpr(OS, Indent, GetTypeOfExpr, GetTypeOfTypeRepr,
|
|
GetTypeOfKeyPathComponent).visit(E, label);
|
|
}
|
|
}, label);
|
|
}
|
|
void PrintBase::printRec(Stmt *S, const ASTContext *Ctx, StringRef label) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
if (!S) {
|
|
printHead("<null stmt>", ExprColor, label);
|
|
printFoot();
|
|
} else {
|
|
PrintStmt(OS, Ctx, Indent, GetTypeOfExpr, GetTypeOfTypeRepr,
|
|
GetTypeOfKeyPathComponent).visit(S, label);
|
|
}
|
|
}, label);
|
|
}
|
|
void PrintBase::printRec(TypeRepr *T, StringRef label) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
if (!T) {
|
|
printHead("<null typerepr>", TypeReprColor, label);
|
|
printFoot();
|
|
} else {
|
|
PrintTypeRepr(OS, Indent, GetTypeOfExpr, GetTypeOfTypeRepr,
|
|
GetTypeOfKeyPathComponent).visit(T, label);
|
|
}
|
|
}, label);
|
|
}
|
|
void PrintBase::printRec(const Pattern *P, StringRef label) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
if (!P) {
|
|
printHead("<null pattern>", PatternColor, label);
|
|
printFoot();
|
|
} else {
|
|
PrintPattern(OS, Indent, GetTypeOfExpr, GetTypeOfTypeRepr,
|
|
GetTypeOfKeyPathComponent).visit(const_cast<Pattern *>(P),
|
|
label);
|
|
}
|
|
}, label);
|
|
}
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
void TypeRepr::dump() const {
|
|
dump(llvm::errs());
|
|
llvm::errs() << '\n';
|
|
}
|
|
void TypeRepr::dump(raw_ostream &os, unsigned indent) const {
|
|
PrintTypeRepr(os, indent).visit(const_cast<TypeRepr*>(this), "");
|
|
}
|
|
|
|
namespace {
|
|
|
|
class PrintConformance : public PrintBase {
|
|
public:
|
|
using PrintBase::PrintBase;
|
|
|
|
void visitProtocolConformanceRef(const ProtocolConformanceRef conformance,
|
|
VisitedConformances &visited,
|
|
StringRef label) {
|
|
if (conformance.isInvalid()) {
|
|
printHead("invalid_conformance", ASTNodeColor, label);
|
|
printFoot();
|
|
} else if (conformance.isConcrete()) {
|
|
visitProtocolConformance(conformance.getConcrete(), visited, label);
|
|
} else if (conformance.isPack()) {
|
|
visitPackConformance(conformance.getPack(), visited, label);
|
|
} else {
|
|
assert(conformance.isAbstract());
|
|
|
|
printHead("abstract_conformance", ASTNodeColor, label);
|
|
printFieldQuoted(conformance.getAbstract()->getName(), "protocol");
|
|
printFoot();
|
|
}
|
|
}
|
|
|
|
void visitProtocolConformance(const ProtocolConformance *conformance,
|
|
VisitedConformances &visited, StringRef label) {
|
|
// A recursive conformance shouldn't have its contents printed, or there's
|
|
// infinite recursion. (This also avoids printing things that occur multiple
|
|
// times in a conformance hierarchy.)
|
|
auto shouldPrintDetails = visited.insert(conformance).second;
|
|
|
|
auto printCommon = [&](StringRef kind) {
|
|
printHead(kind, ASTNodeColor, label);
|
|
printFieldQuoted(conformance->getType(), "type");
|
|
printFieldQuoted(conformance->getProtocol()->getName(), "protocol");
|
|
printFlag(!shouldPrintDetails, "<details printed above>");
|
|
};
|
|
|
|
switch (conformance->getKind()) {
|
|
case ProtocolConformanceKind::Normal: {
|
|
auto normal = cast<NormalProtocolConformance>(conformance);
|
|
|
|
printCommon("normal_conformance");
|
|
if (!shouldPrintDetails)
|
|
break;
|
|
|
|
// Maybe print information about the conforming context?
|
|
if (normal->isLazilyLoaded()) {
|
|
printFlag("lazy");
|
|
} else {
|
|
normal->forEachTypeWitness([&](const AssociatedTypeDecl *req, Type ty,
|
|
const TypeDecl *) -> bool {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("assoc_type", ASTNodeColor, label);
|
|
printFieldQuoted(req->getName(), "req");
|
|
printFieldQuoted(Type(ty->getDesugaredType()), "type", TypeColor);
|
|
printFoot();
|
|
});
|
|
return false;
|
|
});
|
|
normal->forEachValueWitness([&](const ValueDecl *req,
|
|
Witness witness) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("value", ASTNodeColor, label);
|
|
printFieldQuoted(req->getName(), "req");
|
|
if (!witness)
|
|
printFlag("no_witness");
|
|
else if (witness.getDecl() == req)
|
|
printFlag("dynamic_witness");
|
|
else
|
|
printFieldQuotedRaw([&](raw_ostream &out) {
|
|
witness.getDecl()->dumpRef(out);
|
|
}, "witness");
|
|
printFoot();
|
|
});
|
|
});
|
|
|
|
for (auto sigConf : normal->getSignatureConformances()) {
|
|
printRec(sigConf, visited);
|
|
}
|
|
}
|
|
|
|
if (auto condReqs = normal->getConditionalRequirementsIfAvailable()) {
|
|
for (auto requirement : *condReqs) {
|
|
printRec(requirement);
|
|
}
|
|
} else {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("<conditional requirements unable to be computed>",
|
|
ASTNodeColor);
|
|
printFoot();
|
|
});
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ProtocolConformanceKind::Self: {
|
|
printCommon("self_conformance");
|
|
break;
|
|
}
|
|
|
|
case ProtocolConformanceKind::Inherited: {
|
|
auto conf = cast<InheritedProtocolConformance>(conformance);
|
|
printCommon("inherited_conformance");
|
|
if (!shouldPrintDetails)
|
|
break;
|
|
|
|
printRec(conf->getInheritedConformance(), visited);
|
|
break;
|
|
}
|
|
|
|
case ProtocolConformanceKind::Specialized: {
|
|
auto conf = cast<SpecializedProtocolConformance>(conformance);
|
|
printCommon("specialized_conformance");
|
|
if (!shouldPrintDetails)
|
|
break;
|
|
|
|
printRec(conf->getSubstitutionMap(), visited);
|
|
if (auto condReqs = conf->getConditionalRequirementsIfAvailableOrCached(/*computeIfPossible=*/false)) {
|
|
for (auto subReq : *condReqs) {
|
|
printRec(subReq);
|
|
}
|
|
} else {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("<conditional requirements unable to be computed>",
|
|
ASTNodeColor);
|
|
printFoot();
|
|
});
|
|
}
|
|
printRec(conf->getGenericConformance(), visited);
|
|
break;
|
|
}
|
|
|
|
case ProtocolConformanceKind::Builtin: {
|
|
printCommon("builtin_conformance");
|
|
}
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitPackConformance(const PackConformance *conformance,
|
|
VisitedConformances &visited, StringRef label) {
|
|
printHead("pack_conformance", ASTNodeColor, label);
|
|
|
|
printFieldQuoted(Type(conformance->getType()), "type");
|
|
printFieldQuoted(conformance->getProtocol()->getName(), "protocol");
|
|
|
|
for (auto conformanceRef : conformance->getPatternConformances()) {
|
|
printRec(conformanceRef, visited);
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitSubstitutionMap(SubstitutionMap map,
|
|
SubstitutionMap::DumpStyle style,
|
|
VisitedConformances &visited, StringRef label) {
|
|
// In Minimal style, use single quote so this dump can appear in
|
|
// double-quoted fields without escaping.
|
|
std::optional<llvm::SaveAndRestore<char>> restoreQuote;
|
|
if (style == SubstitutionMap::DumpStyle::Minimal)
|
|
restoreQuote.emplace(quote, '\'');
|
|
|
|
auto genericSig = map.getGenericSignature();
|
|
printHead("substitution_map", ASTNodeColor, label);
|
|
SWIFT_DEFER { printFoot(); };
|
|
|
|
if (genericSig.isNull()) {
|
|
printFlag("null_generic_signature");
|
|
return;
|
|
}
|
|
|
|
printFieldQuotedRaw([&](raw_ostream &out) { genericSig->print(out); },
|
|
"generic_signature");
|
|
|
|
auto printSubstitution = [&](GenericTypeParamType * genericParam,
|
|
Type replacementType) {
|
|
printFieldQuotedRaw([&](raw_ostream &out) {
|
|
genericParam->print(out);
|
|
out << " -> ";
|
|
if (replacementType) {
|
|
PrintOptions opts;
|
|
opts.PrintForSIL = true;
|
|
opts.PrintTypesForDebugging = true;
|
|
replacementType->print(out, opts);
|
|
}
|
|
else
|
|
out << "<unresolved concrete type>";
|
|
}, "");
|
|
};
|
|
|
|
auto genericParams = genericSig.getGenericParams();
|
|
auto replacementTypes =
|
|
static_cast<const SubstitutionMap &>(map).getReplacementTypesBuffer();
|
|
for (unsigned i : indices(genericParams)) {
|
|
if (style == SubstitutionMap::DumpStyle::Minimal) {
|
|
printSubstitution(genericParams[i], replacementTypes[i]);
|
|
} else {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("substitution", ASTNodeColor, label);
|
|
printSubstitution(genericParams[i], replacementTypes[i]);
|
|
printFoot();
|
|
});
|
|
}
|
|
}
|
|
|
|
// A minimal dump doesn't need the details about the conformances, a lot of
|
|
// that info can be inferred from the signature.
|
|
if (style == SubstitutionMap::DumpStyle::Minimal)
|
|
return;
|
|
|
|
auto conformances = map.getConformances();
|
|
for (const auto &req : genericSig.getRequirements()) {
|
|
if (req.getKind() != RequirementKind::Conformance)
|
|
continue;
|
|
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("conformance", ASTNodeColor, label);
|
|
printFieldQuoted(req.getFirstType(), "type");
|
|
printRec(conformances.front(), visited);
|
|
printFoot();
|
|
});
|
|
conformances = conformances.slice(1);
|
|
}
|
|
}
|
|
};
|
|
|
|
void PrintBase::printRec(SubstitutionMap map, VisitedConformances &visited,
|
|
StringRef label) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
PrintConformance(OS, Indent)
|
|
.visitSubstitutionMap(map, SubstitutionMap::DumpStyle::Full, visited,
|
|
label);
|
|
}, label);
|
|
}
|
|
|
|
void PrintBase::printRec(const ProtocolConformanceRef &ref,
|
|
VisitedConformances &visited, StringRef label) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
PrintConformance(OS, Indent)
|
|
.visitProtocolConformanceRef(ref, visited, label);
|
|
}, label);
|
|
}
|
|
|
|
void PrintBase::printRec(const ProtocolConformance *conformance,
|
|
VisitedConformances &visited, StringRef label) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
PrintConformance(OS, Indent)
|
|
.visitProtocolConformance(conformance, visited, label);
|
|
}, label);
|
|
}
|
|
|
|
} // end anonymous namespace
|
|
|
|
void ProtocolConformanceRef::dump() const {
|
|
dump(llvm::errs());
|
|
llvm::errs() << '\n';
|
|
}
|
|
|
|
void ProtocolConformanceRef::dump(llvm::raw_ostream &out, unsigned indent,
|
|
bool details) const {
|
|
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;
|
|
if (!details && isConcrete())
|
|
visited.insert(getConcrete());
|
|
|
|
PrintConformance(out, indent).visitProtocolConformanceRef(*this, visited, "");
|
|
}
|
|
|
|
void ProtocolConformanceRef::print(llvm::raw_ostream &out) const {
|
|
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;
|
|
PrintConformance(out, 0).visitProtocolConformanceRef(*this, visited, "");
|
|
}
|
|
|
|
void ProtocolConformance::dump() const {
|
|
auto &out = llvm::errs();
|
|
dump(out);
|
|
out << '\n';
|
|
}
|
|
|
|
void ProtocolConformance::dump(llvm::raw_ostream &out, unsigned indent) const {
|
|
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;
|
|
PrintConformance(out, indent).visitProtocolConformance(this, visited, "");
|
|
}
|
|
|
|
void PackConformance::dump(llvm::raw_ostream &out, unsigned indent) const {
|
|
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;
|
|
PrintConformance(out, indent).visitPackConformance(this, visited, "");
|
|
}
|
|
|
|
void SubstitutionMap::dump(llvm::raw_ostream &out, DumpStyle style,
|
|
unsigned indent) const {
|
|
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;
|
|
PrintConformance(out, indent).visitSubstitutionMap(*this, style, visited, "");
|
|
}
|
|
|
|
void SubstitutionMap::dump() const {
|
|
dump(llvm::errs());
|
|
llvm::errs() << "\n";
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Dumping for Types.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
class PrintType : public TypeVisitor<PrintType, void, StringRef>,
|
|
public PrintBase {
|
|
void printCommon(StringRef name, StringRef label) {
|
|
printHead(name, TypeColor, label);
|
|
}
|
|
|
|
void dumpParameterFlags(ParameterTypeFlags paramFlags) {
|
|
printFlag(paramFlags.isVariadic(), "vararg");
|
|
printFlag(paramFlags.isAutoClosure(), "autoclosure");
|
|
printFlag(paramFlags.isNonEphemeral(), "nonEphemeral");
|
|
printFlag(paramFlags.isCompileTimeConst(), "compileTimeConst");
|
|
printFlag(getDumpString(paramFlags.getValueOwnership()));
|
|
}
|
|
|
|
public:
|
|
using PrintBase::PrintBase;
|
|
|
|
#define TRIVIAL_TYPE_PRINTER(Class,Name) \
|
|
void visit##Class##Type(Class##Type *T, StringRef label) { \
|
|
printCommon(#Name "_type", label); printFoot(); \
|
|
}
|
|
|
|
void visitErrorType(ErrorType *T, StringRef label) {
|
|
printCommon("error_type", label);
|
|
if (auto originalType = T->getOriginalType())
|
|
printRec(originalType, "original_type");
|
|
printFoot();
|
|
}
|
|
|
|
TRIVIAL_TYPE_PRINTER(Unresolved, unresolved)
|
|
|
|
void visitPlaceholderType(PlaceholderType *T, StringRef label) {
|
|
printCommon("placeholder_type", label);
|
|
auto originator = T->getOriginator();
|
|
if (auto *typeVar = originator.dyn_cast<TypeVariableType *>()) {
|
|
printRec(typeVar, "type_variable");
|
|
} else if (auto *VD = originator.dyn_cast<VarDecl *>()) {
|
|
printFieldQuotedRaw([&](raw_ostream &OS) { VD->dumpRef(OS); }, "",
|
|
DeclColor);
|
|
} else if (auto *EE = originator.dyn_cast<ErrorExpr *>()) {
|
|
printFlag("error_expr");
|
|
} else if (auto *DMT = originator.dyn_cast<DependentMemberType *>()) {
|
|
printRec(DMT, "dependent_member_type");
|
|
} else if (originator.is<PlaceholderTypeRepr *>()) {
|
|
printFlag("placeholder_type_repr");
|
|
} else {
|
|
assert(false && "unknown originator");
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitBuiltinIntegerType(BuiltinIntegerType *T, StringRef label) {
|
|
printCommon("builtin_integer_type", label);
|
|
if (T->isFixedWidth())
|
|
printField(T->getFixedWidth(), "bit_width");
|
|
else
|
|
printFlag("word_sized");
|
|
printFoot();
|
|
}
|
|
|
|
void visitBuiltinFloatType(BuiltinFloatType *T, StringRef label) {
|
|
printCommon("builtin_float_type", label);
|
|
printField(T->getBitWidth(), "bit_width");
|
|
printFoot();
|
|
}
|
|
|
|
TRIVIAL_TYPE_PRINTER(BuiltinIntegerLiteral, builtin_integer_literal)
|
|
TRIVIAL_TYPE_PRINTER(BuiltinJob, builtin_job)
|
|
TRIVIAL_TYPE_PRINTER(BuiltinExecutor, builtin_executor_ref)
|
|
TRIVIAL_TYPE_PRINTER(BuiltinDefaultActorStorage, builtin_default_actor_storage)
|
|
TRIVIAL_TYPE_PRINTER(BuiltinNonDefaultDistributedActorStorage, builtin_non_default_distributed_actor_storage)
|
|
TRIVIAL_TYPE_PRINTER(BuiltinPackIndex, builtin_pack_index)
|
|
TRIVIAL_TYPE_PRINTER(BuiltinRawPointer, builtin_raw_pointer)
|
|
TRIVIAL_TYPE_PRINTER(BuiltinRawUnsafeContinuation, builtin_raw_unsafe_continuation)
|
|
TRIVIAL_TYPE_PRINTER(BuiltinNativeObject, builtin_native_object)
|
|
TRIVIAL_TYPE_PRINTER(BuiltinBridgeObject, builtin_bridge_object)
|
|
TRIVIAL_TYPE_PRINTER(BuiltinUnsafeValueBuffer, builtin_unsafe_value_buffer)
|
|
TRIVIAL_TYPE_PRINTER(SILToken, sil_token)
|
|
|
|
void visitBuiltinVectorType(BuiltinVectorType *T, StringRef label) {
|
|
printCommon("builtin_vector_type", label);
|
|
printField(T->getNumElements(), "num_elements");
|
|
printRec(T->getElementType());
|
|
printFoot();
|
|
}
|
|
|
|
void visitTypeAliasType(TypeAliasType *T, StringRef label) {
|
|
printCommon("type_alias_type", label);
|
|
|
|
printFieldQuoted(T->getDecl()->printRef(), "decl");
|
|
if (auto underlying = T->getSinglyDesugaredType()) {
|
|
printField(underlying, "underlying", TypeColor);
|
|
} else {
|
|
printFlag("unresolved_underlying");
|
|
}
|
|
|
|
if (T->getParent())
|
|
printRec(T->getParent(), "parent");
|
|
printRecRange(T->getDirectGenericArgs(), "direct_generic_args");
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitPackType(PackType *T, StringRef label) {
|
|
printCommon("pack_type", label);
|
|
|
|
printField(T->getNumElements(), "num_elements");
|
|
|
|
for (Type elt : T->getElementTypes()) {
|
|
printRec(elt);
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitSILPackType(SILPackType *T, StringRef label) {
|
|
printCommon("sil_pack_type", label);
|
|
|
|
printField(T->isElementAddress(), "element_is_address");
|
|
printField(T->getNumElements(), "num_elements");
|
|
|
|
for (Type elt : T->getElementTypes()) {
|
|
printRec(elt);
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitPackExpansionType(PackExpansionType *T, StringRef label) {
|
|
printCommon("pack_expansion_type", label);
|
|
printRec(T->getPatternType(), "pattern");
|
|
printRec(T->getCountType(), "count");
|
|
printFoot();
|
|
}
|
|
|
|
void visitPackElementType(PackElementType *T, StringRef label) {
|
|
printCommon("element_type", label);
|
|
|
|
printField(T->getLevel(), "level");
|
|
|
|
printRec(T->getPackType(), "pack");
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitParenType(ParenType *T, StringRef label) {
|
|
printCommon("paren_type", label);
|
|
|
|
printRec(T->getUnderlyingType());
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitTupleType(TupleType *T, StringRef label) {
|
|
printCommon("tuple_type", label);
|
|
|
|
printField(T->getNumElements(), "num_elements");
|
|
|
|
for (const auto &elt : T->getElements()) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("tuple_type_elt", FieldLabelColor, label);
|
|
if (elt.hasName())
|
|
printFieldQuoted(elt.getName().str(), "name");
|
|
printRec(elt.getType());
|
|
printFoot();
|
|
});
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
#define REF_STORAGE(Name, name, ...) \
|
|
void visit##Name##StorageType(Name##StorageType *T, StringRef label) { \
|
|
printCommon(#name "_storage_type", label); \
|
|
printRec(T->getReferentType()); \
|
|
printFoot(); \
|
|
}
|
|
#include "swift/AST/ReferenceStorage.def"
|
|
|
|
#define VISIT_NOMINAL_TYPE(TypeClass, Name) \
|
|
void visit##TypeClass(TypeClass *T, StringRef label) { \
|
|
printCommon(#Name, label); \
|
|
\
|
|
printFieldQuoted(T->getDecl()->printRef(), "decl"); \
|
|
\
|
|
if (T->getParent()) \
|
|
printRec(T->getParent(), "parent"); \
|
|
\
|
|
printFoot(); \
|
|
}
|
|
|
|
VISIT_NOMINAL_TYPE(EnumType, enum_type)
|
|
VISIT_NOMINAL_TYPE(StructType, struct_type)
|
|
VISIT_NOMINAL_TYPE(ClassType, class_type)
|
|
VISIT_NOMINAL_TYPE(ProtocolType, protocol_type)
|
|
|
|
#undef VISIT_NOMINAL_TYPE
|
|
|
|
void visitBuiltinTupleType(BuiltinTupleType *T, StringRef label) {
|
|
printCommon("builtin_tuple_type", label);
|
|
printFieldQuoted(T->getDecl()->printRef(), "decl");
|
|
printFoot();
|
|
}
|
|
|
|
void visitMetatypeType(MetatypeType *T, StringRef label) {
|
|
printCommon("metatype_type", label);
|
|
|
|
if (T->hasRepresentation())
|
|
printFlag(getDumpString(T->getRepresentation()));
|
|
|
|
printRec(T->getInstanceType());
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitExistentialMetatypeType(ExistentialMetatypeType *T,
|
|
StringRef label) {
|
|
printCommon("existential_metatype_type", label);
|
|
|
|
if (T->hasRepresentation())
|
|
printFlag(getDumpString(T->getRepresentation()));
|
|
|
|
printRec(T->getInstanceType());
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitModuleType(ModuleType *T, StringRef label) {
|
|
printCommon("module_type", label);
|
|
printDeclNameField(T->getModule(), "module");
|
|
printFoot();
|
|
}
|
|
|
|
void visitDynamicSelfType(DynamicSelfType *T, StringRef label) {
|
|
printCommon("dynamic_self_type", label);
|
|
printRec(T->getSelfType());
|
|
printFoot();
|
|
}
|
|
|
|
void printArchetypeCommon(ArchetypeType *T,
|
|
StringRef className,
|
|
StringRef label) {
|
|
printCommon(className, label);
|
|
|
|
printField(static_cast<void *>(T), "address");
|
|
printFlag(T->requiresClass(), "class");
|
|
if (auto layout = T->getLayoutConstraint()) {
|
|
printFieldRaw([&](raw_ostream &OS) {
|
|
layout->print(OS);
|
|
}, "layout");
|
|
}
|
|
for (auto proto : T->getConformsTo())
|
|
printFieldQuoted(proto->printRef(), "conforms_to");
|
|
}
|
|
|
|
void printArchetypeCommonRec(ArchetypeType *T) {
|
|
printRec(T->getInterfaceType(), "interface_type");
|
|
if (auto superclass = T->getSuperclass())
|
|
printRec(superclass, "superclass");
|
|
}
|
|
|
|
void visitPrimaryArchetypeType(PrimaryArchetypeType *T, StringRef label) {
|
|
printArchetypeCommon(T, "primary_archetype_type", label);
|
|
|
|
printFieldQuoted(T->getFullName(), "name");
|
|
|
|
printArchetypeCommonRec(T);
|
|
|
|
printFoot();
|
|
}
|
|
void visitOpenedArchetypeType(OpenedArchetypeType *T, StringRef label) {
|
|
printArchetypeCommon(T, "opened_archetype_type", label);
|
|
|
|
printFieldQuoted(T->getOpenedExistentialID(), "opened_existential_id");
|
|
|
|
printArchetypeCommonRec(T);
|
|
printRec(T->getGenericEnvironment()->getOpenedExistentialType(), "opened_existential");
|
|
|
|
printFoot();
|
|
}
|
|
void visitOpaqueTypeArchetypeType(OpaqueTypeArchetypeType *T,
|
|
StringRef label) {
|
|
printArchetypeCommon(T, "opaque_type", label);
|
|
|
|
printFieldQuoted(T->getDecl()->getNamingDecl()->printRef(), "decl");
|
|
|
|
printArchetypeCommonRec(T);
|
|
if (!T->getSubstitutions().empty()) {
|
|
printRec(T->getSubstitutions());
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
void visitPackArchetypeType(PackArchetypeType *T, StringRef label) {
|
|
printArchetypeCommon(T, "pack_archetype_type", label);
|
|
printFieldQuoted(T->getFullName(), "name");
|
|
printArchetypeCommonRec(T);
|
|
printFoot();
|
|
}
|
|
void visitElementArchetypeType(ElementArchetypeType *T, StringRef label) {
|
|
printArchetypeCommon(T, "element_archetype_type", label);
|
|
printFieldQuoted(T->getOpenedElementID(), "opened_element_id");
|
|
printFoot();
|
|
}
|
|
|
|
void visitGenericTypeParamType(GenericTypeParamType *T, StringRef label) {
|
|
printCommon("generic_type_param_type", label);
|
|
printField(T->getDepth(), "depth");
|
|
printField(T->getIndex(), "index");
|
|
if (auto decl = T->getDecl())
|
|
printFieldQuoted(decl->printRef(), "decl");
|
|
printFlag(T->isParameterPack(), "pack");
|
|
printFoot();
|
|
}
|
|
|
|
void visitDependentMemberType(DependentMemberType *T, StringRef label) {
|
|
printCommon("dependent_member_type", label);
|
|
|
|
if (auto assocType = T->getAssocType()) {
|
|
printFieldQuoted(assocType->printRef(), "assoc_type");
|
|
} else {
|
|
printFieldQuoted(T->getName(), "name");
|
|
}
|
|
|
|
printRec(T->getBase(), "base");
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void printAnyFunctionParamsRec(ArrayRef<AnyFunctionType::Param> params,
|
|
StringRef label) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printCommon("function_params", label);
|
|
|
|
printField(params.size(), "num_params");
|
|
for (const auto ¶m : params) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("param", FieldLabelColor, label);
|
|
|
|
if (param.hasLabel())
|
|
printFieldQuoted(param.getLabel().str(), "name");
|
|
if (param.hasInternalLabel())
|
|
printFieldQuoted(param.getInternalLabel().str(), "internal_name");
|
|
dumpParameterFlags(param.getParameterFlags());
|
|
|
|
printRec(param.getPlainType());
|
|
|
|
printFoot();
|
|
});
|
|
}
|
|
printFoot();
|
|
}, label);
|
|
}
|
|
|
|
void printClangTypeRec(const ClangTypeInfo &info, const ASTContext &ctx) {
|
|
// [TODO: Improve-Clang-type-printing]
|
|
if (!info.empty()) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("clang_type", ASTNodeColor, label);
|
|
printNameRaw([&](raw_ostream &OS) {
|
|
auto &clangCtx = ctx.getClangModuleLoader()->getClangASTContext();
|
|
info.dump(OS, clangCtx);
|
|
});
|
|
printFoot();
|
|
});
|
|
}
|
|
}
|
|
|
|
void printAnyFunctionTypeCommonRec(AnyFunctionType *T, StringRef label,
|
|
StringRef name) {
|
|
printCommon(name, label);
|
|
|
|
if (T->hasExtInfo()) {
|
|
SILFunctionType::Representation representation =
|
|
T->getExtInfo().getSILRepresentation();
|
|
|
|
if (representation != SILFunctionType::Representation::Thick) {
|
|
printField(representation, "representation");
|
|
}
|
|
printFlag(!T->isNoEscape(), "escaping");
|
|
printFlag(T->isSendable(), "Sendable");
|
|
printFlag(T->isAsync(), "async");
|
|
printFlag(T->isThrowing(), "throws");
|
|
}
|
|
if (Type globalActor = T->getGlobalActor()) {
|
|
printFieldQuoted(globalActor.getString(), "global_actor");
|
|
}
|
|
|
|
printClangTypeRec(T->getClangTypeInfo(), T->getASTContext());
|
|
printAnyFunctionParamsRec(T->getParams(), "input");
|
|
printRec(T->getResult(), "output");
|
|
}
|
|
|
|
void visitFunctionType(FunctionType *T, StringRef label) {
|
|
printAnyFunctionTypeCommonRec(T, label, "function_type");
|
|
printFoot();
|
|
}
|
|
|
|
void visitGenericFunctionType(GenericFunctionType *T, StringRef label) {
|
|
printAnyFunctionTypeCommonRec(T, label, "generic_function_type");
|
|
// FIXME: generic signature dumping needs improvement
|
|
printRecArbitrary([&](StringRef label) {
|
|
printHead("generic_sig", TypeColor, label);
|
|
printFieldQuoted(T->getGenericSignature()->getAsString(), "");
|
|
printFoot();
|
|
});
|
|
printFoot();
|
|
}
|
|
|
|
void visitSILFunctionType(SILFunctionType *T, StringRef label) {
|
|
printCommon("sil_function_type", label);
|
|
printFieldQuoted(T->getString(), "type");
|
|
|
|
for (auto param : T->getParameters()) {
|
|
printRec(param.getInterfaceType(), "input");
|
|
}
|
|
for (auto yield : T->getYields()) {
|
|
printRec(yield.getInterfaceType(), "yield");
|
|
}
|
|
for (auto result : T->getResults()) {
|
|
printRec(result.getInterfaceType(), "result");
|
|
}
|
|
if (auto error = T->getOptionalErrorResult()) {
|
|
printRec(error->getInterfaceType(), "error");
|
|
}
|
|
printRec(T->getPatternSubstitutions());
|
|
printRec(T->getInvocationSubstitutions());
|
|
printClangTypeRec(T->getClangTypeInfo(), T->getASTContext());
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitSILBlockStorageType(SILBlockStorageType *T, StringRef label) {
|
|
printCommon("sil_block_storage_type", label);
|
|
printRec(T->getCaptureType());
|
|
printFoot();
|
|
}
|
|
|
|
void visitSILMoveOnlyWrappedType(SILMoveOnlyWrappedType *T,
|
|
StringRef label) {
|
|
printCommon("sil_move_only_type", label);
|
|
printRec(T->getInnerType());
|
|
printFoot();
|
|
}
|
|
|
|
void visitSILBoxType(SILBoxType *T, StringRef label) {
|
|
printCommon("sil_box_type", label);
|
|
// FIXME: Print the structure of the type.
|
|
printFieldQuoted(T->getString(), "type");
|
|
printFoot();
|
|
}
|
|
|
|
void visitArraySliceType(ArraySliceType *T, StringRef label) {
|
|
printCommon("array_slice_type", label);
|
|
printRec(T->getBaseType());
|
|
printFoot();
|
|
}
|
|
|
|
void visitOptionalType(OptionalType *T, StringRef label) {
|
|
printCommon("optional_type", label);
|
|
printRec(T->getBaseType());
|
|
printFoot();
|
|
}
|
|
|
|
void visitDictionaryType(DictionaryType *T, StringRef label) {
|
|
printCommon("dictionary_type", label);
|
|
printRec(T->getKeyType(), "key");
|
|
printRec(T->getValueType(), "value");
|
|
printFoot();
|
|
}
|
|
|
|
void visitVariadicSequenceType(VariadicSequenceType *T, StringRef label) {
|
|
printCommon("variadic_sequence_type", label);
|
|
printRec(T->getBaseType());
|
|
printFoot();
|
|
}
|
|
|
|
void visitProtocolCompositionType(ProtocolCompositionType *T,
|
|
StringRef label) {
|
|
|
|
printCommon("protocol_composition_type", label);
|
|
|
|
printFlag(T->hasExplicitAnyObject(), "any_object");
|
|
|
|
for (auto proto : T->getMembers()) {
|
|
printRec(proto);
|
|
}
|
|
|
|
printFoot();
|
|
}
|
|
|
|
void visitParameterizedProtocolType(ParameterizedProtocolType *T,
|
|
StringRef label) {
|
|
printCommon("parameterized_protocol_type", label);
|
|
printRec(T->getBaseType(), "base");
|
|
for (auto arg : T->getArgs()) {
|
|
printRec(arg);
|
|
}
|
|
printFoot();
|
|
}
|
|
|
|
void visitExistentialType(ExistentialType *T,
|
|
StringRef label) {
|
|
printCommon("existential_type", label);
|
|
printRec(T->getConstraintType());
|
|
printFoot();
|
|
}
|
|
|
|
void visitLValueType(LValueType *T, StringRef label) {
|
|
printCommon("lvalue_type", label);
|
|
printRec(T->getObjectType());
|
|
printFoot();
|
|
}
|
|
|
|
void visitInOutType(InOutType *T, StringRef label) {
|
|
printCommon("inout_type", label);
|
|
printRec(T->getObjectType());
|
|
printFoot();
|
|
}
|
|
|
|
void visitUnboundGenericType(UnboundGenericType *T, StringRef label) {
|
|
printCommon("unbound_generic_type", label);
|
|
printFieldQuoted(T->getDecl()->printRef(), "decl");
|
|
if (T->getParent())
|
|
printRec(T->getParent(), "parent");
|
|
printFoot();
|
|
}
|
|
|
|
void visitBoundGenericClassType(BoundGenericClassType *T, StringRef label) {
|
|
printCommon("bound_generic_class_type", label);
|
|
printFieldQuoted(T->getDecl()->printRef(), "decl");
|
|
if (T->getParent())
|
|
printRec(T->getParent(), "parent");
|
|
for (auto arg : T->getGenericArgs())
|
|
printRec(arg);
|
|
printFoot();
|
|
}
|
|
|
|
void visitBoundGenericStructType(BoundGenericStructType *T,
|
|
StringRef label) {
|
|
printCommon("bound_generic_struct_type", label);
|
|
printFieldQuoted(T->getDecl()->printRef(), "decl");
|
|
if (T->getParent())
|
|
printRec(T->getParent(), "parent");
|
|
for (auto arg : T->getGenericArgs())
|
|
printRec(arg);
|
|
printFoot();
|
|
}
|
|
|
|
void visitBoundGenericEnumType(BoundGenericEnumType *T, StringRef label) {
|
|
printCommon("bound_generic_enum_type", label);
|
|
printFieldQuoted(T->getDecl()->printRef(), "decl");
|
|
if (T->getParent())
|
|
printRec(T->getParent(), "parent");
|
|
for (auto arg : T->getGenericArgs())
|
|
printRec(arg);
|
|
printFoot();
|
|
}
|
|
|
|
void visitTypeVariableType(TypeVariableType *T, StringRef label) {
|
|
printCommon("type_variable_type", label);
|
|
printField(T->getID(), "id");
|
|
printFoot();
|
|
}
|
|
|
|
#undef TRIVIAL_TYPE_PRINTER
|
|
};
|
|
|
|
void PrintBase::printRec(Type type, StringRef label) {
|
|
printRecArbitrary([&](StringRef label) {
|
|
if (type.isNull()) {
|
|
printHead("<null type>", DeclColor, label);
|
|
printFoot();
|
|
} else {
|
|
PrintType(OS, Indent, GetTypeOfExpr, GetTypeOfTypeRepr,
|
|
GetTypeOfKeyPathComponent).visit(type, label);
|
|
}
|
|
}, label);
|
|
}
|
|
} // end anonymous namespace
|
|
|
|
void Type::dump() const {
|
|
dump(llvm::errs());
|
|
}
|
|
|
|
void Type::dump(raw_ostream &os, unsigned indent) const {
|
|
PrintType(os, indent).visit(*this, "");
|
|
os << "\n";
|
|
}
|
|
|
|
void TypeBase::dump() const {
|
|
// Make sure to print type variables.
|
|
Type(const_cast<TypeBase *>(this)).dump();
|
|
}
|
|
|
|
void TypeBase::dump(raw_ostream &os, unsigned indent) const {
|
|
Type(const_cast<TypeBase *>(this)).dump(os, indent);
|
|
}
|
|
|
|
void GenericSignatureImpl::dump() const {
|
|
GenericSignature(const_cast<GenericSignatureImpl *>(this)).dump();
|
|
}
|
|
|
|
void GenericEnvironment::dump(raw_ostream &os) const {
|
|
os << "Generic environment:\n";
|
|
for (auto gp : getGenericParams()) {
|
|
gp->dump(os);
|
|
mapTypeIntoContext(gp)->dump(os);
|
|
}
|
|
os << "Generic parameters:\n";
|
|
for (auto paramTy : getGenericParams())
|
|
paramTy->dump(os);
|
|
}
|
|
|
|
void GenericEnvironment::dump() const {
|
|
dump(llvm::errs());
|
|
}
|
|
|
|
StringRef swift::getAccessorKindString(AccessorKind value) {
|
|
switch (value) {
|
|
#define ACCESSOR(ID)
|
|
#define SINGLETON_ACCESSOR(ID, KEYWORD) \
|
|
case AccessorKind::ID: return #KEYWORD;
|
|
#include "swift/AST/AccessorKinds.def"
|
|
}
|
|
|
|
llvm_unreachable("Unhandled AccessorKind in switch.");
|
|
}
|
|
|
|
void StableSerializationPath::dump() const {
|
|
dump(llvm::errs());
|
|
}
|
|
|
|
static StringRef getExternalPathComponentKindString(
|
|
StableSerializationPath::ExternalPath::ComponentKind kind) {
|
|
switch (kind) {
|
|
#define CASE(ID, STRING) \
|
|
case StableSerializationPath::ExternalPath::ID: return STRING;
|
|
CASE(Record, "record")
|
|
CASE(Enum, "enum")
|
|
CASE(Namespace, "namespace")
|
|
CASE(Typedef, "typedef")
|
|
CASE(TypedefAnonDecl, "anonymous tag")
|
|
CASE(ObjCInterface, "@interface")
|
|
CASE(ObjCProtocol, "@protocol")
|
|
#undef CASE
|
|
}
|
|
llvm_unreachable("bad kind");
|
|
}
|
|
|
|
void StableSerializationPath::dump(llvm::raw_ostream &os) const {
|
|
if (isSwiftDecl()) {
|
|
os << "clang decl of:\n";
|
|
getSwiftDecl()->dump(os, 2);
|
|
} else {
|
|
auto &path = getExternalPath();
|
|
using ExternalPath = StableSerializationPath::ExternalPath;
|
|
os << "external path: ";
|
|
size_t index = 0;
|
|
for (auto &entry : path.Path) {
|
|
if (index++) os << " -> ";
|
|
os << getExternalPathComponentKindString(entry.first);
|
|
if (ExternalPath::requiresIdentifier(entry.first)) {
|
|
os << "(" << entry.second << ")";
|
|
}
|
|
}
|
|
os << "\n";
|
|
}
|
|
}
|
|
|
|
void RequirementRepr::dump() const {
|
|
print(llvm::errs());
|
|
llvm::errs() << "\n";
|
|
}
|
|
|
|
void GenericParamList::dump() const {
|
|
print(llvm::errs());
|
|
llvm::errs() << '\n';
|
|
}
|
|
|
|
void LayoutConstraint::dump() const {
|
|
if (!*this) {
|
|
llvm::errs() << "(null)\n";
|
|
return;
|
|
}
|
|
getPointer()->print(llvm::errs());
|
|
}
|
|
|
|
void GenericSignature::dump() const {
|
|
print(llvm::errs());
|
|
llvm::errs() << '\n';
|
|
}
|
|
|
|
void Requirement::dump() const {
|
|
dump(llvm::errs());
|
|
llvm::errs() << '\n';
|
|
}
|
|
void Requirement::dump(raw_ostream &out) const {
|
|
PrintBase(out, 0).visitRequirement(*this);
|
|
}
|
|
|
|
void SILParameterInfo::dump() const {
|
|
print(llvm::errs());
|
|
llvm::errs() << '\n';
|
|
}
|
|
|
|
void SILResultInfo::dump() const {
|
|
print(llvm::errs());
|
|
llvm::errs() << '\n';
|
|
}
|