Transformer.cpp 2.3 KB

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