Refactoring.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. //===--- Refactoring.cpp - Framework for clang refactoring tools ----------===//
  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. // Implements tools to support refactorings.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "clang/Tooling/Refactoring.h"
  13. #include "clang/Basic/DiagnosticOptions.h"
  14. #include "clang/Basic/FileManager.h"
  15. #include "clang/Basic/SourceManager.h"
  16. #include "clang/Format/Format.h"
  17. #include "clang/Frontend/TextDiagnosticPrinter.h"
  18. #include "clang/Lex/Lexer.h"
  19. #include "clang/Rewrite/Core/Rewriter.h"
  20. #include "llvm/Support/Path.h"
  21. #include "llvm/Support/raw_os_ostream.h"
  22. namespace clang {
  23. namespace tooling {
  24. RefactoringTool::RefactoringTool(
  25. const CompilationDatabase &Compilations, ArrayRef<std::string> SourcePaths,
  26. std::shared_ptr<PCHContainerOperations> PCHContainerOps)
  27. : ClangTool(Compilations, SourcePaths, std::move(PCHContainerOps)) {}
  28. std::map<std::string, Replacements> &RefactoringTool::getReplacements() {
  29. return FileToReplaces;
  30. }
  31. int RefactoringTool::runAndSave(FrontendActionFactory *ActionFactory) {
  32. if (int Result = run(ActionFactory)) {
  33. return Result;
  34. }
  35. LangOptions DefaultLangOptions;
  36. IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  37. TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), &*DiagOpts);
  38. DiagnosticsEngine Diagnostics(
  39. IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
  40. &*DiagOpts, &DiagnosticPrinter, false);
  41. SourceManager Sources(Diagnostics, getFiles());
  42. Rewriter Rewrite(Sources, DefaultLangOptions);
  43. if (!applyAllReplacements(Rewrite)) {
  44. llvm::errs() << "Skipped some replacements.\n";
  45. }
  46. return saveRewrittenFiles(Rewrite);
  47. }
  48. bool RefactoringTool::applyAllReplacements(Rewriter &Rewrite) {
  49. bool Result = true;
  50. for (const auto &Entry : groupReplacementsByFile(
  51. Rewrite.getSourceMgr().getFileManager(), FileToReplaces))
  52. Result = tooling::applyAllReplacements(Entry.second, Rewrite) && Result;
  53. return Result;
  54. }
  55. int RefactoringTool::saveRewrittenFiles(Rewriter &Rewrite) {
  56. return Rewrite.overwriteChangedFiles() ? 1 : 0;
  57. }
  58. bool formatAndApplyAllReplacements(
  59. const std::map<std::string, Replacements> &FileToReplaces,
  60. Rewriter &Rewrite, StringRef Style) {
  61. SourceManager &SM = Rewrite.getSourceMgr();
  62. FileManager &Files = SM.getFileManager();
  63. bool Result = true;
  64. for (const auto &FileAndReplaces : groupReplacementsByFile(
  65. Rewrite.getSourceMgr().getFileManager(), FileToReplaces)) {
  66. const std::string &FilePath = FileAndReplaces.first;
  67. auto &CurReplaces = FileAndReplaces.second;
  68. const FileEntry *Entry = nullptr;
  69. if (auto File = Files.getFile(FilePath))
  70. Entry = *File;
  71. FileID ID = SM.getOrCreateFileID(Entry, SrcMgr::C_User);
  72. StringRef Code = SM.getBufferData(ID);
  73. auto CurStyle = format::getStyle(Style, FilePath, "LLVM");
  74. if (!CurStyle) {
  75. llvm::errs() << llvm::toString(CurStyle.takeError()) << "\n";
  76. return false;
  77. }
  78. auto NewReplacements =
  79. format::formatReplacements(Code, CurReplaces, *CurStyle);
  80. if (!NewReplacements) {
  81. llvm::errs() << llvm::toString(NewReplacements.takeError()) << "\n";
  82. return false;
  83. }
  84. Result = applyAllReplacements(*NewReplacements, Rewrite) && Result;
  85. }
  86. return Result;
  87. }
  88. } // end namespace tooling
  89. } // end namespace clang