diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Rewrite/FixItRewriter.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Rewrite/FixItRewriter.cpp | 115 |
1 files changed, 78 insertions, 37 deletions
diff --git a/contrib/llvm/tools/clang/lib/Rewrite/FixItRewriter.cpp b/contrib/llvm/tools/clang/lib/Rewrite/FixItRewriter.cpp index 632c0de..3863adb 100644 --- a/contrib/llvm/tools/clang/lib/Rewrite/FixItRewriter.cpp +++ b/contrib/llvm/tools/clang/lib/Rewrite/FixItRewriter.cpp @@ -14,6 +14,8 @@ //===----------------------------------------------------------------------===// #include "clang/Rewrite/FixItRewriter.h" +#include "clang/Edit/Commit.h" +#include "clang/Edit/EditsReceiver.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" @@ -29,16 +31,19 @@ FixItRewriter::FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr, const LangOptions &LangOpts, FixItOptions *FixItOpts) : Diags(Diags), + Editor(SourceMgr, LangOpts), Rewrite(SourceMgr, LangOpts), FixItOpts(FixItOpts), - NumFailures(0) { + NumFailures(0), + PrevDiagSilenced(false) { + OwnsClient = Diags.ownsClient(); Client = Diags.takeClient(); Diags.setClient(this); } FixItRewriter::~FixItRewriter() { Diags.takeClient(); - Diags.setClient(Client); + Diags.setClient(Client, OwnsClient); } bool FixItRewriter::WriteFixedFile(FileID ID, raw_ostream &OS) { @@ -49,26 +54,57 @@ bool FixItRewriter::WriteFixedFile(FileID ID, raw_ostream &OS) { return false; } -bool FixItRewriter::WriteFixedFiles() { +namespace { + +class RewritesReceiver : public edit::EditsReceiver { + Rewriter &Rewrite; + +public: + RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { } + + virtual void insert(SourceLocation loc, StringRef text) { + Rewrite.InsertText(loc, text); + } + virtual void replace(CharSourceRange range, StringRef text) { + Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text); + } +}; + +} + +bool FixItRewriter::WriteFixedFiles( + std::vector<std::pair<std::string, std::string> > *RewrittenFiles) { if (NumFailures > 0 && !FixItOpts->FixWhatYouCan) { Diag(FullSourceLoc(), diag::warn_fixit_no_changes); return true; } + RewritesReceiver Rec(Rewrite); + Editor.applyRewrites(Rec); + for (iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) { const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first); - std::string Filename = FixItOpts->RewriteFilename(Entry->getName()); + int fd; + std::string Filename = FixItOpts->RewriteFilename(Entry->getName(), fd); std::string Err; - llvm::raw_fd_ostream OS(Filename.c_str(), Err, - llvm::raw_fd_ostream::F_Binary); + OwningPtr<llvm::raw_fd_ostream> OS; + if (fd != -1) { + OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true)); + } else { + OS.reset(new llvm::raw_fd_ostream(Filename.c_str(), Err, + llvm::raw_fd_ostream::F_Binary)); + } if (!Err.empty()) { Diags.Report(clang::diag::err_fe_unable_to_open_output) << Filename << Err; continue; } RewriteBuffer &RewriteBuf = I->second; - RewriteBuf.write(OS); - OS.flush(); + RewriteBuf.write(*OS); + OS->flush(); + + if (RewrittenFiles) + RewrittenFiles->push_back(std::make_pair(Entry->getName(), Filename)); } return false; @@ -83,58 +119,63 @@ void FixItRewriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, // Default implementation (Warnings/errors count). DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info); - Client->HandleDiagnostic(DiagLevel, Info); + if (!FixItOpts->Silent || + DiagLevel >= DiagnosticsEngine::Error || + (DiagLevel == DiagnosticsEngine::Note && !PrevDiagSilenced) || + (DiagLevel > DiagnosticsEngine::Note && Info.getNumFixItHints())) { + Client->HandleDiagnostic(DiagLevel, Info); + PrevDiagSilenced = false; + } else { + PrevDiagSilenced = true; + } // Skip over any diagnostics that are ignored or notes. if (DiagLevel <= DiagnosticsEngine::Note) return; + // Skip over errors if we are only fixing warnings. + if (DiagLevel >= DiagnosticsEngine::Error && FixItOpts->FixOnlyWarnings) { + ++NumFailures; + return; + } // Make sure that we can perform all of the modifications we // in this diagnostic. - bool CanRewrite = Info.getNumFixItHints() > 0; + edit::Commit commit(Editor); for (unsigned Idx = 0, Last = Info.getNumFixItHints(); Idx < Last; ++Idx) { const FixItHint &Hint = Info.getFixItHint(Idx); - if (Hint.RemoveRange.isValid() && - Rewrite.getRangeSize(Hint.RemoveRange) == -1) { - CanRewrite = false; - break; + + if (Hint.CodeToInsert.empty()) { + if (Hint.InsertFromRange.isValid()) + commit.insertFromRange(Hint.RemoveRange.getBegin(), + Hint.InsertFromRange, /*afterToken=*/false, + Hint.BeforePreviousInsertions); + else + commit.remove(Hint.RemoveRange); + } else { + if (Hint.RemoveRange.isTokenRange() || + Hint.RemoveRange.getBegin() != Hint.RemoveRange.getEnd()) + commit.replace(Hint.RemoveRange, Hint.CodeToInsert); + else + commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert, + /*afterToken=*/false, Hint.BeforePreviousInsertions); } } + bool CanRewrite = Info.getNumFixItHints() > 0 && commit.isCommitable(); if (!CanRewrite) { if (Info.getNumFixItHints() > 0) Diag(Info.getLocation(), diag::note_fixit_in_macro); // If this was an error, refuse to perform any rewriting. - if (DiagLevel == DiagnosticsEngine::Error || - DiagLevel == DiagnosticsEngine::Fatal) { + if (DiagLevel >= DiagnosticsEngine::Error) { if (++NumFailures == 1) Diag(Info.getLocation(), diag::note_fixit_unfixed_error); } return; } - - bool Failed = false; - for (unsigned Idx = 0, Last = Info.getNumFixItHints(); - Idx < Last; ++Idx) { - const FixItHint &Hint = Info.getFixItHint(Idx); - - if (Hint.CodeToInsert.empty()) { - // We're removing code. - if (Rewrite.RemoveText(Hint.RemoveRange)) - Failed = true; - continue; - } - - // We're replacing code. - if (Rewrite.ReplaceText(Hint.RemoveRange.getBegin(), - Rewrite.getRangeSize(Hint.RemoveRange), - Hint.CodeToInsert)) - Failed = true; - } - - if (Failed) { + + if (!Editor.commit(commit)) { ++NumFailures; Diag(Info.getLocation(), diag::note_fixit_failed); return; |