Files
swift-mirror/lib/AST/PrettyStackTrace.cpp
2013-08-10 01:32:42 +00:00

194 lines
5.4 KiB
C++

//===--- PrettyStackTrace.cpp - Swift-specific PrettyStackTraceEntries ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements several Swift-specific implementations of
// PrettyStackTraceEntry.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/AST.h"
#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/TypeVisitor.h"
#include "swift/Basic/Optional.h"
#include "swift/Basic/SourceManager.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/MemoryBuffer.h"
using namespace swift;
static void printDecomposedLoc(llvm::raw_ostream &out,
const DecomposedLoc &loc) {
out << loc.Buffer->getBufferIdentifier()
<< ":" << loc.Line << ':' << loc.Column;
}
void swift::printSourceLoc(llvm::raw_ostream &OS, SourceLoc Loc,
ASTContext &Context) {
if (Loc.isInvalid()) {
OS << "<<invalid location>>";
return;
}
return printDecomposedLoc(OS, Context.SourceMgr.decompose(Loc));
}
static void printSourceRange(llvm::raw_ostream &OS, SourceRange SR,
ASTContext &Context) {
if (SR.isInvalid()) {
OS << "<<invalid source range>>";
return;
}
DecomposedLoc Start = Context.SourceMgr.decompose(SR.Start);
DecomposedLoc End = Context.SourceMgr.decompose(SR.End);
// Print the start location as normal.
printDecomposedLoc(OS, Start);
OS << '-';
// Only print the non-matching information from the second location.
if (Start.Buffer != End.Buffer) {
printDecomposedLoc(OS, End);
return;
}
if (Start.Line != End.Line) {
OS << End.Line << ':';
}
OS << End.Column;
}
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, Decl *D,
ASTContext &Context) {
if (ValueDecl *named = dyn_cast<ValueDecl>(D)) {
if (named->getName().get())
out << '\'' << named->getName() << '\'';
else
out << "'anonname=" << (const void*)named << '\'';
} else {
out << "declaration";
}
out << " at ";
printSourceLoc(out, D->getStartLoc(), Context);
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) {
if (isa<FuncExpr>(E)) {
out << "function";
} else {
out << "expression";
}
out << " at ";
printSourceRange(out, E->getSourceRange(), Context);
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 ";
printSourceRange(out, S->getSourceRange(), Context);
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 ";
printSourceRange(out, P->getSourceRange(), Context);
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();
}
};
}
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)) {
out << " (declared at ";
printSourceRange(out, decl->getSourceRange(), Context);
out << ')';
}
out << '\n';
}
void PrettyStackTraceLocation::print(llvm::raw_ostream &out) const {
out << "While " << Action << " starting at ";
printSourceLoc(out, Loc, Context);
out << '\n';
}