aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests/Tooling/Syntax/TreeTest.cpp
diff options
context:
space:
mode:
authorSam McCall <sam.mccall@gmail.com>2020-10-23 12:23:29 +0200
committerSam McCall <sam.mccall@gmail.com>2020-10-28 12:37:57 +0100
commitd4934eb5f876cdc97a9a8665bd654351fbbcb66b (patch)
tree5450cdc3a2ef9b1a18059e43e18ac6d679d52b0b /clang/unittests/Tooling/Syntax/TreeTest.cpp
parentedfb2f8b235ff72f00375ae2424f7eb98da08234 (diff)
downloadllvm-d4934eb5f876cdc97a9a8665bd654351fbbcb66b.zip
llvm-d4934eb5f876cdc97a9a8665bd654351fbbcb66b.tar.gz
llvm-d4934eb5f876cdc97a9a8665bd654351fbbcb66b.tar.bz2
[Syntax] Add iterators over children of syntax trees.
This gives us slightly nicer syntax (foreach) for idioms currently expressed as a loop, and the option to use range algorithms where it makes sense (e.g. llvm::all_of et al encapsulate the needed flow control in a useful way). It's also a building block for iteration over filtered views (e.g. iterate over all Stmt children, with the right type): for (const Statement &S : filter<Statement>(N.children())) ... I realize the recent direction has been mostly towards strongly-typed node-specific facilities, but I think it's important we have convenient generic facilities too. Differential Revision: https://reviews.llvm.org/D90023
Diffstat (limited to 'clang/unittests/Tooling/Syntax/TreeTest.cpp')
-rw-r--r--clang/unittests/Tooling/Syntax/TreeTest.cpp52
1 files changed, 52 insertions, 0 deletions
diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp
index fba3164..ed839e2 100644
--- a/clang/unittests/Tooling/Syntax/TreeTest.cpp
+++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp
@@ -8,6 +8,7 @@
#include "clang/Tooling/Syntax/Tree.h"
#include "TreeTestBase.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Tooling/Syntax/BuildTree.h"
#include "clang/Tooling/Syntax/Nodes.h"
#include "llvm/ADT/STLExtras.h"
@@ -17,6 +18,7 @@ using namespace clang;
using namespace clang::syntax;
namespace {
+using testing::ElementsAre;
class TreeTest : public SyntaxTreeTest {
private:
@@ -124,6 +126,56 @@ TEST_P(TreeTest, LastLeaf) {
}
}
+TEST_F(TreeTest, Iterators) {
+ buildTree("", allTestClangConfigs().front());
+ std::vector<Node *> Children = {createLeaf(*Arena, tok::identifier, "a"),
+ createLeaf(*Arena, tok::identifier, "b"),
+ createLeaf(*Arena, tok::identifier, "c")};
+ auto *Tree = syntax::createTree(*Arena,
+ {{Children[0], NodeRole::LeftHandSide},
+ {Children[1], NodeRole::OperatorToken},
+ {Children[2], NodeRole::RightHandSide}},
+ NodeKind::TranslationUnit);
+ const auto *ConstTree = Tree;
+
+ auto Range = Tree->getChildren();
+ EXPECT_THAT(Range, ElementsAre(role(NodeRole::LeftHandSide),
+ role(NodeRole::OperatorToken),
+ role(NodeRole::RightHandSide)));
+
+ auto ConstRange = ConstTree->getChildren();
+ EXPECT_THAT(ConstRange, ElementsAre(role(NodeRole::LeftHandSide),
+ role(NodeRole::OperatorToken),
+ role(NodeRole::RightHandSide)));
+
+ // FIXME: mutate and observe no invalidation. Mutations are private for now...
+ auto It = Range.begin();
+ auto CIt = ConstRange.begin();
+ static_assert(std::is_same<decltype(*It), syntax::Node &>::value,
+ "mutable range");
+ static_assert(std::is_same<decltype(*CIt), const syntax::Node &>::value,
+ "const range");
+
+ for (unsigned I = 0; I < 3; ++I) {
+ EXPECT_EQ(It, CIt);
+ EXPECT_TRUE(It);
+ EXPECT_TRUE(CIt);
+ EXPECT_EQ(It.asPointer(), Children[I]);
+ EXPECT_EQ(CIt.asPointer(), Children[I]);
+ EXPECT_EQ(&*It, Children[I]);
+ EXPECT_EQ(&*CIt, Children[I]);
+ ++It;
+ ++CIt;
+ }
+ EXPECT_EQ(It, CIt);
+ EXPECT_EQ(It, Tree::ChildIterator());
+ EXPECT_EQ(CIt, Tree::ConstChildIterator());
+ EXPECT_FALSE(It);
+ EXPECT_FALSE(CIt);
+ EXPECT_EQ(nullptr, It.asPointer());
+ EXPECT_EQ(nullptr, CIt.asPointer());
+}
+
class ListTest : public SyntaxTreeTest {
private:
std::string dumpQuotedTokensOrNull(const Node *N) {