mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Introduce a convenience for aborting while printing a given message to a frame of the pretty stack trace. Use this in the existing places where we're currently doing this.
226 lines
7.0 KiB
C++
226 lines
7.0 KiB
C++
//===--- ASTScopePrinting.cpp - Swift Object-Oriented AST Scope -----------===//
|
|
//
|
|
// 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 the printing functions of the ASTScopeImpl ontology.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
#include "swift/AST/ASTScope.h"
|
|
|
|
#include "swift/AST/ASTContext.h"
|
|
#include "swift/AST/ASTWalker.h"
|
|
#include "swift/AST/Decl.h"
|
|
#include "swift/AST/Expr.h"
|
|
#include "swift/AST/GenericParamList.h"
|
|
#include "swift/AST/Initializer.h"
|
|
#include "swift/AST/LazyResolver.h"
|
|
#include "swift/AST/Module.h"
|
|
#include "swift/AST/ParameterList.h"
|
|
#include "swift/AST/Pattern.h"
|
|
#include "swift/AST/SourceFile.h"
|
|
#include "swift/AST/Stmt.h"
|
|
#include "swift/AST/TypeRepr.h"
|
|
#include "swift/Basic/Assertions.h"
|
|
#include "swift/Basic/PrettyStackTrace.h"
|
|
#include "swift/Basic/STLExtras.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
#include <algorithm>
|
|
|
|
using namespace swift;
|
|
using namespace ast_scope;
|
|
|
|
#pragma mark dumping
|
|
|
|
void ASTScopeImpl::dump() const { print(llvm::errs(), 0, false); }
|
|
|
|
void ASTScopeImpl::dumpParents() const { printParents(llvm::errs()); }
|
|
|
|
void ASTScopeImpl::dumpOneScopeMapLocation(
|
|
std::pair<unsigned, unsigned> lineColumn) {
|
|
auto bufferID = getSourceFile()->getBufferID();
|
|
SourceLoc loc = getSourceManager().getLocForLineCol(
|
|
bufferID, lineColumn.first, lineColumn.second);
|
|
if (loc.isInvalid())
|
|
return;
|
|
|
|
llvm::errs() << "***Scope at " << lineColumn.first << ":" << lineColumn.second
|
|
<< "***\n";
|
|
auto *parentModule = getSourceFile()->getParentModule();
|
|
auto *locScope = findInnermostEnclosingScope(parentModule, loc, &llvm::errs());
|
|
locScope->print(llvm::errs(), 0, false, false);
|
|
|
|
namelookup::ASTScopeDeclGatherer gatherer;
|
|
// Print the local bindings introduced by this scope.
|
|
locScope->lookupLocalsOrMembers(gatherer);
|
|
if (!gatherer.getDecls().empty()) {
|
|
llvm::errs() << "Local bindings: ";
|
|
llvm::interleave(
|
|
gatherer.getDecls().begin(), gatherer.getDecls().end(),
|
|
[&](ValueDecl *value) { llvm::errs() << value->getName(); },
|
|
[&]() { llvm::errs() << " "; });
|
|
llvm::errs() << "\n";
|
|
}
|
|
}
|
|
|
|
void ASTScopeImpl::abortWithVerificationError(
|
|
llvm::function_ref<void(llvm::raw_ostream &)> messageFn) const {
|
|
abortWithPrettyStackTraceMessage([&](auto &out) {
|
|
out << "ASTScopeImpl verification error in source file '"
|
|
<< getSourceFile()->getFilename() << "':\n";
|
|
messageFn(out);
|
|
});
|
|
}
|
|
|
|
#pragma mark printing
|
|
|
|
void ASTScopeImpl::print(llvm::raw_ostream &out, unsigned level, bool lastChild,
|
|
bool printChildren) const {
|
|
// Indent for levels 2+.
|
|
if (level > 1)
|
|
out.indent((level - 1) * 2);
|
|
|
|
// Print child marker and leading '-' for levels 1+.
|
|
if (level > 0)
|
|
out << (lastChild ? '`' : '|') << '-';
|
|
|
|
out << getClassName();
|
|
if (auto *a = addressForPrinting().getPtrOrNull())
|
|
out << " " << a;
|
|
out << ", ";
|
|
if (auto *d = getDeclIfAny().getPtrOrNull()) {
|
|
if (d->isImplicit())
|
|
out << "implicit ";
|
|
}
|
|
printRange(out);
|
|
out << " ";
|
|
printSpecifics(out);
|
|
out << "\n";
|
|
|
|
if (printChildren) {
|
|
for (unsigned i : indices(getChildren())) {
|
|
getChildren()[i]->print(out, level + 1,
|
|
/*lastChild=*/i == getChildren().size() - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void printSourceRange(llvm::raw_ostream &out, const SourceRange range,
|
|
SourceManager &SM) {
|
|
if (range.isInvalid()) {
|
|
out << "[invalid source range]";
|
|
return;
|
|
}
|
|
|
|
auto startLineAndCol = SM.getPresumedLineAndColumnForLoc(range.Start);
|
|
auto endLineAndCol = SM.getPresumedLineAndColumnForLoc(range.End);
|
|
|
|
out << "[" << startLineAndCol.first << ":" << startLineAndCol.second << " - "
|
|
<< endLineAndCol.first << ":" << endLineAndCol.second << "]";
|
|
}
|
|
|
|
void ASTScopeImpl::printRange(llvm::raw_ostream &out) const {
|
|
SourceRange range = getSourceRangeOfThisASTNode(/*omitAssertions=*/true);
|
|
printSourceRange(out, range, getSourceManager());
|
|
}
|
|
|
|
void ASTScopeImpl::printParents(llvm::raw_ostream &out) const {
|
|
SmallVector<const ASTScopeImpl *, 8> nodes;
|
|
const ASTScopeImpl *cursor = this;
|
|
do {
|
|
nodes.push_back(cursor);
|
|
cursor = cursor->getParent().getPtrOrNull();
|
|
} while (cursor);
|
|
|
|
std::reverse(nodes.begin(), nodes.end());
|
|
|
|
for (auto i : indices(nodes)) {
|
|
nodes[i]->print(out, i, /*lastChild=*/true, /*printChildren=*/false);
|
|
}
|
|
}
|
|
|
|
#pragma mark printSpecifics
|
|
|
|
|
|
void ASTSourceFileScope::printSpecifics(
|
|
llvm::raw_ostream &out) const {
|
|
out << "'" << SF->getFilename() << "'";
|
|
}
|
|
|
|
NullablePtr<const void> ASTScopeImpl::addressForPrinting() const {
|
|
if (auto *p = getDeclIfAny().getPtrOrNull())
|
|
return p;
|
|
if (auto *p = getStmtIfAny().getPtrOrNull())
|
|
return p;
|
|
if (auto *p = getExprIfAny().getPtrOrNull())
|
|
return p;
|
|
return nullptr;
|
|
}
|
|
|
|
void GenericTypeOrExtensionScope::printSpecifics(llvm::raw_ostream &out) const {
|
|
if (shouldHaveABody() && !doesDeclHaveABody())
|
|
out << "<no body>";
|
|
else if (auto *n = getCorrespondingNominalTypeDecl().getPtrOrNull())
|
|
out << "'" << n->getName() << "'";
|
|
else
|
|
out << "<no extended nominal?!>";
|
|
}
|
|
|
|
void GenericParamScope::printSpecifics(llvm::raw_ostream &out) const {
|
|
out << "param " << index;
|
|
auto *genericTypeParamDecl = paramList->getParams()[index];
|
|
out << " '";
|
|
genericTypeParamDecl->print(out);
|
|
out << "'";
|
|
}
|
|
|
|
void AbstractFunctionDeclScope::printSpecifics(llvm::raw_ostream &out) const {
|
|
out << "'" << decl->getName() << "'";
|
|
}
|
|
|
|
void AbstractPatternEntryScope::printSpecifics(llvm::raw_ostream &out) const {
|
|
out << "entry " << patternEntryIndex;
|
|
getPattern()->forEachVariable([&](VarDecl *vd) {
|
|
out << " '" << vd->getName() << "'";
|
|
});
|
|
}
|
|
|
|
void SubscriptDeclScope::printSpecifics(llvm::raw_ostream &out) const {
|
|
decl->dumpRef(out);
|
|
}
|
|
|
|
void MacroDeclScope::printSpecifics(llvm::raw_ostream &out) const {
|
|
decl->dumpRef(out);
|
|
}
|
|
|
|
void MacroExpansionDeclScope::printSpecifics(llvm::raw_ostream &out) const {
|
|
out << decl->getMacroName();
|
|
}
|
|
|
|
void ConditionalClausePatternUseScope::printSpecifics(
|
|
llvm::raw_ostream &out) const {
|
|
sec.getPattern()->print(out);
|
|
}
|
|
|
|
bool GenericTypeOrExtensionScope::doesDeclHaveABody() const { return false; }
|
|
|
|
bool IterableTypeScope::doesDeclHaveABody() const {
|
|
return getBraces().Start != getBraces().End;
|
|
}
|
|
|
|
void ast_scope::simple_display(llvm::raw_ostream &out,
|
|
const ASTScopeImpl *scope) {
|
|
// Cannot call scope->print(out) because printing an ASTFunctionBodyScope
|
|
// gets the source range which can cause a request to parse it.
|
|
// That in turn causes the request dependency printing code to blow up
|
|
// as the AnyRequest ends up with a null.
|
|
out << scope->getClassName() << "\n";
|
|
}
|