1a7dea167SDimitry Andric //===--- Transformer.cpp - Transformer library implementation ---*- C++ -*-===// 2a7dea167SDimitry Andric // 3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a7dea167SDimitry Andric // 7a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8a7dea167SDimitry Andric 9a7dea167SDimitry Andric #include "clang/Tooling/Transformer/RewriteRule.h" 10*e8d8bef9SDimitry Andric #include "clang/AST/ASTTypeTraits.h" 11*e8d8bef9SDimitry Andric #include "clang/AST/Stmt.h" 12a7dea167SDimitry Andric #include "clang/ASTMatchers/ASTMatchFinder.h" 13a7dea167SDimitry Andric #include "clang/ASTMatchers/ASTMatchers.h" 14a7dea167SDimitry Andric #include "clang/Basic/SourceLocation.h" 15a7dea167SDimitry Andric #include "clang/Tooling/Transformer/SourceCode.h" 16a7dea167SDimitry Andric #include "llvm/ADT/Optional.h" 17a7dea167SDimitry Andric #include "llvm/ADT/StringRef.h" 18a7dea167SDimitry Andric #include "llvm/Support/Errc.h" 19a7dea167SDimitry Andric #include "llvm/Support/Error.h" 20a7dea167SDimitry Andric #include <map> 21a7dea167SDimitry Andric #include <string> 22a7dea167SDimitry Andric #include <utility> 23a7dea167SDimitry Andric #include <vector> 24a7dea167SDimitry Andric 25a7dea167SDimitry Andric using namespace clang; 26a7dea167SDimitry Andric using namespace transformer; 27a7dea167SDimitry Andric 28a7dea167SDimitry Andric using ast_matchers::MatchFinder; 29a7dea167SDimitry Andric using ast_matchers::internal::DynTypedMatcher; 30a7dea167SDimitry Andric 31a7dea167SDimitry Andric using MatchResult = MatchFinder::MatchResult; 32a7dea167SDimitry Andric 33*e8d8bef9SDimitry Andric const char transformer::RootID[] = "___root___"; 34*e8d8bef9SDimitry Andric 355ffd83dbSDimitry Andric static Expected<SmallVector<transformer::Edit, 1>> 365ffd83dbSDimitry Andric translateEdits(const MatchResult &Result, ArrayRef<ASTEdit> ASTEdits) { 375ffd83dbSDimitry Andric SmallVector<transformer::Edit, 1> Edits; 385ffd83dbSDimitry Andric for (const auto &E : ASTEdits) { 395ffd83dbSDimitry Andric Expected<CharSourceRange> Range = E.TargetRange(Result); 40a7dea167SDimitry Andric if (!Range) 41a7dea167SDimitry Andric return Range.takeError(); 42a7dea167SDimitry Andric llvm::Optional<CharSourceRange> EditRange = 43a7dea167SDimitry Andric tooling::getRangeForEdit(*Range, *Result.Context); 44a7dea167SDimitry Andric // FIXME: let user specify whether to treat this case as an error or ignore 45*e8d8bef9SDimitry Andric // it as is currently done. This behavior is problematic in that it hides 46*e8d8bef9SDimitry Andric // failures from bad ranges. Also, the behavior here differs from 47*e8d8bef9SDimitry Andric // `flatten`. Here, we abort (without error), whereas flatten, if it hits an 48*e8d8bef9SDimitry Andric // empty list, does not abort. As a result, `editList({A,B})` is not 49*e8d8bef9SDimitry Andric // equivalent to `flatten(edit(A), edit(B))`. The former will abort if `A` 50*e8d8bef9SDimitry Andric // produces a bad range, whereas the latter will simply ignore A. 51a7dea167SDimitry Andric if (!EditRange) 525ffd83dbSDimitry Andric return SmallVector<Edit, 0>(); 535ffd83dbSDimitry Andric auto Replacement = E.Replacement->eval(Result); 54a7dea167SDimitry Andric if (!Replacement) 55a7dea167SDimitry Andric return Replacement.takeError(); 56*e8d8bef9SDimitry Andric auto Metadata = E.Metadata(Result); 57*e8d8bef9SDimitry Andric if (!Metadata) 58*e8d8bef9SDimitry Andric return Metadata.takeError(); 595ffd83dbSDimitry Andric transformer::Edit T; 60*e8d8bef9SDimitry Andric T.Kind = E.Kind; 61a7dea167SDimitry Andric T.Range = *EditRange; 62a7dea167SDimitry Andric T.Replacement = std::move(*Replacement); 63*e8d8bef9SDimitry Andric T.Metadata = std::move(*Metadata); 645ffd83dbSDimitry Andric Edits.push_back(std::move(T)); 65a7dea167SDimitry Andric } 665ffd83dbSDimitry Andric return Edits; 67a7dea167SDimitry Andric } 68a7dea167SDimitry Andric 695ffd83dbSDimitry Andric EditGenerator transformer::editList(SmallVector<ASTEdit, 1> Edits) { 705ffd83dbSDimitry Andric return [Edits = std::move(Edits)](const MatchResult &Result) { 715ffd83dbSDimitry Andric return translateEdits(Result, Edits); 725ffd83dbSDimitry Andric }; 735ffd83dbSDimitry Andric } 745ffd83dbSDimitry Andric 755ffd83dbSDimitry Andric EditGenerator transformer::edit(ASTEdit Edit) { 765ffd83dbSDimitry Andric return [Edit = std::move(Edit)](const MatchResult &Result) { 775ffd83dbSDimitry Andric return translateEdits(Result, {Edit}); 785ffd83dbSDimitry Andric }; 795ffd83dbSDimitry Andric } 805ffd83dbSDimitry Andric 81*e8d8bef9SDimitry Andric EditGenerator transformer::noopEdit(RangeSelector Anchor) { 82*e8d8bef9SDimitry Andric return [Anchor = std::move(Anchor)](const MatchResult &Result) 83*e8d8bef9SDimitry Andric -> Expected<SmallVector<transformer::Edit, 1>> { 84*e8d8bef9SDimitry Andric Expected<CharSourceRange> Range = Anchor(Result); 85*e8d8bef9SDimitry Andric if (!Range) 86*e8d8bef9SDimitry Andric return Range.takeError(); 87*e8d8bef9SDimitry Andric // In case the range is inside a macro expansion, map the location back to a 88*e8d8bef9SDimitry Andric // "real" source location. 89*e8d8bef9SDimitry Andric SourceLocation Begin = 90*e8d8bef9SDimitry Andric Result.SourceManager->getSpellingLoc(Range->getBegin()); 91*e8d8bef9SDimitry Andric Edit E; 92*e8d8bef9SDimitry Andric // Implicitly, leave `E.Replacement` as the empty string. 93*e8d8bef9SDimitry Andric E.Kind = EditKind::Range; 94*e8d8bef9SDimitry Andric E.Range = CharSourceRange::getCharRange(Begin, Begin); 95*e8d8bef9SDimitry Andric return SmallVector<Edit, 1>{E}; 96*e8d8bef9SDimitry Andric }; 97*e8d8bef9SDimitry Andric } 98*e8d8bef9SDimitry Andric 99*e8d8bef9SDimitry Andric EditGenerator 100*e8d8bef9SDimitry Andric transformer::flattenVector(SmallVector<EditGenerator, 2> Generators) { 101*e8d8bef9SDimitry Andric if (Generators.size() == 1) 102*e8d8bef9SDimitry Andric return std::move(Generators[0]); 103*e8d8bef9SDimitry Andric return 104*e8d8bef9SDimitry Andric [Gs = std::move(Generators)]( 105*e8d8bef9SDimitry Andric const MatchResult &Result) -> llvm::Expected<SmallVector<Edit, 1>> { 106*e8d8bef9SDimitry Andric SmallVector<Edit, 1> AllEdits; 107*e8d8bef9SDimitry Andric for (const auto &G : Gs) { 108*e8d8bef9SDimitry Andric llvm::Expected<SmallVector<Edit, 1>> Edits = G(Result); 109*e8d8bef9SDimitry Andric if (!Edits) 110*e8d8bef9SDimitry Andric return Edits.takeError(); 111*e8d8bef9SDimitry Andric AllEdits.append(Edits->begin(), Edits->end()); 112*e8d8bef9SDimitry Andric } 113*e8d8bef9SDimitry Andric return AllEdits; 114*e8d8bef9SDimitry Andric }; 115*e8d8bef9SDimitry Andric } 116*e8d8bef9SDimitry Andric 1175ffd83dbSDimitry Andric ASTEdit transformer::changeTo(RangeSelector Target, TextGenerator Replacement) { 118a7dea167SDimitry Andric ASTEdit E; 1195ffd83dbSDimitry Andric E.TargetRange = std::move(Target); 120a7dea167SDimitry Andric E.Replacement = std::move(Replacement); 121a7dea167SDimitry Andric return E; 122a7dea167SDimitry Andric } 123a7dea167SDimitry Andric 124480093f4SDimitry Andric namespace { 125480093f4SDimitry Andric /// A \c TextGenerator that always returns a fixed string. 126480093f4SDimitry Andric class SimpleTextGenerator : public MatchComputation<std::string> { 127480093f4SDimitry Andric std::string S; 128480093f4SDimitry Andric 129480093f4SDimitry Andric public: 130480093f4SDimitry Andric SimpleTextGenerator(std::string S) : S(std::move(S)) {} 131480093f4SDimitry Andric llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &, 132480093f4SDimitry Andric std::string *Result) const override { 133480093f4SDimitry Andric Result->append(S); 134480093f4SDimitry Andric return llvm::Error::success(); 135480093f4SDimitry Andric } 136480093f4SDimitry Andric std::string toString() const override { 137480093f4SDimitry Andric return (llvm::Twine("text(\"") + S + "\")").str(); 138480093f4SDimitry Andric } 139480093f4SDimitry Andric }; 140480093f4SDimitry Andric } // namespace 141480093f4SDimitry Andric 142*e8d8bef9SDimitry Andric static TextGenerator makeText(std::string S) { 143*e8d8bef9SDimitry Andric return std::make_shared<SimpleTextGenerator>(std::move(S)); 144480093f4SDimitry Andric } 145480093f4SDimitry Andric 146*e8d8bef9SDimitry Andric ASTEdit transformer::remove(RangeSelector S) { 147*e8d8bef9SDimitry Andric return change(std::move(S), makeText("")); 148*e8d8bef9SDimitry Andric } 149*e8d8bef9SDimitry Andric 150*e8d8bef9SDimitry Andric static std::string formatHeaderPath(StringRef Header, IncludeFormat Format) { 151*e8d8bef9SDimitry Andric switch (Format) { 152*e8d8bef9SDimitry Andric case transformer::IncludeFormat::Quoted: 153*e8d8bef9SDimitry Andric return Header.str(); 154*e8d8bef9SDimitry Andric case transformer::IncludeFormat::Angled: 155*e8d8bef9SDimitry Andric return ("<" + Header + ">").str(); 156*e8d8bef9SDimitry Andric } 157*e8d8bef9SDimitry Andric llvm_unreachable("Unknown transformer::IncludeFormat enum"); 158*e8d8bef9SDimitry Andric } 159*e8d8bef9SDimitry Andric 160*e8d8bef9SDimitry Andric ASTEdit transformer::addInclude(RangeSelector Target, StringRef Header, 161*e8d8bef9SDimitry Andric IncludeFormat Format) { 162*e8d8bef9SDimitry Andric ASTEdit E; 163*e8d8bef9SDimitry Andric E.Kind = EditKind::AddInclude; 164*e8d8bef9SDimitry Andric E.TargetRange = Target; 165*e8d8bef9SDimitry Andric E.Replacement = makeText(formatHeaderPath(Header, Format)); 166*e8d8bef9SDimitry Andric return E; 167*e8d8bef9SDimitry Andric } 168*e8d8bef9SDimitry Andric 169*e8d8bef9SDimitry Andric RewriteRule transformer::makeRule(DynTypedMatcher M, EditGenerator Edits, 170a7dea167SDimitry Andric TextGenerator Explanation) { 171*e8d8bef9SDimitry Andric return RewriteRule{{RewriteRule::Case{std::move(M), std::move(Edits), 172*e8d8bef9SDimitry Andric std::move(Explanation)}}}; 173*e8d8bef9SDimitry Andric } 174*e8d8bef9SDimitry Andric 175*e8d8bef9SDimitry Andric namespace { 176*e8d8bef9SDimitry Andric 177*e8d8bef9SDimitry Andric /// Unconditionally binds the given node set before trying `InnerMatcher` and 178*e8d8bef9SDimitry Andric /// keeps the bound nodes on a successful match. 179*e8d8bef9SDimitry Andric template <typename T> 180*e8d8bef9SDimitry Andric class BindingsMatcher : public ast_matchers::internal::MatcherInterface<T> { 181*e8d8bef9SDimitry Andric ast_matchers::BoundNodes Nodes; 182*e8d8bef9SDimitry Andric const ast_matchers::internal::Matcher<T> InnerMatcher; 183*e8d8bef9SDimitry Andric 184*e8d8bef9SDimitry Andric public: 185*e8d8bef9SDimitry Andric explicit BindingsMatcher(ast_matchers::BoundNodes Nodes, 186*e8d8bef9SDimitry Andric ast_matchers::internal::Matcher<T> InnerMatcher) 187*e8d8bef9SDimitry Andric : Nodes(std::move(Nodes)), InnerMatcher(std::move(InnerMatcher)) {} 188*e8d8bef9SDimitry Andric 189*e8d8bef9SDimitry Andric bool matches( 190*e8d8bef9SDimitry Andric const T &Node, ast_matchers::internal::ASTMatchFinder *Finder, 191*e8d8bef9SDimitry Andric ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override { 192*e8d8bef9SDimitry Andric ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder); 193*e8d8bef9SDimitry Andric for (const auto &N : Nodes.getMap()) 194*e8d8bef9SDimitry Andric Result.setBinding(N.first, N.second); 195*e8d8bef9SDimitry Andric if (InnerMatcher.matches(Node, Finder, &Result)) { 196*e8d8bef9SDimitry Andric *Builder = std::move(Result); 197*e8d8bef9SDimitry Andric return true; 198*e8d8bef9SDimitry Andric } 199*e8d8bef9SDimitry Andric return false; 200*e8d8bef9SDimitry Andric } 201*e8d8bef9SDimitry Andric }; 202*e8d8bef9SDimitry Andric 203*e8d8bef9SDimitry Andric /// Matches nodes of type T that have at least one descendant node for which the 204*e8d8bef9SDimitry Andric /// given inner matcher matches. Will match for each descendant node that 205*e8d8bef9SDimitry Andric /// matches. Based on ForEachDescendantMatcher, but takes a dynamic matcher, 206*e8d8bef9SDimitry Andric /// instead of a static one, because it is used by RewriteRule, which carries 207*e8d8bef9SDimitry Andric /// (only top-level) dynamic matchers. 208*e8d8bef9SDimitry Andric template <typename T> 209*e8d8bef9SDimitry Andric class DynamicForEachDescendantMatcher 210*e8d8bef9SDimitry Andric : public ast_matchers::internal::MatcherInterface<T> { 211*e8d8bef9SDimitry Andric const DynTypedMatcher DescendantMatcher; 212*e8d8bef9SDimitry Andric 213*e8d8bef9SDimitry Andric public: 214*e8d8bef9SDimitry Andric explicit DynamicForEachDescendantMatcher(DynTypedMatcher DescendantMatcher) 215*e8d8bef9SDimitry Andric : DescendantMatcher(std::move(DescendantMatcher)) {} 216*e8d8bef9SDimitry Andric 217*e8d8bef9SDimitry Andric bool matches( 218*e8d8bef9SDimitry Andric const T &Node, ast_matchers::internal::ASTMatchFinder *Finder, 219*e8d8bef9SDimitry Andric ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override { 220*e8d8bef9SDimitry Andric return Finder->matchesDescendantOf( 221*e8d8bef9SDimitry Andric Node, this->DescendantMatcher, Builder, 222*e8d8bef9SDimitry Andric ast_matchers::internal::ASTMatchFinder::BK_All); 223*e8d8bef9SDimitry Andric } 224*e8d8bef9SDimitry Andric }; 225*e8d8bef9SDimitry Andric 226*e8d8bef9SDimitry Andric template <typename T> 227*e8d8bef9SDimitry Andric ast_matchers::internal::Matcher<T> 228*e8d8bef9SDimitry Andric forEachDescendantDynamically(ast_matchers::BoundNodes Nodes, 229*e8d8bef9SDimitry Andric DynTypedMatcher M) { 230*e8d8bef9SDimitry Andric return ast_matchers::internal::makeMatcher(new BindingsMatcher<T>( 231*e8d8bef9SDimitry Andric std::move(Nodes), 232*e8d8bef9SDimitry Andric ast_matchers::internal::makeMatcher( 233*e8d8bef9SDimitry Andric new DynamicForEachDescendantMatcher<T>(std::move(M))))); 234*e8d8bef9SDimitry Andric } 235*e8d8bef9SDimitry Andric 236*e8d8bef9SDimitry Andric class ApplyRuleCallback : public MatchFinder::MatchCallback { 237*e8d8bef9SDimitry Andric public: 238*e8d8bef9SDimitry Andric ApplyRuleCallback(RewriteRule Rule) : Rule(std::move(Rule)) {} 239*e8d8bef9SDimitry Andric 240*e8d8bef9SDimitry Andric template <typename T> 241*e8d8bef9SDimitry Andric void registerMatchers(const ast_matchers::BoundNodes &Nodes, 242*e8d8bef9SDimitry Andric MatchFinder *MF) { 243*e8d8bef9SDimitry Andric for (auto &Matcher : transformer::detail::buildMatchers(Rule)) 244*e8d8bef9SDimitry Andric MF->addMatcher(forEachDescendantDynamically<T>(Nodes, Matcher), this); 245*e8d8bef9SDimitry Andric } 246*e8d8bef9SDimitry Andric 247*e8d8bef9SDimitry Andric void run(const MatchFinder::MatchResult &Result) override { 248*e8d8bef9SDimitry Andric if (!Edits) 249*e8d8bef9SDimitry Andric return; 250*e8d8bef9SDimitry Andric transformer::RewriteRule::Case Case = 251*e8d8bef9SDimitry Andric transformer::detail::findSelectedCase(Result, Rule); 252*e8d8bef9SDimitry Andric auto Transformations = Case.Edits(Result); 253*e8d8bef9SDimitry Andric if (!Transformations) { 254*e8d8bef9SDimitry Andric Edits = Transformations.takeError(); 255*e8d8bef9SDimitry Andric return; 256*e8d8bef9SDimitry Andric } 257*e8d8bef9SDimitry Andric Edits->append(Transformations->begin(), Transformations->end()); 258*e8d8bef9SDimitry Andric } 259*e8d8bef9SDimitry Andric 260*e8d8bef9SDimitry Andric RewriteRule Rule; 261*e8d8bef9SDimitry Andric 262*e8d8bef9SDimitry Andric // Initialize to a non-error state. 263*e8d8bef9SDimitry Andric Expected<SmallVector<Edit, 1>> Edits = SmallVector<Edit, 1>(); 264*e8d8bef9SDimitry Andric }; 265*e8d8bef9SDimitry Andric } // namespace 266*e8d8bef9SDimitry Andric 267*e8d8bef9SDimitry Andric template <typename T> 268*e8d8bef9SDimitry Andric llvm::Expected<SmallVector<clang::transformer::Edit, 1>> 269*e8d8bef9SDimitry Andric rewriteDescendantsImpl(const T &Node, RewriteRule Rule, 270*e8d8bef9SDimitry Andric const MatchResult &Result) { 271*e8d8bef9SDimitry Andric ApplyRuleCallback Callback(std::move(Rule)); 272*e8d8bef9SDimitry Andric MatchFinder Finder; 273*e8d8bef9SDimitry Andric Callback.registerMatchers<T>(Result.Nodes, &Finder); 274*e8d8bef9SDimitry Andric Finder.match(Node, *Result.Context); 275*e8d8bef9SDimitry Andric return std::move(Callback.Edits); 276*e8d8bef9SDimitry Andric } 277*e8d8bef9SDimitry Andric 278*e8d8bef9SDimitry Andric llvm::Expected<SmallVector<clang::transformer::Edit, 1>> 279*e8d8bef9SDimitry Andric transformer::detail::rewriteDescendants(const Decl &Node, RewriteRule Rule, 280*e8d8bef9SDimitry Andric const MatchResult &Result) { 281*e8d8bef9SDimitry Andric return rewriteDescendantsImpl(Node, std::move(Rule), Result); 282*e8d8bef9SDimitry Andric } 283*e8d8bef9SDimitry Andric 284*e8d8bef9SDimitry Andric llvm::Expected<SmallVector<clang::transformer::Edit, 1>> 285*e8d8bef9SDimitry Andric transformer::detail::rewriteDescendants(const Stmt &Node, RewriteRule Rule, 286*e8d8bef9SDimitry Andric const MatchResult &Result) { 287*e8d8bef9SDimitry Andric return rewriteDescendantsImpl(Node, std::move(Rule), Result); 288*e8d8bef9SDimitry Andric } 289*e8d8bef9SDimitry Andric 290*e8d8bef9SDimitry Andric llvm::Expected<SmallVector<clang::transformer::Edit, 1>> 291*e8d8bef9SDimitry Andric transformer::detail::rewriteDescendants(const TypeLoc &Node, RewriteRule Rule, 292*e8d8bef9SDimitry Andric const MatchResult &Result) { 293*e8d8bef9SDimitry Andric return rewriteDescendantsImpl(Node, std::move(Rule), Result); 294*e8d8bef9SDimitry Andric } 295*e8d8bef9SDimitry Andric 296*e8d8bef9SDimitry Andric llvm::Expected<SmallVector<clang::transformer::Edit, 1>> 297*e8d8bef9SDimitry Andric transformer::detail::rewriteDescendants(const DynTypedNode &DNode, 298*e8d8bef9SDimitry Andric RewriteRule Rule, 299*e8d8bef9SDimitry Andric const MatchResult &Result) { 300*e8d8bef9SDimitry Andric if (const auto *Node = DNode.get<Decl>()) 301*e8d8bef9SDimitry Andric return rewriteDescendantsImpl(*Node, std::move(Rule), Result); 302*e8d8bef9SDimitry Andric if (const auto *Node = DNode.get<Stmt>()) 303*e8d8bef9SDimitry Andric return rewriteDescendantsImpl(*Node, std::move(Rule), Result); 304*e8d8bef9SDimitry Andric if (const auto *Node = DNode.get<TypeLoc>()) 305*e8d8bef9SDimitry Andric return rewriteDescendantsImpl(*Node, std::move(Rule), Result); 306*e8d8bef9SDimitry Andric 307*e8d8bef9SDimitry Andric return llvm::make_error<llvm::StringError>( 308*e8d8bef9SDimitry Andric llvm::errc::invalid_argument, 309*e8d8bef9SDimitry Andric "type unsupported for recursive rewriting, Kind=" + 310*e8d8bef9SDimitry Andric DNode.getNodeKind().asStringRef()); 311*e8d8bef9SDimitry Andric } 312*e8d8bef9SDimitry Andric 313*e8d8bef9SDimitry Andric EditGenerator transformer::rewriteDescendants(std::string NodeId, 314*e8d8bef9SDimitry Andric RewriteRule Rule) { 315*e8d8bef9SDimitry Andric return [NodeId = std::move(NodeId), 316*e8d8bef9SDimitry Andric Rule = std::move(Rule)](const MatchResult &Result) 317*e8d8bef9SDimitry Andric -> llvm::Expected<SmallVector<clang::transformer::Edit, 1>> { 318*e8d8bef9SDimitry Andric const ast_matchers::BoundNodes::IDToNodeMap &NodesMap = 319*e8d8bef9SDimitry Andric Result.Nodes.getMap(); 320*e8d8bef9SDimitry Andric auto It = NodesMap.find(NodeId); 321*e8d8bef9SDimitry Andric if (It == NodesMap.end()) 322*e8d8bef9SDimitry Andric return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument, 323*e8d8bef9SDimitry Andric "ID not bound: " + NodeId); 324*e8d8bef9SDimitry Andric return detail::rewriteDescendants(It->second, std::move(Rule), Result); 325*e8d8bef9SDimitry Andric }; 326a7dea167SDimitry Andric } 327a7dea167SDimitry Andric 328a7dea167SDimitry Andric void transformer::addInclude(RewriteRule &Rule, StringRef Header, 329a7dea167SDimitry Andric IncludeFormat Format) { 330a7dea167SDimitry Andric for (auto &Case : Rule.Cases) 331*e8d8bef9SDimitry Andric Case.Edits = flatten(std::move(Case.Edits), addInclude(Header, Format)); 332a7dea167SDimitry Andric } 333a7dea167SDimitry Andric 334a7dea167SDimitry Andric #ifndef NDEBUG 335a7dea167SDimitry Andric // Filters for supported matcher kinds. FIXME: Explicitly list the allowed kinds 336a7dea167SDimitry Andric // (all node matcher types except for `QualType` and `Type`), rather than just 337a7dea167SDimitry Andric // banning `QualType` and `Type`. 338a7dea167SDimitry Andric static bool hasValidKind(const DynTypedMatcher &M) { 339a7dea167SDimitry Andric return !M.canConvertTo<QualType>(); 340a7dea167SDimitry Andric } 341a7dea167SDimitry Andric #endif 342a7dea167SDimitry Andric 343a7dea167SDimitry Andric // Binds each rule's matcher to a unique (and deterministic) tag based on 3445ffd83dbSDimitry Andric // `TagBase` and the id paired with the case. All of the returned matchers have 3455ffd83dbSDimitry Andric // their traversal kind explicitly set, either based on a pre-set kind or to the 3465ffd83dbSDimitry Andric // provided `DefaultTraversalKind`. 347a7dea167SDimitry Andric static std::vector<DynTypedMatcher> taggedMatchers( 348a7dea167SDimitry Andric StringRef TagBase, 3495ffd83dbSDimitry Andric const SmallVectorImpl<std::pair<size_t, RewriteRule::Case>> &Cases, 350*e8d8bef9SDimitry Andric TraversalKind DefaultTraversalKind) { 351a7dea167SDimitry Andric std::vector<DynTypedMatcher> Matchers; 352a7dea167SDimitry Andric Matchers.reserve(Cases.size()); 353a7dea167SDimitry Andric for (const auto &Case : Cases) { 354a7dea167SDimitry Andric std::string Tag = (TagBase + Twine(Case.first)).str(); 355a7dea167SDimitry Andric // HACK: Many matchers are not bindable, so ensure that tryBind will work. 356a7dea167SDimitry Andric DynTypedMatcher BoundMatcher(Case.second.Matcher); 357a7dea167SDimitry Andric BoundMatcher.setAllowBind(true); 3585ffd83dbSDimitry Andric auto M = *BoundMatcher.tryBind(Tag); 3595ffd83dbSDimitry Andric Matchers.push_back(!M.getTraversalKind() 3605ffd83dbSDimitry Andric ? M.withTraversalKind(DefaultTraversalKind) 3615ffd83dbSDimitry Andric : std::move(M)); 362a7dea167SDimitry Andric } 363a7dea167SDimitry Andric return Matchers; 364a7dea167SDimitry Andric } 365a7dea167SDimitry Andric 366a7dea167SDimitry Andric // Simply gathers the contents of the various rules into a single rule. The 367a7dea167SDimitry Andric // actual work to combine these into an ordered choice is deferred to matcher 368a7dea167SDimitry Andric // registration. 369a7dea167SDimitry Andric RewriteRule transformer::applyFirst(ArrayRef<RewriteRule> Rules) { 370a7dea167SDimitry Andric RewriteRule R; 371a7dea167SDimitry Andric for (auto &Rule : Rules) 372a7dea167SDimitry Andric R.Cases.append(Rule.Cases.begin(), Rule.Cases.end()); 373a7dea167SDimitry Andric return R; 374a7dea167SDimitry Andric } 375a7dea167SDimitry Andric 376a7dea167SDimitry Andric std::vector<DynTypedMatcher> 377a7dea167SDimitry Andric transformer::detail::buildMatchers(const RewriteRule &Rule) { 378a7dea167SDimitry Andric // Map the cases into buckets of matchers -- one for each "root" AST kind, 379a7dea167SDimitry Andric // which guarantees that they can be combined in a single anyOf matcher. Each 380a7dea167SDimitry Andric // case is paired with an identifying number that is converted to a string id 381a7dea167SDimitry Andric // in `taggedMatchers`. 382a7dea167SDimitry Andric std::map<ASTNodeKind, SmallVector<std::pair<size_t, RewriteRule::Case>, 1>> 383a7dea167SDimitry Andric Buckets; 384a7dea167SDimitry Andric const SmallVectorImpl<RewriteRule::Case> &Cases = Rule.Cases; 385a7dea167SDimitry Andric for (int I = 0, N = Cases.size(); I < N; ++I) { 386a7dea167SDimitry Andric assert(hasValidKind(Cases[I].Matcher) && 387a7dea167SDimitry Andric "Matcher must be non-(Qual)Type node matcher"); 388a7dea167SDimitry Andric Buckets[Cases[I].Matcher.getSupportedKind()].emplace_back(I, Cases[I]); 389a7dea167SDimitry Andric } 390a7dea167SDimitry Andric 3915ffd83dbSDimitry Andric // Each anyOf explicitly controls the traversal kind. The anyOf itself is set 3925ffd83dbSDimitry Andric // to `TK_AsIs` to ensure no nodes are skipped, thereby deferring to the kind 3935ffd83dbSDimitry Andric // of the branches. Then, each branch is either left as is, if the kind is 394*e8d8bef9SDimitry Andric // already set, or explicitly set to `TK_AsIs`. We choose this setting because 395*e8d8bef9SDimitry Andric // it is the default interpretation of matchers. 396a7dea167SDimitry Andric std::vector<DynTypedMatcher> Matchers; 397a7dea167SDimitry Andric for (const auto &Bucket : Buckets) { 398a7dea167SDimitry Andric DynTypedMatcher M = DynTypedMatcher::constructVariadic( 399a7dea167SDimitry Andric DynTypedMatcher::VO_AnyOf, Bucket.first, 400*e8d8bef9SDimitry Andric taggedMatchers("Tag", Bucket.second, TK_AsIs)); 401a7dea167SDimitry Andric M.setAllowBind(true); 402a7dea167SDimitry Andric // `tryBind` is guaranteed to succeed, because `AllowBind` was set to true. 403*e8d8bef9SDimitry Andric Matchers.push_back(M.tryBind(RootID)->withTraversalKind(TK_AsIs)); 404a7dea167SDimitry Andric } 405a7dea167SDimitry Andric return Matchers; 406a7dea167SDimitry Andric } 407a7dea167SDimitry Andric 408a7dea167SDimitry Andric DynTypedMatcher transformer::detail::buildMatcher(const RewriteRule &Rule) { 409a7dea167SDimitry Andric std::vector<DynTypedMatcher> Ms = buildMatchers(Rule); 410a7dea167SDimitry Andric assert(Ms.size() == 1 && "Cases must have compatible matchers."); 411a7dea167SDimitry Andric return Ms[0]; 412a7dea167SDimitry Andric } 413a7dea167SDimitry Andric 414a7dea167SDimitry Andric SourceLocation transformer::detail::getRuleMatchLoc(const MatchResult &Result) { 415a7dea167SDimitry Andric auto &NodesMap = Result.Nodes.getMap(); 416*e8d8bef9SDimitry Andric auto Root = NodesMap.find(RootID); 417a7dea167SDimitry Andric assert(Root != NodesMap.end() && "Transformation failed: missing root node."); 418a7dea167SDimitry Andric llvm::Optional<CharSourceRange> RootRange = tooling::getRangeForEdit( 419a7dea167SDimitry Andric CharSourceRange::getTokenRange(Root->second.getSourceRange()), 420a7dea167SDimitry Andric *Result.Context); 421a7dea167SDimitry Andric if (RootRange) 422a7dea167SDimitry Andric return RootRange->getBegin(); 423a7dea167SDimitry Andric // The match doesn't have a coherent range, so fall back to the expansion 424a7dea167SDimitry Andric // location as the "beginning" of the match. 425a7dea167SDimitry Andric return Result.SourceManager->getExpansionLoc( 426a7dea167SDimitry Andric Root->second.getSourceRange().getBegin()); 427a7dea167SDimitry Andric } 428a7dea167SDimitry Andric 429a7dea167SDimitry Andric // Finds the case that was "selected" -- that is, whose matcher triggered the 430a7dea167SDimitry Andric // `MatchResult`. 431a7dea167SDimitry Andric const RewriteRule::Case & 432a7dea167SDimitry Andric transformer::detail::findSelectedCase(const MatchResult &Result, 433a7dea167SDimitry Andric const RewriteRule &Rule) { 434a7dea167SDimitry Andric if (Rule.Cases.size() == 1) 435a7dea167SDimitry Andric return Rule.Cases[0]; 436a7dea167SDimitry Andric 437a7dea167SDimitry Andric auto &NodesMap = Result.Nodes.getMap(); 438a7dea167SDimitry Andric for (size_t i = 0, N = Rule.Cases.size(); i < N; ++i) { 439a7dea167SDimitry Andric std::string Tag = ("Tag" + Twine(i)).str(); 440a7dea167SDimitry Andric if (NodesMap.find(Tag) != NodesMap.end()) 441a7dea167SDimitry Andric return Rule.Cases[i]; 442a7dea167SDimitry Andric } 443a7dea167SDimitry Andric llvm_unreachable("No tag found for this rule."); 444a7dea167SDimitry Andric } 445a7dea167SDimitry Andric 446*e8d8bef9SDimitry Andric const llvm::StringRef RewriteRule::RootID = ::clang::transformer::RootID; 447