clang API Documentation

Rewrite/FrontendActions.cpp
Go to the documentation of this file.
00001 //===--- FrontendActions.cpp ----------------------------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "clang/Rewrite/FrontendActions.h"
00011 #include "clang/AST/ASTConsumer.h"
00012 #include "clang/Lex/Preprocessor.h"
00013 #include "clang/Parse/Parser.h"
00014 #include "clang/Basic/FileManager.h"
00015 #include "clang/Frontend/FrontendActions.h"
00016 #include "clang/Frontend/CompilerInstance.h"
00017 #include "clang/Frontend/FrontendDiagnostic.h"
00018 #include "clang/Frontend/Utils.h"
00019 #include "clang/Rewrite/ASTConsumers.h"
00020 #include "clang/Rewrite/FixItRewriter.h"
00021 #include "clang/Rewrite/Rewriters.h"
00022 #include "llvm/ADT/OwningPtr.h"
00023 #include "llvm/Support/raw_ostream.h"
00024 #include "llvm/Support/Path.h"
00025 #include "llvm/Support/FileSystem.h"
00026 
00027 using namespace clang;
00028 
00029 //===----------------------------------------------------------------------===//
00030 // AST Consumer Actions
00031 //===----------------------------------------------------------------------===//
00032 
00033 ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
00034                                                 StringRef InFile) {
00035   if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
00036     return CreateHTMLPrinter(OS, CI.getPreprocessor());
00037   return 0;
00038 }
00039 
00040 FixItAction::FixItAction() {}
00041 FixItAction::~FixItAction() {}
00042 
00043 ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,
00044                                             StringRef InFile) {
00045   return new ASTConsumer();
00046 }
00047 
00048 namespace {
00049 class FixItRewriteInPlace : public FixItOptions {
00050 public:
00051   std::string RewriteFilename(const std::string &Filename, int &fd) {
00052     fd = -1;
00053     return Filename;
00054   }
00055 };
00056 
00057 class FixItActionSuffixInserter : public FixItOptions {
00058   std::string NewSuffix;
00059 
00060 public:
00061   FixItActionSuffixInserter(std::string NewSuffix, bool FixWhatYouCan)
00062     : NewSuffix(NewSuffix) {
00063       this->FixWhatYouCan = FixWhatYouCan;
00064   }
00065 
00066   std::string RewriteFilename(const std::string &Filename, int &fd) {
00067     fd = -1;
00068     SmallString<128> Path(Filename);
00069     llvm::sys::path::replace_extension(Path,
00070       NewSuffix + llvm::sys::path::extension(Path));
00071     return Path.str();
00072   }
00073 };
00074 
00075 class FixItRewriteToTemp : public FixItOptions {
00076 public:
00077   std::string RewriteFilename(const std::string &Filename, int &fd) {
00078     SmallString<128> Path;
00079     Path = llvm::sys::path::filename(Filename);
00080     Path += "-%%%%%%%%";
00081     Path += llvm::sys::path::extension(Filename);
00082     SmallString<128> NewPath;
00083     llvm::sys::fs::unique_file(Path.str(), fd, NewPath);
00084     return NewPath.str();
00085   }
00086 };
00087 } // end anonymous namespace
00088 
00089 bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
00090                                         StringRef Filename) {
00091   const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
00092   if (!FEOpts.FixItSuffix.empty()) {
00093     FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix,
00094                                                   FEOpts.FixWhatYouCan));
00095   } else {
00096     FixItOpts.reset(new FixItRewriteInPlace);
00097     FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan;
00098   }
00099   Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
00100                                    CI.getLangOpts(), FixItOpts.get()));
00101   return true;
00102 }
00103 
00104 void FixItAction::EndSourceFileAction() {
00105   // Otherwise rewrite all files.
00106   Rewriter->WriteFixedFiles();
00107 }
00108 
00109 bool FixItRecompile::BeginInvocation(CompilerInstance &CI) {
00110 
00111   std::vector<std::pair<std::string, std::string> > RewrittenFiles;
00112   bool err = false;
00113   {
00114     const FrontendOptions &FEOpts = CI.getFrontendOpts();
00115     OwningPtr<FrontendAction> FixAction(new SyntaxOnlyAction());
00116     if (FixAction->BeginSourceFile(CI, FEOpts.Inputs[0])) {
00117       OwningPtr<FixItOptions> FixItOpts;
00118       if (FEOpts.FixToTemporaries)
00119         FixItOpts.reset(new FixItRewriteToTemp());
00120       else
00121         FixItOpts.reset(new FixItRewriteInPlace());
00122       FixItOpts->Silent = true;
00123       FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan;
00124       FixItOpts->FixOnlyWarnings = FEOpts.FixOnlyWarnings;
00125       FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(),
00126                              CI.getLangOpts(), FixItOpts.get());
00127       FixAction->Execute();
00128   
00129       err = Rewriter.WriteFixedFiles(&RewrittenFiles);
00130     
00131       FixAction->EndSourceFile();
00132       CI.setSourceManager(0);
00133       CI.setFileManager(0);
00134     } else {
00135       err = true;
00136     }
00137   }
00138   if (err)
00139     return false;
00140   CI.getDiagnosticClient().clear();
00141   CI.getDiagnostics().Reset();
00142 
00143   PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
00144   PPOpts.RemappedFiles.insert(PPOpts.RemappedFiles.end(),
00145                               RewrittenFiles.begin(), RewrittenFiles.end());
00146   PPOpts.RemappedFilesKeepOriginalName = false;
00147 
00148   return true;
00149 }
00150 
00151 //===----------------------------------------------------------------------===//
00152 // Preprocessor Actions
00153 //===----------------------------------------------------------------------===//
00154 
00155 ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI,
00156                                                   StringRef InFile) {
00157   if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp")) {
00158     if (CI.getLangOpts().ObjCNonFragileABI)
00159       return CreateModernObjCRewriter(InFile, OS,
00160                                 CI.getDiagnostics(), CI.getLangOpts(),
00161                                 CI.getDiagnosticOpts().NoRewriteMacros);
00162     return CreateObjCRewriter(InFile, OS,
00163                               CI.getDiagnostics(), CI.getLangOpts(),
00164                               CI.getDiagnosticOpts().NoRewriteMacros);
00165   }
00166   return 0;
00167 }
00168 
00169 void RewriteMacrosAction::ExecuteAction() {
00170   CompilerInstance &CI = getCompilerInstance();
00171   raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
00172   if (!OS) return;
00173 
00174   RewriteMacrosInInput(CI.getPreprocessor(), OS);
00175 }
00176 
00177 void RewriteTestAction::ExecuteAction() {
00178   CompilerInstance &CI = getCompilerInstance();
00179   raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
00180   if (!OS) return;
00181 
00182   DoRewriteTest(CI.getPreprocessor(), OS);
00183 }