eduucaldas created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
eduucaldas requested review of this revision.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D88106

Files:
  clang/include/clang/Tooling/Syntax/Tree.h
  clang/lib/Tooling/Syntax/Nodes.cpp
  clang/lib/Tooling/Syntax/Tree.cpp

Index: clang/lib/Tooling/Syntax/Tree.cpp
===================================================================
--- clang/lib/Tooling/Syntax/Tree.cpp
+++ clang/lib/Tooling/Syntax/Tree.cpp
@@ -9,6 +9,7 @@
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Tooling/Syntax/Nodes.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Casting.h"
 #include <cassert>
@@ -294,46 +295,107 @@
   }
 }
 
-std::vector<syntax::List::ElementAndDelimiter<syntax::Node>>
-syntax::List::getElementsAsNodesAndDelimiters() {
-  if (!getFirstChild())
-    return {};
+syntax::List::ElementAndDelimiter<syntax::Node>
+syntax::List::getWithDelimiter(syntax::Node *Element) {
+  assert(Element && Element->getRole() == syntax::NodeRole::ListElement);
+  auto *Next = Element->getNextSibling();
+  if (!Next)
+    return {Element, nullptr};
+  switch (Next->getRole()) {
+  case syntax::NodeRole::ListElement:
+    return {Element, nullptr};
+  case syntax::NodeRole::ListDelimiter:
+    return {Element, cast<syntax::Leaf>(Next)};
+  default:
+    llvm_unreachable(
+        "A list can have only elements and delimiters as children.");
+  }
+}
 
-  std::vector<syntax::List::ElementAndDelimiter<Node>> Children;
-  syntax::Node *ElementWithoutDelimiter = nullptr;
-  for (auto *C = getFirstChild(); C; C = C->getNextSibling()) {
-    switch (C->getRole()) {
-    case syntax::NodeRole::ListElement: {
-      if (ElementWithoutDelimiter) {
-        Children.push_back({ElementWithoutDelimiter, nullptr});
-      }
-      ElementWithoutDelimiter = C;
-      break;
-    }
-    case syntax::NodeRole::ListDelimiter: {
-      Children.push_back({ElementWithoutDelimiter, cast<syntax::Leaf>(C)});
-      ElementWithoutDelimiter = nullptr;
-      break;
-    }
-    default:
-      llvm_unreachable(
-          "A list can have only elements and delimiters as children.");
+llvm::Optional<syntax::List::ElementAndDelimiter<syntax::Node>>
+syntax::List::getElementAndDelimiterAfterDelimiter(syntax::Leaf *Delimiter) {
+  assert(Delimiter && Delimiter->getRole() == syntax::NodeRole::ListDelimiter);
+  auto *Next = Delimiter->getNextSibling();
+  if (!Next) {
+    switch (getTerminationKind()) {
+    // List is separated and ends with delimiter
+    // => missing last ElementAndDelimiter.
+    case syntax::List::TerminationKind::Separated:
+      return llvm::Optional<syntax::List::ElementAndDelimiter<syntax::Node>>(
+          {nullptr, nullptr});
+    case syntax::List::TerminationKind::Terminated:
+    case syntax::List::TerminationKind::MaybeTerminated:
+      return None;
     }
   }
-
-  switch (getTerminationKind()) {
-  case syntax::List::TerminationKind::Separated: {
-    Children.push_back({ElementWithoutDelimiter, nullptr});
-    break;
+  switch (Next->getRole()) {
+  case syntax::NodeRole::ListElement:
+    return getWithDelimiter(Next);
+
+  // Consecutive Delimiters => missing Element
+  case syntax::NodeRole::ListDelimiter:
+    return llvm::Optional<syntax::List::ElementAndDelimiter<syntax::Node>>(
+        {nullptr, cast<Leaf>(Next)});
+  default:
+    llvm_unreachable(
+        "A list can have only elements and delimiters as children.");
   }
-  case syntax::List::TerminationKind::Terminated:
-  case syntax::List::TerminationKind::MaybeTerminated: {
-    if (ElementWithoutDelimiter) {
-      Children.push_back({ElementWithoutDelimiter, nullptr});
-    }
-    break;
+}
+
+llvm::Optional<syntax::List::ElementAndDelimiter<syntax::Node>>
+syntax::List::getElementAndDelimiterAfterElement(syntax::Node *Element) {
+  assert(Element && Element->getRole() == syntax::NodeRole::ListElement);
+  auto *Next = Element->getNextSibling();
+  // a  b, x => End of list, this was the last ElementAndDelimiter.
+  if (!Next)
+    return None;
+
+  switch (Next->getRole()) {
+  // x  b, c => next ElementAndDelimiter starts with 'b'.
+  case syntax::NodeRole::ListElement:
+    return getWithDelimiter(Next);
+
+  // a  x, c => next ElementAndDelimiter starts after ','.
+  case syntax::NodeRole::ListDelimiter:
+    return getElementAndDelimiterAfterDelimiter(cast<Leaf>(Next));
+
+  default:
+    llvm_unreachable(
+        "A list can have only elements and delimiters as children.");
   }
+}
+
+llvm::Optional<syntax::List::ElementAndDelimiter<syntax::Node>>
+syntax::List::getNext(syntax::List::ElementAndDelimiter<syntax::Node> &ED) {
+  if (auto *Delimiter = ED.delimiter)
+    return getElementAndDelimiterAfterDelimiter(Delimiter);
+  if (auto *Element = ED.element)
+    return getElementAndDelimiterAfterElement(Element);
+  return None;
+}
+
+llvm::Optional<syntax::List::ElementAndDelimiter<syntax::Node>>
+syntax::List::getFirst() {
+  auto *First = this->getFirstChild();
+  if (!First)
+    return None;
+  switch (First->getRole()) {
+  case syntax::NodeRole::ListElement:
+    return getWithDelimiter(First);
+  case syntax::NodeRole::ListDelimiter:
+    return llvm::Optional<syntax::List::ElementAndDelimiter<syntax::Node>>(
+        {nullptr, cast<Leaf>(First)});
+  default:
+    llvm_unreachable(
+        "A list can have only elements and delimiters as children.");
   }
+}
+
+std::vector<syntax::List::ElementAndDelimiter<syntax::Node>>
+syntax::List::getElementsAsNodesAndDelimiters() {
+  auto Children = std::vector<syntax::List::ElementAndDelimiter<Node>>();
+  for (auto C = getFirst(); C; C = getNext(*C))
+    Children.push_back(*C);
 
   return Children;
 }
@@ -341,43 +403,9 @@
 // Almost the same implementation of `getElementsAsNodesAndDelimiters` but
 // ignoring delimiters
 std::vector<syntax::Node *> syntax::List::getElementsAsNodes() {
-  if (!getFirstChild())
-    return {};
-
-  std::vector<syntax::Node *> Children;
-  syntax::Node *ElementWithoutDelimiter = nullptr;
-  for (auto *C = getFirstChild(); C; C = C->getNextSibling()) {
-    switch (C->getRole()) {
-    case syntax::NodeRole::ListElement: {
-      if (ElementWithoutDelimiter) {
-        Children.push_back(ElementWithoutDelimiter);
-      }
-      ElementWithoutDelimiter = C;
-      break;
-    }
-    case syntax::NodeRole::ListDelimiter: {
-      Children.push_back(ElementWithoutDelimiter);
-      ElementWithoutDelimiter = nullptr;
-      break;
-    }
-    default:
-      llvm_unreachable("A list has only elements or delimiters.");
-    }
-  }
-
-  switch (getTerminationKind()) {
-  case syntax::List::TerminationKind::Separated: {
-    Children.push_back(ElementWithoutDelimiter);
-    break;
-  }
-  case syntax::List::TerminationKind::Terminated:
-  case syntax::List::TerminationKind::MaybeTerminated: {
-    if (ElementWithoutDelimiter) {
-      Children.push_back(ElementWithoutDelimiter);
-    }
-    break;
-  }
-  }
+  auto Children = std::vector<syntax::Node *>();
+  for (auto C = getFirst(); C; C = getNext(*C))
+    Children.push_back(C->element);
 
   return Children;
 }
Index: clang/lib/Tooling/Syntax/Nodes.cpp
===================================================================
--- clang/lib/Tooling/Syntax/Nodes.cpp
+++ clang/lib/Tooling/Syntax/Nodes.cpp
@@ -226,68 +226,58 @@
 // vector
 std::vector<syntax::NameSpecifier *>
 syntax::NestedNameSpecifier::getSpecifiers() {
-  auto SpecifiersAsNodes = getElementsAsNodes();
-  std::vector<syntax::NameSpecifier *> Children;
-  for (const auto &Element : SpecifiersAsNodes) {
-    Children.push_back(llvm::cast<syntax::NameSpecifier>(Element));
-  }
+  auto Children = std::vector<syntax::NameSpecifier *>();
+  for (auto C = getFirst(); C; C = getNext(*C))
+    Children.push_back(cast<syntax::NameSpecifier>(C->element));
+
   return Children;
 }
 
 std::vector<syntax::List::ElementAndDelimiter<syntax::NameSpecifier>>
 syntax::NestedNameSpecifier::getSpecifiersAndDoubleColons() {
-  auto SpecifiersAsNodesAndDoubleColons = getElementsAsNodesAndDelimiters();
-  std::vector<syntax::List::ElementAndDelimiter<syntax::NameSpecifier>>
-      Children;
-  for (const auto &SpecifierAndDoubleColon : SpecifiersAsNodesAndDoubleColons) {
-    Children.push_back(
-        {llvm::cast<syntax::NameSpecifier>(SpecifierAndDoubleColon.element),
-         SpecifierAndDoubleColon.delimiter});
-  }
+  auto Children =
+      std::vector<syntax::List::ElementAndDelimiter<syntax::NameSpecifier>>();
+  for (auto C = getFirst(); C; C = getNext(*C))
+    Children.push_back({cast<syntax::NameSpecifier>(C->element), C->delimiter});
+
   return Children;
 }
 
 std::vector<syntax::Expression *> syntax::CallArguments::getArguments() {
-  auto ArgumentsAsNodes = getElementsAsNodes();
-  std::vector<syntax::Expression *> Children;
-  for (const auto &ArgumentAsNode : ArgumentsAsNodes) {
-    Children.push_back(llvm::cast<syntax::Expression>(ArgumentAsNode));
-  }
+  auto Children = std::vector<syntax::Expression *>();
+  for (auto C = getFirst(); C; C = getNext(*C))
+    Children.push_back(cast<syntax::Expression>(C->element));
+
   return Children;
 }
 
 std::vector<syntax::List::ElementAndDelimiter<syntax::Expression>>
 syntax::CallArguments::getArgumentsAndCommas() {
-  auto ArgumentsAsNodesAndCommas = getElementsAsNodesAndDelimiters();
-  std::vector<syntax::List::ElementAndDelimiter<syntax::Expression>> Children;
-  for (const auto &ArgumentAsNodeAndComma : ArgumentsAsNodesAndCommas) {
-    Children.push_back(
-        {llvm::cast<syntax::Expression>(ArgumentAsNodeAndComma.element),
-         ArgumentAsNodeAndComma.delimiter});
-  }
+  auto Children =
+      std::vector<syntax::List::ElementAndDelimiter<syntax::Expression>>();
+  for (auto C = getFirst(); C; C = getNext(*C))
+    Children.push_back({cast<syntax::Expression>(C->element), C->delimiter});
+
   return Children;
 }
 
 std::vector<syntax::SimpleDeclaration *>
 syntax::ParameterDeclarationList::getParameterDeclarations() {
-  auto ParametersAsNodes = getElementsAsNodes();
-  std::vector<syntax::SimpleDeclaration *> Children;
-  for (const auto &ParameterAsNode : ParametersAsNodes) {
-    Children.push_back(llvm::cast<syntax::SimpleDeclaration>(ParameterAsNode));
-  }
+  auto Children = std::vector<syntax::SimpleDeclaration *>();
+  for (auto C = getFirst(); C; C = getNext(*C))
+    Children.push_back(cast<syntax::SimpleDeclaration>(C->element));
+
   return Children;
 }
 
 std::vector<syntax::List::ElementAndDelimiter<syntax::SimpleDeclaration>>
 syntax::ParameterDeclarationList::getParametersAndCommas() {
-  auto ParametersAsNodesAndCommas = getElementsAsNodesAndDelimiters();
-  std::vector<syntax::List::ElementAndDelimiter<syntax::SimpleDeclaration>>
-      Children;
-  for (const auto &ParameterAsNodeAndComma : ParametersAsNodesAndCommas) {
+  auto Children = std::vector<
+      syntax::List::ElementAndDelimiter<syntax::SimpleDeclaration>>();
+  for (auto C = getFirst(); C; C = getNext(*C))
     Children.push_back(
-        {llvm::cast<syntax::SimpleDeclaration>(ParameterAsNodeAndComma.element),
-         ParameterAsNodeAndComma.delimiter});
-  }
+        {cast<syntax::SimpleDeclaration>(C->element), C->delimiter});
+
   return Children;
 }
 
Index: clang/include/clang/Tooling/Syntax/Tree.h
===================================================================
--- clang/include/clang/Tooling/Syntax/Tree.h
+++ clang/include/clang/Tooling/Syntax/Tree.h
@@ -214,6 +214,16 @@
 
   using Tree::Tree;
   static bool classof(const Node *N);
+
+  ElementAndDelimiter<Node> getWithDelimiter(Node *Element);
+  llvm::Optional<ElementAndDelimiter<Node>>
+  getElementAndDelimiterAfterDelimiter(Leaf *Delimiter);
+  llvm::Optional<ElementAndDelimiter<Node>>
+  getElementAndDelimiterAfterElement(Node *Element);
+  llvm::Optional<ElementAndDelimiter<Node>>
+  getNext(ElementAndDelimiter<Node> &B);
+  llvm::Optional<ElementAndDelimiter<Node>> getFirst();
+
   /// Returns the elements and corresponding delimiters. Missing elements
   /// and delimiters are represented as null pointers.
   ///
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to