FrontendActions.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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/FrontendActions.h"
  10. #include "clang/AST/ASTConsumer.h"
  11. #include "clang/Lex/Preprocessor.h"
  12. #include "clang/Parse/Parser.h"
  13. #include "clang/Basic/FileManager.h"
  14. #include "clang/Frontend/FrontendActions.h"
  15. #include "clang/Frontend/CompilerInstance.h"
  16. #include "clang/Frontend/FrontendDiagnostic.h"
  17. #include "clang/Frontend/Utils.h"
  18. #include "clang/Rewrite/ASTConsumers.h"
  19. #include "clang/Rewrite/FixItRewriter.h"
  20. #include "clang/Rewrite/Rewriters.h"
  21. #include "llvm/ADT/OwningPtr.h"
  22. #include "llvm/Support/raw_ostream.h"
  23. #include "llvm/Support/Path.h"
  24. #include "llvm/Support/FileSystem.h"
  25. using namespace clang;
  26. //===----------------------------------------------------------------------===//
  27. // AST Consumer Actions
  28. //===----------------------------------------------------------------------===//
  29. ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
  30. StringRef InFile) {
  31. if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
  32. return CreateHTMLPrinter(OS, CI.getPreprocessor());
  33. return 0;
  34. }
  35. FixItAction::FixItAction() {}
  36. FixItAction::~FixItAction() {}
  37. ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,
  38. StringRef InFile) {
  39. return new ASTConsumer();
  40. }
  41. namespace {
  42. class FixItRewriteInPlace : public FixItOptions {
  43. public:
  44. std::string RewriteFilename(const std::string &Filename, int &fd) {
  45. fd = -1;
  46. return Filename;
  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) {
  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) {
  67. SmallString<128> Path;
  68. Path = llvm::sys::path::filename(Filename);
  69. Path += "-%%%%%%%%";
  70. Path += llvm::sys::path::extension(Filename);
  71. SmallString<128> NewPath;
  72. llvm::sys::fs::unique_file(Path.str(), fd, NewPath);
  73. return NewPath.str();
  74. }
  75. };
  76. } // end anonymous namespace
  77. bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
  78. StringRef Filename) {
  79. const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
  80. if (!FEOpts.FixItSuffix.empty()) {
  81. FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix,
  82. FEOpts.FixWhatYouCan));
  83. } else {
  84. FixItOpts.reset(new FixItRewriteInPlace);
  85. FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan;
  86. }
  87. Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
  88. CI.getLangOpts(), FixItOpts.get()));
  89. return true;
  90. }
  91. void FixItAction::EndSourceFileAction() {
  92. // Otherwise rewrite all files.
  93. Rewriter->WriteFixedFiles();
  94. }
  95. bool FixItRecompile::BeginInvocation(CompilerInstance &CI) {
  96. std::vector<std::pair<std::string, std::string> > RewrittenFiles;
  97. bool err = false;
  98. {
  99. const FrontendOptions &FEOpts = CI.getFrontendOpts();
  100. OwningPtr<FrontendAction> FixAction(new SyntaxOnlyAction());
  101. if (FixAction->BeginSourceFile(CI, FEOpts.Inputs[0])) {
  102. OwningPtr<FixItOptions> FixItOpts;
  103. if (FEOpts.FixToTemporaries)
  104. FixItOpts.reset(new FixItRewriteToTemp());
  105. else
  106. FixItOpts.reset(new FixItRewriteInPlace());
  107. FixItOpts->Silent = true;
  108. FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan;
  109. FixItOpts->FixOnlyWarnings = FEOpts.FixOnlyWarnings;
  110. FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(),
  111. CI.getLangOpts(), FixItOpts.get());
  112. FixAction->Execute();
  113. err = Rewriter.WriteFixedFiles(&RewrittenFiles);
  114. FixAction->EndSourceFile();
  115. CI.setSourceManager(0);
  116. CI.setFileManager(0);
  117. } else {
  118. err = true;
  119. }
  120. }
  121. if (err)
  122. return false;
  123. CI.getDiagnosticClient().clear();
  124. CI.getDiagnostics().Reset();
  125. PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
  126. PPOpts.RemappedFiles.insert(PPOpts.RemappedFiles.end(),
  127. RewrittenFiles.begin(), RewrittenFiles.end());
  128. PPOpts.RemappedFilesKeepOriginalName = false;
  129. return true;
  130. }
  131. //===----------------------------------------------------------------------===//
  132. // Preprocessor Actions
  133. //===----------------------------------------------------------------------===//
  134. ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI,
  135. StringRef InFile) {
  136. if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp"))
  137. return CreateObjCRewriter(InFile, OS,
  138. CI.getDiagnostics(), CI.getLangOpts(),
  139. CI.getDiagnosticOpts().NoRewriteMacros);
  140. return 0;
  141. }
  142. void RewriteMacrosAction::ExecuteAction() {
  143. CompilerInstance &CI = getCompilerInstance();
  144. raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
  145. if (!OS) return;
  146. RewriteMacrosInInput(CI.getPreprocessor(), OS);
  147. }
  148. void RewriteTestAction::ExecuteAction() {
  149. CompilerInstance &CI = getCompilerInstance();
  150. raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
  151. if (!OS) return;
  152. DoRewriteTest(CI.getPreprocessor(), OS);
  153. }