diff options
Diffstat (limited to 'clang/lib/Tooling/Transformer')
| -rw-r--r-- | clang/lib/Tooling/Transformer/Parsing.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Tooling/Transformer/Stencil.cpp | 79 |
2 files changed, 78 insertions, 3 deletions
diff --git a/clang/lib/Tooling/Transformer/Parsing.cpp b/clang/lib/Tooling/Transformer/Parsing.cpp index 66fa04a15594..242db2a16b43 100644 --- a/clang/lib/Tooling/Transformer/Parsing.cpp +++ b/clang/lib/Tooling/Transformer/Parsing.cpp @@ -165,7 +165,7 @@ static ExpectedProgress<llvm::NoneType> parseChar(char c, ParseState State) { static ExpectedProgress<std::string> parseId(ParseState State) { State.Input = consumeWhitespace(State.Input); auto Id = State.Input.take_while( - [](char c) { return isASCII(c) && isIdentifierBody(c); }); + [](char c) { return isASCII(c) && isAsciiIdentifierContinue(c); }); if (Id.empty()) return makeParseError(State, "failed to parse name"); return makeParseProgress(advance(State, Id.size()), Id.str()); diff --git a/clang/lib/Tooling/Transformer/Stencil.cpp b/clang/lib/Tooling/Transformer/Stencil.cpp index 4dc3544bb06d..8b20ef34c3ff 100644 --- a/clang/lib/Tooling/Transformer/Stencil.cpp +++ b/clang/lib/Tooling/Transformer/Stencil.cpp @@ -27,14 +27,15 @@ using namespace clang; using namespace transformer; +using ast_matchers::BoundNodes; using ast_matchers::MatchFinder; using llvm::errc; using llvm::Error; using llvm::Expected; using llvm::StringError; -static llvm::Expected<DynTypedNode> -getNode(const ast_matchers::BoundNodes &Nodes, StringRef Id) { +static llvm::Expected<DynTypedNode> getNode(const BoundNodes &Nodes, + StringRef Id) { auto &NodesMap = Nodes.getMap(); auto It = NodesMap.find(Id); if (It == NodesMap.end()) @@ -366,6 +367,73 @@ public: } }; +class SelectBoundStencil : public clang::transformer::StencilInterface { + static bool containsNoNullStencils( + const std::vector<std::pair<std::string, Stencil>> &Cases) { + for (const auto &S : Cases) + if (S.second == nullptr) + return false; + return true; + } + +public: + SelectBoundStencil(std::vector<std::pair<std::string, Stencil>> Cases, + Stencil Default) + : CaseStencils(std::move(Cases)), DefaultStencil(std::move(Default)) { + assert(containsNoNullStencils(CaseStencils) && + "cases of selectBound may not be null"); + } + ~SelectBoundStencil() override{}; + + llvm::Error eval(const MatchFinder::MatchResult &match, + std::string *result) const override { + const BoundNodes::IDToNodeMap &NodeMap = match.Nodes.getMap(); + for (const auto &S : CaseStencils) { + if (NodeMap.count(S.first) > 0) { + return S.second->eval(match, result); + } + } + + if (DefaultStencil != nullptr) { + return DefaultStencil->eval(match, result); + } + + llvm::SmallVector<llvm::StringRef, 2> CaseIDs; + CaseIDs.reserve(CaseStencils.size()); + for (const auto &S : CaseStencils) + CaseIDs.emplace_back(S.first); + + return llvm::createStringError( + errc::result_out_of_range, + llvm::Twine("selectBound failed: no cases bound and no default: {") + + llvm::join(CaseIDs, ", ") + "}"); + } + + std::string toString() const override { + std::string Buffer; + llvm::raw_string_ostream Stream(Buffer); + Stream << "selectBound({"; + bool First = true; + for (const auto &S : CaseStencils) { + if (First) + First = false; + else + Stream << "}, "; + Stream << "{\"" << S.first << "\", " << S.second->toString(); + } + Stream << "}}"; + if (DefaultStencil != nullptr) { + Stream << ", " << DefaultStencil->toString(); + } + Stream << ")"; + return Stream.str(); + } + +private: + std::vector<std::pair<std::string, Stencil>> CaseStencils; + Stencil DefaultStencil; +}; + class SequenceStencil : public StencilInterface { std::vector<Stencil> Stencils; @@ -462,6 +530,13 @@ Stencil transformer::ifBound(StringRef Id, Stencil TrueStencil, std::move(FalseStencil)); } +Stencil transformer::selectBound( + std::vector<std::pair<std::string, Stencil>> CaseStencils, + Stencil DefaultStencil) { + return std::make_shared<SelectBoundStencil>(std::move(CaseStencils), + std::move(DefaultStencil)); +} + Stencil transformer::run(MatchConsumer<std::string> Fn) { return std::make_shared<RunStencil>(std::move(Fn)); } |
