FrontendActions.cpp revision 243830
1158115Sume//===--- FrontendActions.cpp ----------------------------------------------===// 2158115Sume// 3158115Sume// The LLVM Compiler Infrastructure 4158115Sume// 5158115Sume// This file is distributed under the University of Illinois Open Source 6158115Sume// License. See LICENSE.TXT for details. 7158115Sume// 8158115Sume//===----------------------------------------------------------------------===// 9158115Sume 10158115Sume#include "clang/Rewrite/Frontend/FrontendActions.h" 11158115Sume#include "clang/AST/ASTConsumer.h" 12158115Sume#include "clang/Lex/Preprocessor.h" 13158115Sume#include "clang/Parse/Parser.h" 14158115Sume#include "clang/Basic/FileManager.h" 15158115Sume#include "clang/Frontend/FrontendActions.h" 16158115Sume#include "clang/Frontend/CompilerInstance.h" 17158115Sume#include "clang/Frontend/FrontendDiagnostic.h" 18158115Sume#include "clang/Frontend/Utils.h" 19158115Sume#include "clang/Rewrite/Frontend/ASTConsumers.h" 20158115Sume#include "clang/Rewrite/Frontend/FixItRewriter.h" 21158115Sume#include "clang/Rewrite/Frontend/Rewriters.h" 22158115Sume#include "llvm/ADT/OwningPtr.h" 23158115Sume#include "llvm/Support/raw_ostream.h" 24158115Sume#include "llvm/Support/Path.h" 25158115Sume#include "llvm/Support/FileSystem.h" 26158115Sume 27158115Sumeusing namespace clang; 28158115Sume 29158115Sume//===----------------------------------------------------------------------===// 30158115Sume// AST Consumer Actions 31158115Sume//===----------------------------------------------------------------------===// 32194093Sdes 33158115SumeASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI, 34158115Sume StringRef InFile) { 35158115Sume if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile)) 36194093Sdes return CreateHTMLPrinter(OS, CI.getPreprocessor()); 37158115Sume return 0; 38194093Sdes} 39158115Sume 40158115SumeFixItAction::FixItAction() {} 41158115SumeFixItAction::~FixItAction() {} 42158115Sume 43158115SumeASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI, 44194087Sdes StringRef InFile) { 45158115Sume return new ASTConsumer(); 46158115Sume} 47158115Sume 48158115Sumenamespace { 49158115Sumeclass FixItRewriteInPlace : public FixItOptions { 50158115Sumepublic: 51158115Sume std::string RewriteFilename(const std::string &Filename, int &fd) { 52158115Sume fd = -1; 53158115Sume return Filename; 54158115Sume } 55158115Sume}; 56158115Sume 57158115Sumeclass FixItActionSuffixInserter : public FixItOptions { 58158115Sume std::string NewSuffix; 59158115Sume 60158115Sumepublic: 61158115Sume FixItActionSuffixInserter(std::string NewSuffix, bool FixWhatYouCan) 62158115Sume : NewSuffix(NewSuffix) { 63158115Sume this->FixWhatYouCan = FixWhatYouCan; 64158115Sume } 65158115Sume 66158115Sume std::string RewriteFilename(const std::string &Filename, int &fd) { 67158115Sume fd = -1; 68158115Sume SmallString<128> Path(Filename); 69158115Sume llvm::sys::path::replace_extension(Path, 70158115Sume NewSuffix + llvm::sys::path::extension(Path)); 71158115Sume return Path.str(); 72158115Sume } 73158115Sume}; 74158115Sume 75158115Sumeclass FixItRewriteToTemp : public FixItOptions { 76158115Sumepublic: 77158115Sume std::string RewriteFilename(const std::string &Filename, int &fd) { 78158115Sume SmallString<128> Path; 79158115Sume Path = llvm::sys::path::filename(Filename); 80158115Sume Path += "-%%%%%%%%"; 81158115Sume Path += llvm::sys::path::extension(Filename); 82158115Sume SmallString<128> NewPath; 83158115Sume llvm::sys::fs::unique_file(Path.str(), fd, NewPath); 84158115Sume return NewPath.str(); 85158115Sume } 86158115Sume}; 87158115Sume} // end anonymous namespace 88158115Sume 89158115Sumebool FixItAction::BeginSourceFileAction(CompilerInstance &CI, 90158115Sume StringRef Filename) { 91158115Sume const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts(); 92158115Sume if (!FEOpts.FixItSuffix.empty()) { 93158115Sume FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix, 94158115Sume FEOpts.FixWhatYouCan)); 95158115Sume } else { 96158115Sume FixItOpts.reset(new FixItRewriteInPlace); 97158115Sume FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan; 98158115Sume } 99158115Sume Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(), 100158115Sume CI.getLangOpts(), FixItOpts.get())); 101158115Sume return true; 102158115Sume} 103158115Sume 104158115Sumevoid FixItAction::EndSourceFileAction() { 105158115Sume // Otherwise rewrite all files. 106158115Sume Rewriter->WriteFixedFiles(); 107158115Sume} 108158115Sume 109158115Sumebool FixItRecompile::BeginInvocation(CompilerInstance &CI) { 110158115Sume 111158115Sume std::vector<std::pair<std::string, std::string> > RewrittenFiles; 112158115Sume bool err = false; 113158115Sume { 114158115Sume const FrontendOptions &FEOpts = CI.getFrontendOpts(); 115158115Sume OwningPtr<FrontendAction> FixAction(new SyntaxOnlyAction()); 116158115Sume if (FixAction->BeginSourceFile(CI, FEOpts.Inputs[0])) { 117158115Sume OwningPtr<FixItOptions> FixItOpts; 118158115Sume if (FEOpts.FixToTemporaries) 119158115Sume FixItOpts.reset(new FixItRewriteToTemp()); 120158115Sume else 121158115Sume FixItOpts.reset(new FixItRewriteInPlace()); 122158115Sume FixItOpts->Silent = true; 123158115Sume FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan; 124158115Sume FixItOpts->FixOnlyWarnings = FEOpts.FixOnlyWarnings; 125158115Sume FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(), 126158115Sume CI.getLangOpts(), FixItOpts.get()); 127158115Sume FixAction->Execute(); 128158115Sume 129158115Sume err = Rewriter.WriteFixedFiles(&RewrittenFiles); 130158115Sume 131158115Sume FixAction->EndSourceFile(); 132158115Sume CI.setSourceManager(0); 133158115Sume CI.setFileManager(0); 134158115Sume } else { 135158115Sume err = true; 136158115Sume } 137158115Sume } 138158115Sume if (err) 139158115Sume return false; 140158115Sume CI.getDiagnosticClient().clear(); 141158115Sume CI.getDiagnostics().Reset(); 142158115Sume 143158115Sume PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); 144158115Sume PPOpts.RemappedFiles.insert(PPOpts.RemappedFiles.end(), 145158115Sume RewrittenFiles.begin(), RewrittenFiles.end()); 146158115Sume PPOpts.RemappedFilesKeepOriginalName = false; 147158115Sume 148158115Sume return true; 149158115Sume} 150158115Sume 151158115Sume//===----------------------------------------------------------------------===// 152158115Sume// Preprocessor Actions 153194104Sdes//===----------------------------------------------------------------------===// 154158115Sume 155158115SumeASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, 156158115Sume StringRef InFile) { 157158115Sume if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp")) { 158158115Sume if (CI.getLangOpts().ObjCRuntime.isNonFragile()) 159158115Sume return CreateModernObjCRewriter(InFile, OS, 160158115Sume CI.getDiagnostics(), CI.getLangOpts(), 161158115Sume CI.getDiagnosticOpts().NoRewriteMacros); 162158115Sume return CreateObjCRewriter(InFile, OS, 163158115Sume CI.getDiagnostics(), CI.getLangOpts(), 164158115Sume CI.getDiagnosticOpts().NoRewriteMacros); 165158115Sume } 166158115Sume return 0; 167158115Sume} 168158115Sume 169158115Sumevoid RewriteMacrosAction::ExecuteAction() { 170158115Sume CompilerInstance &CI = getCompilerInstance(); 171158115Sume raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); 172158115Sume if (!OS) return; 173158115Sume 174158115Sume RewriteMacrosInInput(CI.getPreprocessor(), OS); 175158115Sume} 176158115Sume 177158115Sumevoid RewriteTestAction::ExecuteAction() { 178158115Sume CompilerInstance &CI = getCompilerInstance(); 179158115Sume raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile()); 180158115Sume if (!OS) return; 181158115Sume 182158115Sume DoRewriteTest(CI.getPreprocessor(), OS); 183158115Sume} 184158115Sume 185158115Sumevoid RewriteIncludesAction::ExecuteAction() { 186194104Sdes CompilerInstance &CI = getCompilerInstance(); 187158115Sume raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); 188158115Sume if (!OS) return; 189158115Sume 190158115Sume RewriteIncludesInInput(CI.getPreprocessor(), OS, 191158115Sume CI.getPreprocessorOutputOpts()); 192158115Sume} 193158115Sume