[PATCH] D87779: [SyntaxTree] Test `findFirstLeaf` and `findLastLeaf`

2020-09-22 Thread Eduardo Caldas via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGaf582c9b0f3a: [SyntaxTree] Test `findFirstLeaf` and 
`findLastLeaf` (authored by eduucaldas).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87779/new/

https://reviews.llvm.org/D87779

Files:
  clang/lib/Tooling/Syntax/Tree.cpp
  clang/unittests/Tooling/Syntax/CMakeLists.txt
  clang/unittests/Tooling/Syntax/TreeTest.cpp

Index: clang/unittests/Tooling/Syntax/TreeTest.cpp
===
--- /dev/null
+++ clang/unittests/Tooling/Syntax/TreeTest.cpp
@@ -0,0 +1,125 @@
+//===- TreeTest.cpp -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "clang/Tooling/Syntax/Tree.h"
+#include "TreeTestBase.h"
+#include "clang/Tooling/Syntax/BuildTree.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace clang::syntax;
+
+namespace {
+
+class TreeTest : public SyntaxTreeTest {
+private:
+  Tree *createTree(ArrayRef Children) {
+std::vector> ChildrenWithRoles;
+ChildrenWithRoles.reserve(Children.size());
+for (const auto *Child : Children) {
+  ChildrenWithRoles.push_back(
+  std::make_pair(deepCopy(*Arena, Child), NodeRole::Unknown));
+}
+return clang::syntax::createTree(*Arena, ChildrenWithRoles,
+ NodeKind::UnknownExpression);
+  }
+
+  // Generate Forests by combining `Children` into `ParentCount` Trees.
+  //
+  // We do this recursively.
+  std::vector>
+  generateAllForests(ArrayRef Children, unsigned ParentCount) {
+assert(ParentCount > 0);
+// If there is only one Parent node, then combine `Children` under
+// this Parent.
+if (ParentCount == 1)
+  return {{createTree(Children)}};
+
+// Otherwise, combine `ChildrenCount` children under the last parent and
+// solve the smaller problem without these children and this parent. Do this
+// for every `ChildrenCount` and combine the results.
+std::vector> AllForests;
+for (unsigned ChildrenCount = 0; ChildrenCount <= Children.size();
+ ++ChildrenCount) {
+  auto *LastParent = createTree(Children.take_back(ChildrenCount));
+  for (auto  : generateAllForests(Children.drop_back(ChildrenCount),
+ ParentCount - 1)) {
+Forest.push_back(LastParent);
+AllForests.push_back(Forest);
+  }
+}
+return AllForests;
+  }
+
+protected:
+  // Generates all trees with a `Base` of `Node`s and `NodeCountPerLayer`
+  // `Node`s per layer. An example of Tree with `Base` = {`(`, `)`} and
+  // `NodeCountPerLayer` = {2, 2}:
+  //  Tree
+  //  |-Tree
+  //  `-Tree
+  //|-Tree
+  //| `-'('
+  //`-Tree
+  //  `-')'
+  std::vector
+  generateAllTreesWithShape(ArrayRef Base,
+ArrayRef NodeCountPerLayer) {
+// We compute the solution per layer. A layer is a collection of bases,
+// where each base has the same number of nodes, given by
+// `NodeCountPerLayer`.
+auto GenerateNextLayer = [this](ArrayRef> Layer,
+unsigned NextLayerNodeCount) {
+  std::vector> NextLayer;
+  for (const auto  : Layer) {
+for (const auto  :
+ generateAllForests(Base, NextLayerNodeCount)) {
+  NextLayer.push_back(
+  std::vector(NextBase.begin(), NextBase.end()));
+}
+  }
+  return NextLayer;
+};
+
+std::vector> Layer = {Base};
+for (auto NodeCount : NodeCountPerLayer)
+  Layer = GenerateNextLayer(Layer, NodeCount);
+
+std::vector AllTrees;
+AllTrees.reserve(Layer.size());
+for (const auto  : Layer)
+  AllTrees.push_back(createTree(Base));
+
+return AllTrees;
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(TreeTests, TreeTest,
+::testing::ValuesIn(allTestClangConfigs()), );
+
+TEST_P(TreeTest, FirstLeaf) {
+  buildTree("", GetParam());
+  std::vector Leafs = {createLeaf(*Arena, tok::l_paren),
+ createLeaf(*Arena, tok::r_paren)};
+  for (const auto *Tree : generateAllTreesWithShape(Leafs, {3u})) {
+ASSERT_TRUE(Tree->findFirstLeaf() != nullptr);
+EXPECT_EQ(Tree->findFirstLeaf()->getToken()->kind(), tok::l_paren);
+  }
+}
+
+TEST_P(TreeTest, LastLeaf) {
+  buildTree("", GetParam());
+  std::vector Leafs = {createLeaf(*Arena, tok::l_paren),
+ createLeaf(*Arena, tok::r_paren)};
+  for (const auto *Tree : generateAllTreesWithShape(Leafs, {3u})) {
+ASSERT_TRUE(Tree->findLastLeaf() != nullptr);
+

[PATCH] D87779: [SyntaxTree] Test `findFirstLeaf` and `findLastLeaf`

2020-09-21 Thread Eduardo Caldas via Phabricator via cfe-commits
eduucaldas updated this revision to Diff 293167.
eduucaldas added a comment.

Comment `generateAllTreesWithShape`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87779/new/

https://reviews.llvm.org/D87779

Files:
  clang/lib/Tooling/Syntax/Tree.cpp
  clang/unittests/Tooling/Syntax/CMakeLists.txt
  clang/unittests/Tooling/Syntax/TreeTest.cpp

Index: clang/unittests/Tooling/Syntax/TreeTest.cpp
===
--- /dev/null
+++ clang/unittests/Tooling/Syntax/TreeTest.cpp
@@ -0,0 +1,125 @@
+//===- TreeTest.cpp -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "clang/Tooling/Syntax/Tree.h"
+#include "TreeTestBase.h"
+#include "clang/Tooling/Syntax/BuildTree.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace clang::syntax;
+
+namespace {
+
+class TreeTest : public SyntaxTreeTest {
+private:
+  Tree *createTree(ArrayRef Children) {
+std::vector> ChildrenWithRoles;
+ChildrenWithRoles.reserve(Children.size());
+for (const auto *Child : Children) {
+  ChildrenWithRoles.push_back(
+  std::make_pair(deepCopy(*Arena, Child), NodeRole::Unknown));
+}
+return clang::syntax::createTree(*Arena, ChildrenWithRoles,
+ NodeKind::UnknownExpression);
+  }
+
+  // Generate Forests by combining `Children` into `ParentCount` Trees.
+  //
+  // We do this recursively.
+  std::vector>
+  generateAllForests(ArrayRef Children, unsigned ParentCount) {
+assert(ParentCount > 0);
+// If there is only one Parent node, then combine `Children` under
+// this Parent.
+if (ParentCount == 1)
+  return {{createTree(Children)}};
+
+// Otherwise, combine `ChildrenCount` children under the last parent and
+// solve the smaller problem without these children and this parent. Do this
+// for every `ChildrenCount` and combine the results.
+std::vector> AllForests;
+for (unsigned ChildrenCount = 0; ChildrenCount <= Children.size();
+ ++ChildrenCount) {
+  auto *LastParent = createTree(Children.take_back(ChildrenCount));
+  for (auto  : generateAllForests(Children.drop_back(ChildrenCount),
+ ParentCount - 1)) {
+Forest.push_back(LastParent);
+AllForests.push_back(Forest);
+  }
+}
+return AllForests;
+  }
+
+protected:
+  // Generates all trees with a `Base` of `Node`s and `NodeCountPerLayer`
+  // `Node`s per layer. An example of Tree with `Base` = {`(`, `)`} and
+  // `NodeCountPerLayer` = {2, 2}:
+  //  Tree
+  //  |-Tree
+  //  `-Tree
+  //|-Tree
+  //| `-'('
+  //`-Tree
+  //  `-')'
+  std::vector
+  generateAllTreesWithShape(ArrayRef Base,
+ArrayRef NodeCountPerLayer) {
+// We compute the solution per layer. A layer is a collection of bases,
+// where each base has the same number of nodes, given by
+// `NodeCountPerLayer`.
+auto GenerateNextLayer = [this](ArrayRef> Layer,
+unsigned NextLayerNodeCount) {
+  std::vector> NextLayer;
+  for (const auto  : Layer) {
+for (const auto  :
+ generateAllForests(Base, NextLayerNodeCount)) {
+  NextLayer.push_back(
+  std::vector(NextBase.begin(), NextBase.end()));
+}
+  }
+  return NextLayer;
+};
+
+std::vector> Layer = {Base};
+for (auto NodeCount : NodeCountPerLayer)
+  Layer = GenerateNextLayer(Layer, NodeCount);
+
+std::vector AllTrees;
+AllTrees.reserve(Layer.size());
+for (const auto  : Layer)
+  AllTrees.push_back(createTree(Base));
+
+return AllTrees;
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(TreeTests, TreeTest,
+::testing::ValuesIn(allTestClangConfigs()), );
+
+TEST_P(TreeTest, FirstLeaf) {
+  buildTree("", GetParam());
+  std::vector Leafs = {createLeaf(*Arena, tok::l_paren),
+ createLeaf(*Arena, tok::r_paren)};
+  for (const auto *Tree : generateAllTreesWithShape(Leafs, {3u})) {
+ASSERT_TRUE(Tree->findFirstLeaf() != nullptr);
+EXPECT_EQ(Tree->findFirstLeaf()->getToken()->kind(), tok::l_paren);
+  }
+}
+
+TEST_P(TreeTest, LastLeaf) {
+  buildTree("", GetParam());
+  std::vector Leafs = {createLeaf(*Arena, tok::l_paren),
+ createLeaf(*Arena, tok::r_paren)};
+  for (const auto *Tree : generateAllTreesWithShape(Leafs, {3u})) {
+ASSERT_TRUE(Tree->findLastLeaf() != nullptr);
+EXPECT_EQ(Tree->findLastLeaf()->getToken()->kind(), tok::r_paren);
+  }
+}
+
+} // namespace
Index: 

[PATCH] D87779: [SyntaxTree] Test `findFirstLeaf` and `findLastLeaf`

2020-09-21 Thread Eduardo Caldas via Phabricator via cfe-commits
eduucaldas updated this revision to Diff 293163.
eduucaldas marked 3 inline comments as done.
eduucaldas added a comment.

- Answer Review
- Change names in `generateAllTreesWithShape`
- `auto x = vector()` -> `vector x;`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87779/new/

https://reviews.llvm.org/D87779

Files:
  clang/lib/Tooling/Syntax/Tree.cpp
  clang/unittests/Tooling/Syntax/CMakeLists.txt
  clang/unittests/Tooling/Syntax/TreeTest.cpp

Index: clang/unittests/Tooling/Syntax/TreeTest.cpp
===
--- /dev/null
+++ clang/unittests/Tooling/Syntax/TreeTest.cpp
@@ -0,0 +1,123 @@
+//===- TreeTest.cpp -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "clang/Tooling/Syntax/Tree.h"
+#include "TreeTestBase.h"
+#include "clang/Tooling/Syntax/BuildTree.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace clang::syntax;
+
+namespace {
+
+class TreeTest : public SyntaxTreeTest {
+private:
+  Tree *createTree(ArrayRef Children) {
+std::vector> ChildrenWithRoles;
+ChildrenWithRoles.reserve(Children.size());
+for (const auto *Child : Children) {
+  ChildrenWithRoles.push_back(
+  std::make_pair(deepCopy(*Arena, Child), NodeRole::Unknown));
+}
+return clang::syntax::createTree(*Arena, ChildrenWithRoles,
+ NodeKind::UnknownExpression);
+  }
+
+  // Generate Forests by combining `Children` into `ParentCount` Trees.
+  //
+  // We do this recursively.
+  std::vector>
+  generateAllForests(ArrayRef Children, unsigned ParentCount) {
+assert(ParentCount > 0);
+// If there is only one Parent node, then combine `Children` under
+// this Parent.
+if (ParentCount == 1)
+  return {{createTree(Children)}};
+
+// Otherwise, combine `ChildrenCount` children under the last parent and
+// solve the smaller problem without these children and this parent. Do this
+// for every `ChildrenCount` and combine the results.
+std::vector> AllForests;
+for (unsigned ChildrenCount = 0; ChildrenCount <= Children.size();
+ ++ChildrenCount) {
+  auto *LastParent = createTree(Children.take_back(ChildrenCount));
+  for (auto  : generateAllForests(Children.drop_back(ChildrenCount),
+ ParentCount - 1)) {
+Forest.push_back(LastParent);
+AllForests.push_back(Forest);
+  }
+}
+return AllForests;
+  }
+
+protected:
+  // Generates all trees with a `Base` of `Node`s and `NodeCountPerLayer`
+  // `Node`s per layer. An example of Tree with `Base` = {`(`, `)`} and
+  // `NodeCountPerLayer` = {2, 2}:
+  //  Tree
+  //  |-Tree
+  //  `-Tree
+  //|-Tree
+  //| `-'('
+  //`-Tree
+  //  `-')'
+  std::vector
+  generateAllTreesWithShape(ArrayRef Base,
+ArrayRef NodeCountPerLayer) {
+auto GenerateNextLayer = [this](ArrayRef> Layer,
+unsigned NextLayerNodeCount) {
+  std::vector> NextLayer;
+  for (const auto  : Layer) {
+for (const auto  :
+ generateAllForests(Base, NextLayerNodeCount)) {
+  NextLayer.push_back(
+  std::vector(NextBase.begin(), NextBase.end()));
+}
+  }
+  return NextLayer;
+};
+
+std::vector> Layer = {Base};
+for (auto NodeCount : NodeCountPerLayer) {
+  Layer = GenerateNextLayer(Layer, NodeCount);
+}
+
+std::vector AllTrees;
+AllTrees.reserve(Layer.size());
+for (const auto  : Layer) {
+  AllTrees.push_back(createTree(Base));
+}
+return AllTrees;
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(TreeTests, TreeTest,
+::testing::ValuesIn(allTestClangConfigs()), );
+
+TEST_P(TreeTest, FirstLeaf) {
+  buildTree("", GetParam());
+  std::vector Leafs = {createLeaf(*Arena, tok::l_paren),
+ createLeaf(*Arena, tok::r_paren)};
+  for (const auto *Tree : generateAllTreesWithShape(Leafs, {3u})) {
+ASSERT_TRUE(Tree->findFirstLeaf() != nullptr);
+EXPECT_EQ(Tree->findFirstLeaf()->getToken()->kind(), tok::l_paren);
+  }
+}
+
+TEST_P(TreeTest, LastLeaf) {
+  buildTree("", GetParam());
+  std::vector Leafs = {createLeaf(*Arena, tok::l_paren),
+ createLeaf(*Arena, tok::r_paren)};
+  for (const auto *Tree : generateAllTreesWithShape(Leafs, {3u})) {
+ASSERT_TRUE(Tree->findLastLeaf() != nullptr);
+EXPECT_EQ(Tree->findLastLeaf()->getToken()->kind(), tok::r_paren);
+  }
+}
+
+} // namespace
Index: clang/unittests/Tooling/Syntax/CMakeLists.txt

[PATCH] D87779: [SyntaxTree] Test `findFirstLeaf` and `findLastLeaf`

2020-09-18 Thread Dmitri Gribenko via Phabricator via cfe-commits
gribozavr2 added inline comments.



Comment at: clang/unittests/Tooling/Syntax/TreeTest.cpp:9
+//
+// This file tests the Syntax Tree base API.
+//

Please elaborate what "base API" covers -- specifically, what classes and such. 
 However, I'm not sure it is necessary to have this comment at all. Up to you.



Comment at: clang/unittests/Tooling/Syntax/TreeTest.cpp:39
+return ::testing::AssertionSuccess();
+  }
+

Is this copied from somewhere? I feel like other tests have this function 
already. Can we share?



Comment at: clang/unittests/Tooling/Syntax/TreeTest.cpp:52
+
+  // Generate Forests by combining `Children` under `ParentCount` Trees.
+  //

under => into?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87779/new/

https://reviews.llvm.org/D87779

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D87779: [SyntaxTree] Test `findFirstLeaf` and `findLastLeaf`

2020-09-16 Thread Eduardo Caldas via Phabricator via cfe-commits
eduucaldas created this revision.
Herald added subscribers: cfe-commits, mgorny.
Herald added a project: clang.
eduucaldas requested review of this revision.

- Introduce `TreeTest.cpp` to unit test `Tree.h`
- Add `generateAllTreesWithShape` to generating test cases
- Add tests for `findFirstLeaf` and `findLastLeaf`
- Fix implementations of `findFirstLeaf` and `findLastLeaf` that had

been broken when empty `Tree` were present.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D87779

Files:
  clang/lib/Tooling/Syntax/Tree.cpp
  clang/unittests/Tooling/Syntax/CMakeLists.txt
  clang/unittests/Tooling/Syntax/TreeTest.cpp

Index: clang/unittests/Tooling/Syntax/TreeTest.cpp
===
--- /dev/null
+++ clang/unittests/Tooling/Syntax/TreeTest.cpp
@@ -0,0 +1,141 @@
+//===- TreeTest.cpp -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// This file tests the Syntax Tree base API.
+//
+//===--===//
+
+#include "clang/Tooling/Syntax/Tree.h"
+#include "TreeTestBase.h"
+#include "clang/Tooling/Syntax/BuildTree.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace clang::syntax;
+
+namespace {
+
+class TreeTest : public SyntaxTreeTest {
+protected:
+  ::testing::AssertionResult treeDumpEqual(const syntax::Node *Root,
+   StringRef Dump) {
+if (!Root)
+  return ::testing::AssertionFailure()
+ << "Root was not built successfully.";
+
+auto Actual = StringRef(Root->dump(Arena->getSourceManager())).trim().str();
+auto Expected = Dump.trim().str();
+// EXPECT_EQ shows the diff between the two strings if they are different.
+EXPECT_EQ(Expected, Actual);
+if (Actual != Expected) {
+  return ::testing::AssertionFailure();
+}
+return ::testing::AssertionSuccess();
+  }
+
+  Tree *createTree(ArrayRef Children) {
+auto ChildrenWithRoles = std::vector>();
+ChildrenWithRoles.reserve(Children.size());
+for (const auto *Child : Children) {
+  ChildrenWithRoles.push_back(
+  std::make_pair(deepCopy(*Arena, Child), NodeRole::Unknown));
+}
+return clang::syntax::createTree(*Arena, ChildrenWithRoles,
+ NodeKind::UnknownExpression);
+  }
+
+  // Generate Forests by combining `Children` under `ParentCount` Trees.
+  //
+  // We do this recursively.
+  std::vector>
+  generateAllForests(ArrayRef Children, unsigned ParentCount) {
+assert(ParentCount > 0);
+// If there is only one Parent node, we need to combine `Children` under
+// this Parent.
+if (ParentCount == 1)
+  return {{createTree(Children)}};
+
+// Otherwise, we combine `ChildrenCount` children under the last parent and
+// solve the smaller problem without these children and this parent. Finally
+// we combine the results for every possible `ChildrenCount`.
+auto AllForests = std::vector>();
+for (unsigned ChildrenCount = 0; ChildrenCount <= Children.size();
+ ++ChildrenCount) {
+  auto *LastParent = createTree(Children.take_back(ChildrenCount));
+  for (auto  : generateAllForests(Children.drop_back(ChildrenCount),
+ ParentCount - 1)) {
+Forest.push_back(LastParent);
+AllForests.push_back(Forest);
+  }
+}
+return AllForests;
+  }
+
+  // Generates all trees with a `Base` layer of `Node`s and `NodeCountPerLayer`
+  // `Node`s per layer. An example of Tree with `Base` = {`(`, `)`} and
+  // `NodeCountPerLayer` = {2, 2}:
+  //  Tree
+  //  |-Tree
+  //  `-Tree
+  //|-Tree
+  //| `-'('
+  //`-Tree
+  //  `-')'
+  std::vector
+  generateAllTreesWithShape(ArrayRef Base,
+ArrayRef NodeCountPerLayer) {
+auto GenerateNextLayers = [this](ArrayRef> Bases,
+ unsigned NodeCount) {
+  auto NextLayers = std::vector>();
+  for (const auto  : Bases) {
+for (const auto  : generateAllForests(Base, NodeCount)) {
+  NextLayers.push_back(
+  std::vector(NextLayer.begin(), NextLayer.end()));
+}
+  }
+  return NextLayers;
+};
+
+auto Layers = std::vector>({Base});
+for (auto NodeCount : NodeCountPerLayer) {
+  Layers = GenerateNextLayers(Layers, NodeCount);
+}
+
+auto AllTrees = std::vector();
+AllTrees.reserve(Layers.size());
+for (const auto  : Layers) {
+  AllTrees.push_back(createTree(Layer));
+}
+return AllTrees;
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(TreeTests, TreeTest,
+