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 static Expected<SmallVector<transformer::Edit, 1>> 34 translateEdits(const MatchResult &Result, ArrayRef<ASTEdit> ASTEdits) { 35 SmallVector<transformer::Edit, 1> Edits; 36 for (const auto &E : ASTEdits) { 37 Expected<CharSourceRange> Range = E.TargetRange(Result); 38 if (!Range) 39 return Range.takeError(); 40 llvm::Optional<CharSourceRange> EditRange = 41 tooling::getRangeForEdit(*Range, *Result.Context); 42 // FIXME: let user specify whether to treat this case as an error or ignore 43 // it as is currently done. 44 if (!EditRange) 45 return SmallVector<Edit, 0>(); 46 auto Replacement = E.Replacement->eval(Result); 47 if (!Replacement) 48 return Replacement.takeError(); 49 auto Metadata = E.Metadata(Result); 50 if (!Metadata) 51 return Metadata.takeError(); 52 transformer::Edit T; 53 T.Range = *EditRange; 54 T.Replacement = std::move(*Replacement); 55 T.Metadata = std::move(*Metadata); 56 Edits.push_back(std::move(T)); 57 } 58 return Edits; 59 } 60 61 EditGenerator transformer::editList(SmallVector<ASTEdit, 1> Edits) { 62 return [Edits = std::move(Edits)](const MatchResult &Result) { 63 return translateEdits(Result, Edits); 64 }; 65 } 66 67 EditGenerator transformer::edit(ASTEdit Edit) { 68 return [Edit = std::move(Edit)](const MatchResult &Result) { 69 return translateEdits(Result, {Edit}); 70 }; 71 } 72 73 EditGenerator 74 transformer::flattenVector(SmallVector<EditGenerator, 2> Generators) { 75 if (Generators.size() == 1) 76 return std::move(Generators[0]); 77 return 78 [Gs = std::move(Generators)]( 79 const MatchResult &Result) -> llvm::Expected<SmallVector<Edit, 1>> { 80 SmallVector<Edit, 1> AllEdits; 81 for (const auto &G : Gs) { 82 llvm::Expected<SmallVector<Edit, 1>> Edits = G(Result); 83 if (!Edits) 84 return Edits.takeError(); 85 AllEdits.append(Edits->begin(), Edits->end()); 86 } 87 return AllEdits; 88 }; 89 } 90 91 ASTEdit transformer::changeTo(RangeSelector Target, TextGenerator Replacement) { 92 ASTEdit E; 93 E.TargetRange = std::move(Target); 94 E.Replacement = std::move(Replacement); 95 return E; 96 } 97 98 namespace { 99 /// A \c TextGenerator that always returns a fixed string. 100 class SimpleTextGenerator : public MatchComputation<std::string> { 101 std::string S; 102 103 public: 104 SimpleTextGenerator(std::string S) : S(std::move(S)) {} 105 llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &, 106 std::string *Result) const override { 107 Result->append(S); 108 return llvm::Error::success(); 109 } 110 std::string toString() const override { 111 return (llvm::Twine("text(\"") + S + "\")").str(); 112 } 113 }; 114 } // namespace 115 116 ASTEdit transformer::remove(RangeSelector S) { 117 return change(std::move(S), std::make_shared<SimpleTextGenerator>("")); 118 } 119 120 RewriteRule transformer::makeRule(DynTypedMatcher M, EditGenerator Edits, 121 TextGenerator Explanation) { 122 return RewriteRule{{RewriteRule::Case{ 123 std::move(M), std::move(Edits), std::move(Explanation), {}}}}; 124 } 125 126 namespace { 127 128 /// Unconditionally binds the given node set before trying `InnerMatcher` and 129 /// keeps the bound nodes on a successful match. 130 template <typename T> 131 class BindingsMatcher : public ast_matchers::internal::MatcherInterface<T> { 132 ast_matchers::BoundNodes Nodes; 133 const ast_matchers::internal::Matcher<T> InnerMatcher; 134 135 public: 136 explicit BindingsMatcher(ast_matchers::BoundNodes Nodes, 137 ast_matchers::internal::Matcher<T> InnerMatcher) 138 : Nodes(std::move(Nodes)), InnerMatcher(std::move(InnerMatcher)) {} 139 140 bool matches( 141 const T &Node, ast_matchers::internal::ASTMatchFinder *Finder, 142 ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override { 143 ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder); 144 for (const auto &N : Nodes.getMap()) 145 Result.setBinding(N.first, N.second); 146 if (InnerMatcher.matches(Node, Finder, &Result)) { 147 *Builder = std::move(Result); 148 return true; 149 } 150 return false; 151 } 152 }; 153 154 /// Matches nodes of type T that have at least one descendant node for which the 155 /// given inner matcher matches. Will match for each descendant node that 156 /// matches. Based on ForEachDescendantMatcher, but takes a dynamic matcher, 157 /// instead of a static one, because it is used by RewriteRule, which carries 158 /// (only top-level) dynamic matchers. 159 template <typename T> 160 class DynamicForEachDescendantMatcher 161 : public ast_matchers::internal::MatcherInterface<T> { 162 const DynTypedMatcher DescendantMatcher; 163 164 public: 165 explicit DynamicForEachDescendantMatcher(DynTypedMatcher DescendantMatcher) 166 : DescendantMatcher(std::move(DescendantMatcher)) {} 167 168 bool matches( 169 const T &Node, ast_matchers::internal::ASTMatchFinder *Finder, 170 ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override { 171 return Finder->matchesDescendantOf( 172 Node, this->DescendantMatcher, Builder, 173 ast_matchers::internal::ASTMatchFinder::BK_All); 174 } 175 }; 176 177 template <typename T> 178 ast_matchers::internal::Matcher<T> 179 forEachDescendantDynamically(ast_matchers::BoundNodes Nodes, 180 DynTypedMatcher M) { 181 return ast_matchers::internal::makeMatcher(new BindingsMatcher<T>( 182 std::move(Nodes), 183 ast_matchers::internal::makeMatcher( 184 new DynamicForEachDescendantMatcher<T>(std::move(M))))); 185 } 186 187 class ApplyRuleCallback : public MatchFinder::MatchCallback { 188 public: 189 ApplyRuleCallback(RewriteRule Rule) : Rule(std::move(Rule)) {} 190 191 template <typename T> 192 void registerMatchers(const ast_matchers::BoundNodes &Nodes, 193 MatchFinder *MF) { 194 for (auto &Matcher : transformer::detail::buildMatchers(Rule)) 195 MF->addMatcher(forEachDescendantDynamically<T>(Nodes, Matcher), this); 196 } 197 198 void run(const MatchFinder::MatchResult &Result) override { 199 if (!Edits) 200 return; 201 transformer::RewriteRule::Case Case = 202 transformer::detail::findSelectedCase(Result, Rule); 203 auto Transformations = Case.Edits(Result); 204 if (!Transformations) { 205 Edits = Transformations.takeError(); 206 return; 207 } 208 Edits->append(Transformations->begin(), Transformations->end()); 209 } 210 211 RewriteRule Rule; 212 213 // Initialize to a non-error state. 214 Expected<SmallVector<Edit, 1>> Edits = SmallVector<Edit, 1>(); 215 }; 216 } // namespace 217 218 template <typename T> 219 llvm::Expected<SmallVector<clang::transformer::Edit, 1>> 220 rewriteDescendantsImpl(const T &Node, RewriteRule Rule, 221 const MatchResult &Result) { 222 ApplyRuleCallback Callback(std::move(Rule)); 223 MatchFinder Finder; 224 Callback.registerMatchers<T>(Result.Nodes, &Finder); 225 Finder.match(Node, *Result.Context); 226 return std::move(Callback.Edits); 227 } 228 229 EditGenerator transformer::rewriteDescendants(std::string NodeId, 230 RewriteRule Rule) { 231 // FIXME: warn or return error if `Rule` contains any `AddedIncludes`, since 232 // these will be dropped. 233 return [NodeId = std::move(NodeId), 234 Rule = std::move(Rule)](const MatchResult &Result) 235 -> llvm::Expected<SmallVector<clang::transformer::Edit, 1>> { 236 const ast_matchers::BoundNodes::IDToNodeMap &NodesMap = 237 Result.Nodes.getMap(); 238 auto It = NodesMap.find(NodeId); 239 if (It == NodesMap.end()) 240 return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument, 241 "ID not bound: " + NodeId); 242 if (auto *Node = It->second.get<Decl>()) 243 return rewriteDescendantsImpl(*Node, std::move(Rule), Result); 244 if (auto *Node = It->second.get<Stmt>()) 245 return rewriteDescendantsImpl(*Node, std::move(Rule), Result); 246 if (auto *Node = It->second.get<TypeLoc>()) 247 return rewriteDescendantsImpl(*Node, std::move(Rule), Result); 248 249 return llvm::make_error<llvm::StringError>( 250 llvm::errc::invalid_argument, 251 "type unsupported for recursive rewriting, ID=\"" + NodeId + 252 "\", Kind=" + It->second.getNodeKind().asStringRef()); 253 }; 254 } 255 256 void transformer::addInclude(RewriteRule &Rule, StringRef Header, 257 IncludeFormat Format) { 258 for (auto &Case : Rule.Cases) 259 Case.AddedIncludes.emplace_back(Header.str(), Format); 260 } 261 262 #ifndef NDEBUG 263 // Filters for supported matcher kinds. FIXME: Explicitly list the allowed kinds 264 // (all node matcher types except for `QualType` and `Type`), rather than just 265 // banning `QualType` and `Type`. 266 static bool hasValidKind(const DynTypedMatcher &M) { 267 return !M.canConvertTo<QualType>(); 268 } 269 #endif 270 271 // Binds each rule's matcher to a unique (and deterministic) tag based on 272 // `TagBase` and the id paired with the case. All of the returned matchers have 273 // their traversal kind explicitly set, either based on a pre-set kind or to the 274 // provided `DefaultTraversalKind`. 275 static std::vector<DynTypedMatcher> taggedMatchers( 276 StringRef TagBase, 277 const SmallVectorImpl<std::pair<size_t, RewriteRule::Case>> &Cases, 278 ast_type_traits::TraversalKind DefaultTraversalKind) { 279 std::vector<DynTypedMatcher> Matchers; 280 Matchers.reserve(Cases.size()); 281 for (const auto &Case : Cases) { 282 std::string Tag = (TagBase + Twine(Case.first)).str(); 283 // HACK: Many matchers are not bindable, so ensure that tryBind will work. 284 DynTypedMatcher BoundMatcher(Case.second.Matcher); 285 BoundMatcher.setAllowBind(true); 286 auto M = *BoundMatcher.tryBind(Tag); 287 Matchers.push_back(!M.getTraversalKind() 288 ? M.withTraversalKind(DefaultTraversalKind) 289 : std::move(M)); 290 } 291 return Matchers; 292 } 293 294 // Simply gathers the contents of the various rules into a single rule. The 295 // actual work to combine these into an ordered choice is deferred to matcher 296 // registration. 297 RewriteRule transformer::applyFirst(ArrayRef<RewriteRule> Rules) { 298 RewriteRule R; 299 for (auto &Rule : Rules) 300 R.Cases.append(Rule.Cases.begin(), Rule.Cases.end()); 301 return R; 302 } 303 304 std::vector<DynTypedMatcher> 305 transformer::detail::buildMatchers(const RewriteRule &Rule) { 306 // Map the cases into buckets of matchers -- one for each "root" AST kind, 307 // which guarantees that they can be combined in a single anyOf matcher. Each 308 // case is paired with an identifying number that is converted to a string id 309 // in `taggedMatchers`. 310 std::map<ASTNodeKind, SmallVector<std::pair<size_t, RewriteRule::Case>, 1>> 311 Buckets; 312 const SmallVectorImpl<RewriteRule::Case> &Cases = Rule.Cases; 313 for (int I = 0, N = Cases.size(); I < N; ++I) { 314 assert(hasValidKind(Cases[I].Matcher) && 315 "Matcher must be non-(Qual)Type node matcher"); 316 Buckets[Cases[I].Matcher.getSupportedKind()].emplace_back(I, Cases[I]); 317 } 318 319 // Each anyOf explicitly controls the traversal kind. The anyOf itself is set 320 // to `TK_AsIs` to ensure no nodes are skipped, thereby deferring to the kind 321 // of the branches. Then, each branch is either left as is, if the kind is 322 // already set, or explicitly set to `TK_IgnoreUnlessSpelledInSource`. We 323 // choose this setting, because we think it is the one most friendly to 324 // beginners, who are (largely) the target audience of Transformer. 325 std::vector<DynTypedMatcher> Matchers; 326 for (const auto &Bucket : Buckets) { 327 DynTypedMatcher M = DynTypedMatcher::constructVariadic( 328 DynTypedMatcher::VO_AnyOf, Bucket.first, 329 taggedMatchers("Tag", Bucket.second, TK_IgnoreUnlessSpelledInSource)); 330 M.setAllowBind(true); 331 // `tryBind` is guaranteed to succeed, because `AllowBind` was set to true. 332 Matchers.push_back( 333 M.tryBind(RewriteRule::RootID)->withTraversalKind(TK_AsIs)); 334 } 335 return Matchers; 336 } 337 338 DynTypedMatcher transformer::detail::buildMatcher(const RewriteRule &Rule) { 339 std::vector<DynTypedMatcher> Ms = buildMatchers(Rule); 340 assert(Ms.size() == 1 && "Cases must have compatible matchers."); 341 return Ms[0]; 342 } 343 344 SourceLocation transformer::detail::getRuleMatchLoc(const MatchResult &Result) { 345 auto &NodesMap = Result.Nodes.getMap(); 346 auto Root = NodesMap.find(RewriteRule::RootID); 347 assert(Root != NodesMap.end() && "Transformation failed: missing root node."); 348 llvm::Optional<CharSourceRange> RootRange = tooling::getRangeForEdit( 349 CharSourceRange::getTokenRange(Root->second.getSourceRange()), 350 *Result.Context); 351 if (RootRange) 352 return RootRange->getBegin(); 353 // The match doesn't have a coherent range, so fall back to the expansion 354 // location as the "beginning" of the match. 355 return Result.SourceManager->getExpansionLoc( 356 Root->second.getSourceRange().getBegin()); 357 } 358 359 // Finds the case that was "selected" -- that is, whose matcher triggered the 360 // `MatchResult`. 361 const RewriteRule::Case & 362 transformer::detail::findSelectedCase(const MatchResult &Result, 363 const RewriteRule &Rule) { 364 if (Rule.Cases.size() == 1) 365 return Rule.Cases[0]; 366 367 auto &NodesMap = Result.Nodes.getMap(); 368 for (size_t i = 0, N = Rule.Cases.size(); i < N; ++i) { 369 std::string Tag = ("Tag" + Twine(i)).str(); 370 if (NodesMap.find(Tag) != NodesMap.end()) 371 return Rule.Cases[i]; 372 } 373 llvm_unreachable("No tag found for this rule."); 374 } 375 376 constexpr llvm::StringLiteral RewriteRule::RootID; 377 378 TextGenerator tooling::text(std::string M) { 379 return std::make_shared<SimpleTextGenerator>(std::move(M)); 380 } 381