FrontendActions_rewrite.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. //===--- FrontendActions.cpp ----------------------------------------------===//
  2. ///////////////////////////////////////////////////////////////////////////////
  3. // //
  4. // FrontendActions_rewrite.cpp //
  5. // Copyright (C) Microsoft Corporation. All rights reserved. //
  6. // This file is distributed under the University of Illinois Open Source //
  7. // License. See LICENSE.TXT for details. //
  8. // //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include "clang/Rewrite/Frontend/FrontendActions.h"
  11. #include "clang/AST/ASTConsumer.h"
  12. #include "clang/Basic/FileManager.h"
  13. #include "clang/Frontend/CompilerInstance.h"
  14. #include "clang/Frontend/FrontendActions.h"
  15. #include "clang/Frontend/FrontendDiagnostic.h"
  16. #include "clang/Frontend/Utils.h"
  17. #include "clang/Lex/Preprocessor.h"
  18. #include "clang/Parse/Parser.h"
  19. #include "clang/Rewrite/Frontend/ASTConsumers.h"
  20. #include "clang/Rewrite/Frontend/FixItRewriter.h"
  21. #include "clang/Rewrite/Frontend/Rewriters.h"
  22. #include "llvm/Support/FileSystem.h"
  23. #include "llvm/Support/Path.h"
  24. #include "llvm/Support/raw_ostream.h"
  25. #include <memory>
  26. using namespace clang;
  27. //===----------------------------------------------------------------------===//
  28. // AST Consumer Actions
  29. //===----------------------------------------------------------------------===//
  30. std::unique_ptr<ASTConsumer>
  31. HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
  32. if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
  33. return CreateHTMLPrinter(OS, CI.getPreprocessor());
  34. return nullptr;
  35. }
  36. FixItAction::FixItAction() {}
  37. FixItAction::~FixItAction() {}
  38. std::unique_ptr<ASTConsumer>
  39. FixItAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
  40. return llvm::make_unique<ASTConsumer>();
  41. }
  42. namespace {
  43. class FixItRewriteInPlace : public FixItOptions {
  44. public:
  45. FixItRewriteInPlace() { InPlace = true; }
  46. std::string RewriteFilename(const std::string &Filename, int &fd) override {
  47. llvm_unreachable("don't call RewriteFilename for inplace rewrites");
  48. }
  49. };
  50. class FixItActionSuffixInserter : public FixItOptions {
  51. std::string NewSuffix;
  52. public:
  53. FixItActionSuffixInserter(std::string NewSuffix, bool FixWhatYouCan)
  54. : NewSuffix(NewSuffix) {
  55. this->FixWhatYouCan = FixWhatYouCan;
  56. }
  57. std::string RewriteFilename(const std::string &Filename, int &fd) override {
  58. fd = -1;
  59. SmallString<128> Path(Filename);
  60. llvm::sys::path::replace_extension(Path,
  61. NewSuffix + llvm::sys::path::extension(Path));
  62. return Path.str();
  63. }
  64. };
  65. class FixItRewriteToTemp : public FixItOptions {
  66. public:
  67. std::string RewriteFilename(const std::string &Filename, int &fd) override {
  68. SmallString<128> Path;
  69. llvm::sys::fs::createTemporaryFile(llvm::sys::path::filename(Filename),
  70. llvm::sys::path::extension(Filename), fd,
  71. Path);
  72. return Path.str();
  73. }
  74. };
  75. } // end anonymous namespace
  76. bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
  77. StringRef Filename) {
  78. const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
  79. if (!FEOpts.FixItSuffix.empty()) {
  80. FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix,
  81. FEOpts.FixWhatYouCan));
  82. } else {
  83. FixItOpts.reset(new FixItRewriteInPlace);
  84. FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan;
  85. }
  86. Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
  87. CI.getLangOpts(), FixItOpts.get()));
  88. return true;
  89. }
  90. void FixItAction::EndSourceFileAction() {
  91. // Otherwise rewrite all files.
  92. Rewriter->WriteFixedFiles();
  93. }
  94. bool FixItRecompile::BeginInvocation(CompilerInstance &CI) {
  95. std::vector<std::pair<std::string, std::string> > RewrittenFiles;
  96. bool err = false;
  97. {
  98. const FrontendOptions &FEOpts = CI.getFrontendOpts();
  99. std::unique_ptr<FrontendAction> FixAction(new SyntaxOnlyAction());
  100. if (FixAction->BeginSourceFile(CI, FEOpts.Inputs[0])) {
  101. std::unique_ptr<FixItOptions> FixItOpts;
  102. if (FEOpts.FixToTemporaries)
  103. FixItOpts.reset(new FixItRewriteToTemp());
  104. else
  105. FixItOpts.reset(new FixItRewriteInPlace());
  106. FixItOpts->Silent = true;
  107. FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan;
  108. FixItOpts->FixOnlyWarnings = FEOpts.FixOnlyWarnings;
  109. FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(),
  110. CI.getLangOpts(), FixItOpts.get());
  111. FixAction->Execute();
  112. err = Rewriter.WriteFixedFiles(&RewrittenFiles);
  113. FixAction->EndSourceFile();
  114. CI.setSourceManager(nullptr);
  115. CI.setFileManager(nullptr);
  116. } else {
  117. err = true;
  118. }
  119. }
  120. if (err)
  121. return false;
  122. CI.getDiagnosticClient().clear();
  123. CI.getDiagnostics().Reset();
  124. PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
  125. PPOpts.RemappedFiles.insert(PPOpts.RemappedFiles.end(),
  126. RewrittenFiles.begin(), RewrittenFiles.end());
  127. PPOpts.RemappedFilesKeepOriginalName = false;
  128. return true;
  129. }
  130. #ifdef CLANG_ENABLE_OBJC_REWRITER
  131. std::unique_ptr<ASTConsumer>
  132. RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
  133. if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp")) {
  134. if (CI.getLangOpts().ObjCRuntime.isNonFragile())
  135. return CreateModernObjCRewriter(InFile, OS,
  136. CI.getDiagnostics(), CI.getLangOpts(),
  137. CI.getDiagnosticOpts().NoRewriteMacros,
  138. (CI.getCodeGenOpts().getDebugInfo() !=
  139. CodeGenOptions::NoDebugInfo));
  140. return CreateObjCRewriter(InFile, OS,
  141. CI.getDiagnostics(), CI.getLangOpts(),
  142. CI.getDiagnosticOpts().NoRewriteMacros);
  143. }
  144. return nullptr;
  145. }
  146. #endif
  147. //===----------------------------------------------------------------------===//
  148. // Preprocessor Actions
  149. //===----------------------------------------------------------------------===//
  150. void RewriteMacrosAction::ExecuteAction() {
  151. CompilerInstance &CI = getCompilerInstance();
  152. raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
  153. if (!OS) return;
  154. RewriteMacrosInInput(CI.getPreprocessor(), OS);
  155. }
  156. void RewriteTestAction::ExecuteAction() {
  157. CompilerInstance &CI = getCompilerInstance();
  158. raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
  159. if (!OS) return;
  160. DoRewriteTest(CI.getPreprocessor(), OS);
  161. }
  162. void RewriteIncludesAction::ExecuteAction() {
  163. CompilerInstance &CI = getCompilerInstance();
  164. raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
  165. if (!OS) return;
  166. RewriteIncludesInInput(CI.getPreprocessor(), OS,
  167. CI.getPreprocessorOutputOpts());
  168. }