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 10 #include "clang/Rewrite/FrontendActions.h" 11 #include "clang/AST/ASTConsumer.h" 12 #include "clang/Lex/Preprocessor.h" 13 #include "clang/Parse/Parser.h" 14 #include "clang/Basic/FileManager.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 using namespace clang; 25 26 //===----------------------------------------------------------------------===// 27 // AST Consumer Actions 28 //===----------------------------------------------------------------------===// 29 30 ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI, 31 StringRef InFile) { 32 if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile)) 33 return CreateHTMLPrinter(OS, CI.getPreprocessor()); 34 return 0; 35 } 36 37 FixItAction::FixItAction() {} 38 FixItAction::~FixItAction() {} 39 40 ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI, 41 StringRef InFile) { 42 return new ASTConsumer(); 43 } 44 45 namespace { 46 class FixItRewriteInPlace : public FixItOptions { 47 public: 48 std::string RewriteFilename(const std::string &Filename) { return Filename; } 49 }; 50 51 class FixItActionSuffixInserter : public FixItOptions { 52 std::string NewSuffix; 53 54 public: 55 FixItActionSuffixInserter(std::string NewSuffix, bool FixWhatYouCan) 56 : NewSuffix(NewSuffix) { 57 this->FixWhatYouCan = FixWhatYouCan; 58 } 59 60 std::string RewriteFilename(const std::string &Filename) { 61 llvm::SmallString<128> Path(Filename); 62 llvm::sys::path::replace_extension(Path, 63 NewSuffix + llvm::sys::path::extension(Path)); 64 return Path.str(); 65 } 66 }; 67 } // end anonymous namespace 68 69 bool FixItAction::BeginSourceFileAction(CompilerInstance &CI, 70 StringRef Filename) { 71 const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts(); 72 if (!FEOpts.FixItSuffix.empty()) { 73 FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix, 74 FEOpts.FixWhatYouCan)); 75 } else { 76 FixItOpts.reset(new FixItRewriteInPlace); 77 FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan; 78 } 79 Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(), 80 CI.getLangOpts(), FixItOpts.get())); 81 return true; 82 } 83 84 void FixItAction::EndSourceFileAction() { 85 // Otherwise rewrite all files. 86 Rewriter->WriteFixedFiles(); 87 } 88 89 //===----------------------------------------------------------------------===// 90 // Preprocessor Actions 91 //===----------------------------------------------------------------------===// 92 93 ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, 94 StringRef InFile) { 95 if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp")) 96 return CreateObjCRewriter(InFile, OS, 97 CI.getDiagnostics(), CI.getLangOpts(), 98 CI.getDiagnosticOpts().NoRewriteMacros); 99 return 0; 100 } 101 102 void RewriteMacrosAction::ExecuteAction() { 103 CompilerInstance &CI = getCompilerInstance(); 104 raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); 105 if (!OS) return; 106 107 RewriteMacrosInInput(CI.getPreprocessor(), OS); 108 } 109 110 void RewriteTestAction::ExecuteAction() { 111 CompilerInstance &CI = getCompilerInstance(); 112 raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile()); 113 if (!OS) return; 114 115 DoRewriteTest(CI.getPreprocessor(), OS); 116 } 117