[clang] c655d80 - [SyntaxTree] Extend the syntax tree dump to also cover `NodeRole`
Eduardo Caldas via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 24 23:39:23 PDT 2020
Author: Eduardo Caldas
Date: 2020-08-25T06:34:40Z
New Revision: c655d8081570336dda109502ed1e7a2eff1b26e2
URL: https://github.com/llvm/llvm-project/commit/c655d8081570336dda109502ed1e7a2eff1b26e2
DIFF: https://github.com/llvm/llvm-project/commit/c655d8081570336dda109502ed1e7a2eff1b26e2.diff
LOG: [SyntaxTree] Extend the syntax tree dump to also cover `NodeRole`
We should see `NodeRole` information in the dump because that exposes how the
accessors will behave.
Functional changes in the dump:
* Surround Leaf tokens with `'`
* Append `Node` dumps with `NodeRole` information, except for unknown roles
* Append marks to `Node` dumps, instead of prepending
Non-functional changes:
* `::dumpTokens(llvm::raw_ostream, ArrayRef<syntax::Token>, const
SourceManager &SM)` always received as parameter a `syntax::Token *`
pointing to `Leaf::token()`. Changed the function to
`dumpLeaf(llvm::raw_ostream, syntax::Leaf *, const SourceManager&)`
* `dumpTree` acted on a Node, rename to `dumpNode`
Differential Revision: https://reviews.llvm.org/D85330
Added:
Modified:
clang/include/clang/Tooling/Syntax/Tree.h
clang/lib/Tooling/Syntax/BuildTree.cpp
clang/lib/Tooling/Syntax/Tree.cpp
clang/unittests/Tooling/Syntax/TreeTestBase.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Tooling/Syntax/Tree.h b/clang/include/clang/Tooling/Syntax/Tree.h
index fcd169cad3ec..f7f9e6bdc5a0 100644
--- a/clang/include/clang/Tooling/Syntax/Tree.h
+++ b/clang/include/clang/Tooling/Syntax/Tree.h
@@ -106,9 +106,9 @@ class Node {
Node *nextSibling() { return NextSibling; }
/// Dumps the structure of a subtree. For debugging and testing purposes.
- std::string dump(const Arena &A) const;
+ std::string dump(const SourceManager &SM) const;
/// Dumps the tokens forming this subtree.
- std::string dumpTokens(const Arena &A) const;
+ std::string dumpTokens(const SourceManager &SM) const;
/// Asserts invariants on this node of the tree and its immediate children.
/// Will not recurse into the subtree. No-op if NDEBUG is set.
diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp
index 3ab52ce5b7b4..f027a60030b7 100644
--- a/clang/lib/Tooling/Syntax/BuildTree.cpp
+++ b/clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -546,7 +546,7 @@ class syntax::TreeBuilder {
R += std::string(
formatv("- '{0}' covers '{1}'+{2} tokens\n", It->second->kind(),
It->first->text(A.sourceManager()), CoveredTokens));
- R += It->second->dump(A);
+ R += It->second->dump(A.sourceManager());
}
return R;
}
diff --git a/clang/lib/Tooling/Syntax/Tree.cpp b/clang/lib/Tooling/Syntax/Tree.cpp
index 70e3c8e02783..7dbceedfb48f 100644
--- a/clang/lib/Tooling/Syntax/Tree.cpp
+++ b/clang/lib/Tooling/Syntax/Tree.cpp
@@ -133,46 +133,45 @@ void syntax::Tree::replaceChildRangeLowLevel(Node *BeforeBegin, Node *End,
}
namespace {
-static void dumpTokens(raw_ostream &OS, ArrayRef<syntax::Token> Tokens,
- const SourceManager &SM) {
- assert(!Tokens.empty());
- bool First = true;
- for (const auto &T : Tokens) {
- if (!First)
- OS << " ";
- else
- First = false;
- // Handle 'eof' separately, calling text() on it produces an empty string.
- if (T.kind() == tok::eof) {
- OS << "<eof>";
- continue;
- }
- OS << T.text(SM);
- }
+static void dumpLeaf(raw_ostream &OS, const syntax::Leaf *L,
+ const SourceManager &SM) {
+ assert(L);
+ const auto *Token = L->token();
+ assert(Token);
+ // Handle 'eof' separately, calling text() on it produces an empty string.
+ if (Token->kind() == tok::eof)
+ OS << "<eof>";
+ else
+ OS << Token->text(SM);
}
-static void dumpTree(raw_ostream &OS, const syntax::Node *N,
- const syntax::Arena &A, std::vector<bool> IndentMask) {
- std::string Marks;
- if (!N->isOriginal())
- Marks += "M";
- if (N->role() == syntax::NodeRole::Detached)
- Marks += "*"; // FIXME: find a nice way to print other roles.
- if (!N->canModify())
- Marks += "I";
- if (!Marks.empty())
- OS << Marks << ": ";
-
- if (auto *L = dyn_cast<syntax::Leaf>(N)) {
- dumpTokens(OS, *L->token(), A.sourceManager());
+static void dumpNode(raw_ostream &OS, const syntax::Node *N,
+ const SourceManager &SM, std::vector<bool> IndentMask) {
+ auto dumpExtraInfo = [&OS](const syntax::Node *N) {
+ if (N->role() != syntax::NodeRole::Unknown)
+ OS << " " << N->role();
+ if (!N->isOriginal())
+ OS << " synthesized";
+ if (!N->canModify())
+ OS << " unmodifiable";
+ };
+
+ assert(N);
+ if (const auto *L = dyn_cast<syntax::Leaf>(N)) {
+ OS << "'";
+ dumpLeaf(OS, L, SM);
+ OS << "'";
+ dumpExtraInfo(N);
OS << "\n";
return;
}
- auto *T = cast<syntax::Tree>(N);
- OS << T->kind() << "\n";
+ const auto *T = cast<syntax::Tree>(N);
+ OS << T->kind();
+ dumpExtraInfo(N);
+ OS << "\n";
- for (auto It = T->firstChild(); It != nullptr; It = It->nextSibling()) {
+ for (const auto *It = T->firstChild(); It; It = It->nextSibling()) {
for (bool Filled : IndentMask) {
if (Filled)
OS << "| ";
@@ -186,28 +185,27 @@ static void dumpTree(raw_ostream &OS, const syntax::Node *N,
OS << "|-";
IndentMask.push_back(true);
}
- dumpTree(OS, It, A, IndentMask);
+ dumpNode(OS, It, SM, IndentMask);
IndentMask.pop_back();
}
}
} // namespace
-std::string syntax::Node::dump(const Arena &A) const {
+std::string syntax::Node::dump(const SourceManager &SM) const {
std::string Str;
llvm::raw_string_ostream OS(Str);
- dumpTree(OS, this, A, /*IndentMask=*/{});
+ dumpNode(OS, this, SM, /*IndentMask=*/{});
return std::move(OS.str());
}
-std::string syntax::Node::dumpTokens(const Arena &A) const {
+std::string syntax::Node::dumpTokens(const SourceManager &SM) const {
std::string Storage;
llvm::raw_string_ostream OS(Storage);
traverse(this, [&](const syntax::Node *N) {
- auto *L = dyn_cast<syntax::Leaf>(N);
- if (!L)
- return;
- ::dumpTokens(OS, *L->token(), A.sourceManager());
- OS << " ";
+ if (const auto *L = dyn_cast<syntax::Leaf>(N)) {
+ dumpLeaf(OS, L, SM);
+ OS << " ";
+ }
});
return OS.str();
}
diff --git a/clang/unittests/Tooling/Syntax/TreeTestBase.cpp b/clang/unittests/Tooling/Syntax/TreeTestBase.cpp
index c5dbb770c538..ebee0115cb72 100644
--- a/clang/unittests/Tooling/Syntax/TreeTestBase.cpp
+++ b/clang/unittests/Tooling/Syntax/TreeTestBase.cpp
@@ -171,7 +171,7 @@ ::testing::AssertionResult SyntaxTreeTest::treeDumpEqual(StringRef Code,
<< "Source file has syntax errors, they were printed to the test "
"log";
}
- auto Actual = StringRef(Root->dump(*Arena)).trim().str();
+ auto Actual = StringRef(Root->dump(Arena->sourceManager())).trim().str();
// EXPECT_EQ shows the
diff between the two strings if they are
diff erent.
EXPECT_EQ(Tree.trim().str(), Actual);
if (Actual != Tree.trim().str()) {
@@ -205,7 +205,7 @@ SyntaxTreeTest::treeDumpEqualOnAnnotations(StringRef CodeWithAnnotations,
auto *AnnotatedNode = nodeByRange(AnnotatedRanges[i], Root);
assert(AnnotatedNode);
auto AnnotatedNodeDump =
- StringRef(AnnotatedNode->dump(*Arena)).trim().str();
+ StringRef(AnnotatedNode->dump(Arena->sourceManager())).trim().str();
// EXPECT_EQ shows the
diff between the two strings if they are
diff erent.
EXPECT_EQ(TreeDumps[i].trim().str(), AnnotatedNodeDump)
<< "Dumps diverged for the code:\n"
More information about the cfe-commits
mailing list