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