FrontendActions.cpp 6.6 KB

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