1169689Skan//===--- FrontendActions.cpp ----------------------------------------------===// 2169689Skan// 3169689Skan// The LLVM Compiler Infrastructure 4169689Skan// 5169689Skan// This file is distributed under the University of Illinois Open Source 6169689Skan// License. See LICENSE.TXT for details. 7169689Skan// 8169689Skan//===----------------------------------------------------------------------===// 9169689Skan 10169689Skan#include "clang/Rewrite/Frontend/FrontendActions.h" 11169689Skan#include "clang/AST/ASTConsumer.h" 12169689Skan#include "clang/Basic/FileManager.h" 13169689Skan#include "clang/Frontend/CompilerInstance.h" 14169689Skan#include "clang/Frontend/FrontendActions.h" 15169689Skan#include "clang/Frontend/FrontendDiagnostic.h" 16169689Skan#include "clang/Frontend/Utils.h" 17169689Skan#include "clang/Lex/Preprocessor.h" 18169689Skan#include "clang/Parse/Parser.h" 19169689Skan#include "clang/Rewrite/Frontend/ASTConsumers.h" 20169689Skan#include "clang/Rewrite/Frontend/FixItRewriter.h" 21169689Skan#include "clang/Rewrite/Frontend/Rewriters.h" 22169689Skan#include "llvm/ADT/OwningPtr.h" 23169689Skan#include "llvm/Support/FileSystem.h" 24169689Skan#include "llvm/Support/Path.h" 25169689Skan#include "llvm/Support/raw_ostream.h" 26169689Skan 27169689Skanusing namespace clang; 28169689Skan 29169689Skan//===----------------------------------------------------------------------===// 30169689Skan// AST Consumer Actions 31169689Skan//===----------------------------------------------------------------------===// 32169689Skan 33169689SkanASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI, 34169689Skan StringRef InFile) { 35169689Skan if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile)) 36169689Skan return CreateHTMLPrinter(OS, CI.getPreprocessor()); 37169689Skan return 0; 38169689Skan} 39169689Skan 40169689SkanFixItAction::FixItAction() {} 41169689SkanFixItAction::~FixItAction() {} 42169689Skan 43169689SkanASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI, 44169689Skan StringRef InFile) { 45169689Skan return new ASTConsumer(); 46169689Skan} 47169689Skan 48169689Skannamespace { 49169689Skanclass FixItRewriteInPlace : public FixItOptions { 50169689Skanpublic: 51169689Skan std::string RewriteFilename(const std::string &Filename, int &fd) { 52169689Skan fd = -1; 53169689Skan return Filename; 54169689Skan } 55169689Skan}; 56169689Skan 57169689Skanclass FixItActionSuffixInserter : public FixItOptions { 58169689Skan std::string NewSuffix; 59169689Skan 60169689Skanpublic: 61169689Skan FixItActionSuffixInserter(std::string NewSuffix, bool FixWhatYouCan) 62169689Skan : NewSuffix(NewSuffix) { 63169689Skan this->FixWhatYouCan = FixWhatYouCan; 64169689Skan } 65169689Skan 66169689Skan std::string RewriteFilename(const std::string &Filename, int &fd) { 67169689Skan fd = -1; 68169689Skan SmallString<128> Path(Filename); 69169689Skan llvm::sys::path::replace_extension(Path, 70169689Skan NewSuffix + llvm::sys::path::extension(Path)); 71169689Skan return Path.str(); 72169689Skan } 73169689Skan}; 74169689Skan 75169689Skanclass FixItRewriteToTemp : public FixItOptions { 76169689Skanpublic: 77169689Skan std::string RewriteFilename(const std::string &Filename, int &fd) { 78 SmallString<128> Path; 79 llvm::sys::fs::createTemporaryFile(llvm::sys::path::filename(Filename), 80 llvm::sys::path::extension(Filename), fd, 81 Path); 82 return Path.str(); 83 } 84}; 85} // end anonymous namespace 86 87bool FixItAction::BeginSourceFileAction(CompilerInstance &CI, 88 StringRef Filename) { 89 const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts(); 90 if (!FEOpts.FixItSuffix.empty()) { 91 FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix, 92 FEOpts.FixWhatYouCan)); 93 } else { 94 FixItOpts.reset(new FixItRewriteInPlace); 95 FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan; 96 } 97 Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(), 98 CI.getLangOpts(), FixItOpts.get())); 99 return true; 100} 101 102void FixItAction::EndSourceFileAction() { 103 // Otherwise rewrite all files. 104 Rewriter->WriteFixedFiles(); 105} 106 107bool FixItRecompile::BeginInvocation(CompilerInstance &CI) { 108 109 std::vector<std::pair<std::string, std::string> > RewrittenFiles; 110 bool err = false; 111 { 112 const FrontendOptions &FEOpts = CI.getFrontendOpts(); 113 OwningPtr<FrontendAction> FixAction(new SyntaxOnlyAction()); 114 if (FixAction->BeginSourceFile(CI, FEOpts.Inputs[0])) { 115 OwningPtr<FixItOptions> FixItOpts; 116 if (FEOpts.FixToTemporaries) 117 FixItOpts.reset(new FixItRewriteToTemp()); 118 else 119 FixItOpts.reset(new FixItRewriteInPlace()); 120 FixItOpts->Silent = true; 121 FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan; 122 FixItOpts->FixOnlyWarnings = FEOpts.FixOnlyWarnings; 123 FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(), 124 CI.getLangOpts(), FixItOpts.get()); 125 FixAction->Execute(); 126 127 err = Rewriter.WriteFixedFiles(&RewrittenFiles); 128 129 FixAction->EndSourceFile(); 130 CI.setSourceManager(0); 131 CI.setFileManager(0); 132 } else { 133 err = true; 134 } 135 } 136 if (err) 137 return false; 138 CI.getDiagnosticClient().clear(); 139 CI.getDiagnostics().Reset(); 140 141 PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); 142 PPOpts.RemappedFiles.insert(PPOpts.RemappedFiles.end(), 143 RewrittenFiles.begin(), RewrittenFiles.end()); 144 PPOpts.RemappedFilesKeepOriginalName = false; 145 146 return true; 147} 148 149//===----------------------------------------------------------------------===// 150// Preprocessor Actions 151//===----------------------------------------------------------------------===// 152 153ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, 154 StringRef InFile) { 155 if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp")) { 156 if (CI.getLangOpts().ObjCRuntime.isNonFragile()) 157 return CreateModernObjCRewriter(InFile, OS, 158 CI.getDiagnostics(), CI.getLangOpts(), 159 CI.getDiagnosticOpts().NoRewriteMacros, 160 (CI.getCodeGenOpts().getDebugInfo() != 161 CodeGenOptions::NoDebugInfo)); 162 return CreateObjCRewriter(InFile, OS, 163 CI.getDiagnostics(), CI.getLangOpts(), 164 CI.getDiagnosticOpts().NoRewriteMacros); 165 } 166 return 0; 167} 168 169void RewriteMacrosAction::ExecuteAction() { 170 CompilerInstance &CI = getCompilerInstance(); 171 raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); 172 if (!OS) return; 173 174 RewriteMacrosInInput(CI.getPreprocessor(), OS); 175} 176 177void RewriteTestAction::ExecuteAction() { 178 CompilerInstance &CI = getCompilerInstance(); 179 raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile()); 180 if (!OS) return; 181 182 DoRewriteTest(CI.getPreprocessor(), OS); 183} 184 185void RewriteIncludesAction::ExecuteAction() { 186 CompilerInstance &CI = getCompilerInstance(); 187 raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); 188 if (!OS) return; 189 190 RewriteIncludesInInput(CI.getPreprocessor(), OS, 191 CI.getPreprocessorOutputOpts()); 192} 193