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