blob: 40e07b0ce3ef284d7746020a55424bbc29c06b5b [file] [log] [blame]
//===--- PrettyStackTrace.cpp - Swift-specific PrettyStackTraceEntries ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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 several Swift-specific implementations of
// PrettyStackTraceEntry.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/Module.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/Stmt.h"
#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/TypeVisitor.h"
#include "swift/Basic/SourceManager.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/MemoryBuffer.h"
using namespace swift;
void PrettyStackTraceDecl::print(llvm::raw_ostream &out) const {
out << "While " << Action << ' ';
if (!TheDecl) {
out << "NULL declaration!\n";
return;
}
printDeclDescription(out, TheDecl, TheDecl->getASTContext());
}
void swift::printDeclDescription(llvm::raw_ostream &out, const Decl *D,
ASTContext &Context) {
SourceLoc loc = D->getStartLoc();
bool hasPrintedName = false;
if (auto *named = dyn_cast<ValueDecl>(D)) {
if (named->hasName()) {
out << '\'' << named->getFullName() << '\'';
hasPrintedName = true;
} else if (auto *accessor = dyn_cast<AccessorDecl>(named)) {
auto ASD = accessor->getStorage();
if (ASD->hasName()) {
switch (accessor->getAccessorKind()) {
case AccessorKind::IsGetter:
out << "getter";
break;
case AccessorKind::IsSetter:
out << "setter";
break;
case AccessorKind::IsWillSet:
out << "willset";
break;
case AccessorKind::IsDidSet:
out << "didset";
break;
case AccessorKind::IsMaterializeForSet:
out << "materializeForSet";
break;
case AccessorKind::IsAddressor:
out << "addressor";
break;
case AccessorKind::IsMutableAddressor:
out << "mutableAddressor";
break;
}
out << " for " << ASD->getFullName();
hasPrintedName = true;
loc = ASD->getStartLoc();
}
}
} else if (auto *extension = dyn_cast<ExtensionDecl>(D)) {
Type extendedTy = extension->getExtendedType();
if (extendedTy) {
out << "extension of " << extendedTy;
hasPrintedName = true;
}
}
if (!hasPrintedName)
out << "declaration " << (const void *)D;
if (loc.isValid()) {
out << " at ";
loc.print(out, Context.SourceMgr);
} else {
out << " in module '" << D->getModuleContext()->getName() << '\'';
}
out << '\n';
}
void PrettyStackTraceExpr::print(llvm::raw_ostream &out) const {
out << "While " << Action << ' ';
if (!TheExpr) {
out << "NULL expression!\n";
return;
}
printExprDescription(out, TheExpr, Context);
}
void swift::printExprDescription(llvm::raw_ostream &out, Expr *E,
ASTContext &Context) {
out << "expression at ";
E->getSourceRange().print(out, Context.SourceMgr);
out << '\n';
}
void PrettyStackTraceStmt::print(llvm::raw_ostream &out) const {
out << "While " << Action << ' ';
if (!TheStmt) {
out << "NULL statement!\n";
return;
}
printStmtDescription(out, TheStmt, Context);
}
void swift::printStmtDescription(llvm::raw_ostream &out, Stmt *S,
ASTContext &Context) {
out << "statement at ";
S->getSourceRange().print(out, Context.SourceMgr);
out << '\n';
}
void PrettyStackTracePattern::print(llvm::raw_ostream &out) const {
out << "While " << Action << ' ';
if (!ThePattern) {
out << "NULL pattern!\n";
return;
}
printPatternDescription(out, ThePattern, Context);
}
void swift::printPatternDescription(llvm::raw_ostream &out, Pattern *P,
ASTContext &Context) {
out << "pattern at ";
P->getSourceRange().print(out, Context.SourceMgr);
out << '\n';
}
namespace {
/// Map a Type to an interesting declaration whose source range we
/// should print.
struct InterestingDeclForType
: TypeVisitor<InterestingDeclForType, Decl*> {
Decl *visitType(TypeBase *type) {
return nullptr;
}
Decl *visitUnboundGenericType(UnboundGenericType *type) {
return type->getDecl();
}
Decl *visitBoundGenericType(BoundGenericType *type) {
return type->getDecl();
}
Decl *visitNominalType(NominalType *type) {
return type->getDecl();
}
Decl *visitNameAliasType(NameAliasType *type) {
return type->getDecl();
}
};
} // end anonymous namespace
void PrettyStackTraceType::print(llvm::raw_ostream &out) const {
out << "While " << Action << ' ';
if (TheType.isNull()) {
out << "NULL type!\n";
return;
}
printTypeDescription(out, TheType, Context);
}
void swift::printTypeDescription(llvm::raw_ostream &out, Type type,
ASTContext &Context) {
out << "type '" << type << '\'';
if (Decl *decl = InterestingDeclForType().visit(type)) {
if (decl->getSourceRange().isValid()) {
out << " (declared at ";
decl->getSourceRange().print(out, Context.SourceMgr);
out << ')';
}
}
out << '\n';
}
void PrettyStackTraceTypeRepr::print(llvm::raw_ostream &out) const {
out << "While " << Action << " type ";
TheType->print(out);
if (TheType && TheType->getSourceRange().isValid()) {
out << " at ";
TheType->getSourceRange().print(out, Context.SourceMgr);
}
out << '\n';
}
void swift::printSourceLocDescription(llvm::raw_ostream &out,
SourceLoc loc, ASTContext &ctx) {
loc.print(out, ctx.SourceMgr);
out << '\n';
}
void PrettyStackTraceLocation::print(llvm::raw_ostream &out) const {
out << "While " << Action << " starting at ";
printSourceLocDescription(out, Loc, Context);
}
void PrettyStackTraceGenericSignature::print(llvm::raw_ostream &out) const {
out << "While " << Action << " generic signature ";
GenericSig->print(out);
if (Requirement) {
out << " in requirement #" << *Requirement;
}
out << '\n';
}