[clang] c3c08bf - [SyntaxTree] Test the List API
Eduardo Caldas via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 22 10:07:51 PDT 2020
Author: Eduardo Caldas
Date: 2020-09-22T17:07:41Z
New Revision: c3c08bfdfd6244e0429753ee56df39c90187d772
URL: https://github.com/llvm/llvm-project/commit/c3c08bfdfd6244e0429753ee56df39c90187d772
DIFF: https://github.com/llvm/llvm-project/commit/c3c08bfdfd6244e0429753ee56df39c90187d772.diff
LOG: [SyntaxTree] Test the List API
Differential Revision: https://reviews.llvm.org/D87839
Added:
Modified:
clang/include/clang/Tooling/Syntax/Tree.h
clang/unittests/Tooling/Syntax/TreeTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Tooling/Syntax/Tree.h b/clang/include/clang/Tooling/Syntax/Tree.h
index a544fc1827b7..5840a86199eb 100644
--- a/clang/include/clang/Tooling/Syntax/Tree.h
+++ b/clang/include/clang/Tooling/Syntax/Tree.h
@@ -218,12 +218,16 @@ class List : public Tree {
/// and delimiters are represented as null pointers.
///
/// For example, in a separated list:
- /// "a, b, c" <=> [("a", ","), ("b", ","), ("c", null)]
- /// "a, , c" <=> [("a", ","), (null, ","), ("c", ",)]
- /// "a, b," <=> [("a", ","), ("b", ","), (null, null)]
+ /// "a, b, c" <=> [("a" , ","), ("b" , "," ), ("c" , null)]
+ /// "a, , c" <=> [("a" , ","), (null, "," ), ("c" , null)]
+ /// "a, b c" <=> [("a" , ","), ("b" , null), ("c" , null)]
+ /// "a, b," <=> [("a" , ","), ("b" , "," ), (null, null)]
///
/// In a terminated or maybe-terminated list:
- /// "a, b," <=> [("a", ","), ("b", ",")]
+ /// "a; b; c;" <=> [("a" , ";"), ("b" , ";" ), ("c" , ";" )]
+ /// "a; ; c;" <=> [("a" , ";"), (null, ";" ), ("c" , ";" )]
+ /// "a; b c;" <=> [("a" , ";"), ("b" , null), ("c" , ";" )]
+ /// "a; b; c" <=> [("a" , ";"), ("b" , ";" ), ("c" , null)]
std::vector<ElementAndDelimiter<Node>> getElementsAsNodesAndDelimiters();
/// Returns the elements of the list. Missing elements are represented
diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp
index 6e777b353b04..fba3164e5966 100644
--- a/clang/unittests/Tooling/Syntax/TreeTest.cpp
+++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp
@@ -9,6 +9,8 @@
#include "clang/Tooling/Syntax/Tree.h"
#include "TreeTestBase.h"
#include "clang/Tooling/Syntax/BuildTree.h"
+#include "clang/Tooling/Syntax/Nodes.h"
+#include "llvm/ADT/STLExtras.h"
#include "gtest/gtest.h"
using namespace clang;
@@ -122,4 +124,231 @@ TEST_P(TreeTest, LastLeaf) {
}
}
+class ListTest : public SyntaxTreeTest {
+private:
+ std::string dumpQuotedTokensOrNull(const Node *N) {
+ return N ? "'" +
+ StringRef(N->dumpTokens(Arena->getSourceManager()))
+ .trim()
+ .str() +
+ "'"
+ : "null";
+ }
+
+protected:
+ std::string
+ dumpElementsAndDelimiters(ArrayRef<List::ElementAndDelimiter<Node>> EDs) {
+ std::string Storage;
+ llvm::raw_string_ostream OS(Storage);
+
+ OS << "[";
+
+ llvm::interleaveComma(
+ EDs, OS, [&OS, this](const List::ElementAndDelimiter<Node> &ED) {
+ OS << "(" << dumpQuotedTokensOrNull(ED.element) << ", "
+ << dumpQuotedTokensOrNull(ED.delimiter) << ")";
+ });
+
+ OS << "]";
+
+ return OS.str();
+ }
+
+ std::string dumpNodes(ArrayRef<Node *> Nodes) {
+ std::string Storage;
+ llvm::raw_string_ostream OS(Storage);
+
+ OS << "[";
+
+ llvm::interleaveComma(Nodes, OS, [&OS, this](const Node *N) {
+ OS << dumpQuotedTokensOrNull(N);
+ });
+
+ OS << "]";
+
+ return OS.str();
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(TreeTests, ListTest,
+ ::testing::ValuesIn(allTestClangConfigs()), );
+
+/// "a, b, c" <=> [("a", ","), ("b", ","), ("c", null)]
+TEST_P(ListTest, List_Separated_WellFormed) {
+ buildTree("", GetParam());
+
+ // "a, b, c"
+ auto *List = dyn_cast<syntax::List>(syntax::createTree(
+ *Arena,
+ {
+ {createLeaf(*Arena, tok::identifier, "a"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::comma), NodeRole::ListDelimiter},
+ {createLeaf(*Arena, tok::identifier, "b"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::comma), NodeRole::ListDelimiter},
+ {createLeaf(*Arena, tok::identifier, "c"), NodeRole::ListElement},
+ },
+ NodeKind::CallArguments));
+
+ EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
+ "[('a', ','), ('b', ','), ('c', null)]");
+ EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', 'b', 'c']");
+}
+
+/// "a, , c" <=> [("a", ","), (null, ","), ("c", null)]
+TEST_P(ListTest, List_Separated_MissingElement) {
+ buildTree("", GetParam());
+
+ // "a, , c"
+ auto *List = dyn_cast<syntax::List>(syntax::createTree(
+ *Arena,
+ {
+ {createLeaf(*Arena, tok::identifier, "a"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::comma), NodeRole::ListDelimiter},
+ {createLeaf(*Arena, tok::comma), NodeRole::ListDelimiter},
+ {createLeaf(*Arena, tok::identifier, "c"), NodeRole::ListElement},
+ },
+ NodeKind::CallArguments));
+
+ EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
+ "[('a', ','), (null, ','), ('c', null)]");
+ EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', null, 'c']");
+}
+
+/// "a, b c" <=> [("a", ","), ("b", null), ("c", null)]
+TEST_P(ListTest, List_Separated_MissingDelimiter) {
+ buildTree("", GetParam());
+
+ // "a, b c"
+ auto *List = dyn_cast<syntax::List>(syntax::createTree(
+ *Arena,
+ {
+ {createLeaf(*Arena, tok::identifier, "a"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::comma), NodeRole::ListDelimiter},
+ {createLeaf(*Arena, tok::identifier, "b"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::identifier, "c"), NodeRole::ListElement},
+ },
+ NodeKind::CallArguments));
+
+ EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
+ "[('a', ','), ('b', null), ('c', null)]");
+ EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', 'b', 'c']");
+}
+
+/// "a, b," <=> [("a", ","), ("b", ","), (null, null)]
+TEST_P(ListTest, List_Separated_MissingLastElement) {
+ buildTree("", GetParam());
+
+ // "a, b, c"
+ auto *List = dyn_cast<syntax::List>(syntax::createTree(
+ *Arena,
+ {
+ {createLeaf(*Arena, tok::identifier, "a"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::comma), NodeRole::ListDelimiter},
+ {createLeaf(*Arena, tok::identifier, "b"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::comma), NodeRole::ListDelimiter},
+ },
+ NodeKind::CallArguments));
+
+ EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
+ "[('a', ','), ('b', ','), (null, null)]");
+ EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', 'b', null]");
+}
+
+/// "a:: b:: c::" <=> [("a", "::"), ("b", "::"), ("c", "::")]
+TEST_P(ListTest, List_Terminated_WellFormed) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ buildTree("", GetParam());
+
+ // "a:: b:: c::"
+ auto *List = dyn_cast<syntax::List>(syntax::createTree(
+ *Arena,
+ {
+ {createLeaf(*Arena, tok::identifier, "a"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::coloncolon), NodeRole::ListDelimiter},
+ {createLeaf(*Arena, tok::identifier, "b"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::coloncolon), NodeRole::ListDelimiter},
+ {createLeaf(*Arena, tok::identifier, "c"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::coloncolon), NodeRole::ListDelimiter},
+ },
+ NodeKind::NestedNameSpecifier));
+
+ EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
+ "[('a', '::'), ('b', '::'), ('c', '::')]");
+ EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', 'b', 'c']");
+}
+
+/// "a:: :: c::" <=> [("a", "::"), (null, "::"), ("c", "::")]
+TEST_P(ListTest, List_Terminated_MissingElement) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ buildTree("", GetParam());
+
+ // "a:: b:: c::"
+ auto *List = dyn_cast<syntax::List>(syntax::createTree(
+ *Arena,
+ {
+ {createLeaf(*Arena, tok::identifier, "a"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::coloncolon), NodeRole::ListDelimiter},
+ {createLeaf(*Arena, tok::coloncolon), NodeRole::ListDelimiter},
+ {createLeaf(*Arena, tok::identifier, "c"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::coloncolon), NodeRole::ListDelimiter},
+ },
+ NodeKind::NestedNameSpecifier));
+
+ EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
+ "[('a', '::'), (null, '::'), ('c', '::')]");
+ EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', null, 'c']");
+}
+
+/// "a:: b c::" <=> [("a", "::"), ("b", null), ("c", "::")]
+TEST_P(ListTest, List_Terminated_MissingDelimiter) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ buildTree("", GetParam());
+
+ // "a:: b c::"
+ auto *List = dyn_cast<syntax::List>(syntax::createTree(
+ *Arena,
+ {
+ {createLeaf(*Arena, tok::identifier, "a"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::coloncolon), NodeRole::ListDelimiter},
+ {createLeaf(*Arena, tok::identifier, "b"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::identifier, "c"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::coloncolon), NodeRole::ListDelimiter},
+ },
+ NodeKind::NestedNameSpecifier));
+
+ EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
+ "[('a', '::'), ('b', null), ('c', '::')]");
+ EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', 'b', 'c']");
+}
+
+/// "a:: b:: c" <=> [("a", "::"), ("b", "::"), ("c", null)]
+TEST_P(ListTest, List_Terminated_MissingLastDelimiter) {
+ if (!GetParam().isCXX()) {
+ return;
+ }
+ buildTree("", GetParam());
+
+ // "a:: b:: c"
+ auto *List = dyn_cast<syntax::List>(syntax::createTree(
+ *Arena,
+ {
+ {createLeaf(*Arena, tok::identifier, "a"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::coloncolon), NodeRole::ListDelimiter},
+ {createLeaf(*Arena, tok::identifier, "b"), NodeRole::ListElement},
+ {createLeaf(*Arena, tok::coloncolon), NodeRole::ListDelimiter},
+ {createLeaf(*Arena, tok::identifier, "c"), NodeRole::ListElement},
+ },
+ NodeKind::NestedNameSpecifier));
+
+ EXPECT_EQ(dumpElementsAndDelimiters(List->getElementsAsNodesAndDelimiters()),
+ "[('a', '::'), ('b', '::'), ('c', null)]");
+ EXPECT_EQ(dumpNodes(List->getElementsAsNodes()), "['a', 'b', 'c']");
+}
+
} // namespace
More information about the cfe-commits
mailing list