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/Transformer.h" 10 #include "clang/ASTMatchers/ASTMatchFinder.h" 11 #include "clang/ASTMatchers/ASTMatchersInternal.h" 12 #include "clang/Basic/SourceLocation.h" 13 #include "clang/Tooling/Refactoring/AtomicChange.h" 14 #include "llvm/Support/Error.h" 15 #include <map> 16 #include <utility> 17 #include <vector> 18 19 using namespace clang; 20 using namespace tooling; 21 22 using ast_matchers::MatchFinder; 23 24 void Transformer::registerMatchers(MatchFinder *MatchFinder) { 25 for (auto &Matcher : transformer::detail::buildMatchers(Rule)) 26 MatchFinder->addDynamicMatcher(Matcher, this); 27 } 28 29 void Transformer::run(const MatchFinder::MatchResult &Result) { 30 if (Result.Context->getDiagnostics().hasErrorOccurred()) 31 return; 32 33 transformer::RewriteRule::Case Case = 34 transformer::detail::findSelectedCase(Result, Rule); 35 auto Transformations = Case.Edits(Result); 36 if (!Transformations) { 37 Consumer(Transformations.takeError()); 38 return; 39 } 40 41 if (Transformations->empty()) 42 return; 43 44 // Group the transformations, by file, into AtomicChanges, each anchored by 45 // the location of the first change in that file. 46 std::map<FileID, AtomicChange> ChangesByFileID; 47 for (const auto &T : *Transformations) { 48 auto ID = Result.SourceManager->getFileID(T.Range.getBegin()); 49 auto Iter = ChangesByFileID 50 .emplace(ID, AtomicChange(*Result.SourceManager, 51 T.Range.getBegin(), T.Metadata)) 52 .first; 53 auto &AC = Iter->second; 54 switch (T.Kind) { 55 case transformer::EditKind::Range: 56 if (auto Err = 57 AC.replace(*Result.SourceManager, T.Range, T.Replacement)) { 58 Consumer(std::move(Err)); 59 return; 60 } 61 break; 62 case transformer::EditKind::AddInclude: 63 AC.addHeader(T.Replacement); 64 break; 65 } 66 } 67 68 for (auto &IDChangePair : ChangesByFileID) 69 Consumer(std::move(IDChangePair.second)); 70 } 71