From ec04c0dba0b2ca2ad6906009e8eca54928b99c46 Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Thu, 16 May 2013 10:40:07 +0000 Subject: Add a more convenient interface to use clang-format. It turns out that several implementations go through the trouble of setting up a SourceManager and Lexer and abstracting this into a function makes usage easier. Also abstracts SourceManager-independent ranges out of tooling::Refactoring and provides a convenience function to create them from line ranges. llvm-svn: 181997 --- clang/lib/Tooling/Refactoring.cpp | 57 ++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 13 deletions(-) (limited to 'clang/lib/Tooling') diff --git a/clang/lib/Tooling/Refactoring.cpp b/clang/lib/Tooling/Refactoring.cpp index d8440d639d0..f795def74ff 100644 --- a/clang/lib/Tooling/Refactoring.cpp +++ b/clang/lib/Tooling/Refactoring.cpp @@ -26,12 +26,12 @@ namespace tooling { static const char * const InvalidLocation = ""; Replacement::Replacement() - : FilePath(InvalidLocation), Offset(0), Length(0) {} + : FilePath(InvalidLocation) {} -Replacement::Replacement(StringRef FilePath, unsigned Offset, - unsigned Length, StringRef ReplacementText) - : FilePath(FilePath), Offset(Offset), - Length(Length), ReplacementText(ReplacementText) {} +Replacement::Replacement(StringRef FilePath, unsigned Offset, unsigned Length, + StringRef ReplacementText) + : FilePath(FilePath), ReplacementRange(Offset, Length), + ReplacementText(ReplacementText) {} Replacement::Replacement(SourceManager &Sources, SourceLocation Start, unsigned Length, StringRef ReplacementText) { @@ -62,11 +62,12 @@ bool Replacement::apply(Rewriter &Rewrite) const { // the remapping API is not public in the RewriteBuffer. const SourceLocation Start = SM.getLocForStartOfFile(ID). - getLocWithOffset(Offset); + getLocWithOffset(ReplacementRange.getOffset()); // ReplaceText returns false on success. // ReplaceText only fails if the source location is not a file location, in // which case we already returned false earlier. - bool RewriteSucceeded = !Rewrite.ReplaceText(Start, Length, ReplacementText); + bool RewriteSucceeded = !Rewrite.ReplaceText( + Start, ReplacementRange.getLength(), ReplacementText); assert(RewriteSucceeded); return RewriteSucceeded; } @@ -74,16 +75,18 @@ bool Replacement::apply(Rewriter &Rewrite) const { std::string Replacement::toString() const { std::string result; llvm::raw_string_ostream stream(result); - stream << FilePath << ": " << Offset << ":+" << Length - << ":\"" << ReplacementText << "\""; + stream << FilePath << ": " << ReplacementRange.getOffset() << ":+" + << ReplacementRange.getLength() << ":\"" << ReplacementText << "\""; return result; } bool Replacement::Less::operator()(const Replacement &R1, const Replacement &R2) const { if (R1.FilePath != R2.FilePath) return R1.FilePath < R2.FilePath; - if (R1.Offset != R2.Offset) return R1.Offset < R2.Offset; - if (R1.Length != R2.Length) return R1.Length < R2.Length; + if (R1.ReplacementRange.getOffset() != R2.ReplacementRange.getOffset()) + return R1.ReplacementRange.getOffset() < R2.ReplacementRange.getOffset(); + if (R1.ReplacementRange.getLength() != R2.ReplacementRange.getLength()) + return R1.ReplacementRange.getLength() < R2.ReplacementRange.getLength(); return R1.ReplacementText < R2.ReplacementText; } @@ -94,8 +97,7 @@ void Replacement::setFromSourceLocation(SourceManager &Sources, Sources.getDecomposedLoc(Start); const FileEntry *Entry = Sources.getFileEntryForID(DecomposedLocation.first); this->FilePath = Entry != NULL ? Entry->getName() : InvalidLocation; - this->Offset = DecomposedLocation.second; - this->Length = Length; + this->ReplacementRange = Range(DecomposedLocation.second, Length); this->ReplacementText = ReplacementText; } @@ -135,6 +137,35 @@ bool applyAllReplacements(Replacements &Replaces, Rewriter &Rewrite) { return Result; } +std::string applyAllReplacements(StringRef Code, Replacements &Replaces) { + FileManager Files((FileSystemOptions())); + DiagnosticsEngine Diagnostics( + IntrusiveRefCntPtr(new DiagnosticIDs), + new DiagnosticOptions); + Diagnostics.setClient(new TextDiagnosticPrinter( + llvm::outs(), &Diagnostics.getDiagnosticOptions())); + SourceManager SourceMgr(Diagnostics, Files); + Rewriter Rewrite(SourceMgr, LangOptions()); + llvm::MemoryBuffer *Buf = llvm::MemoryBuffer::getMemBuffer(Code, ""); + const clang::FileEntry *Entry = + Files.getVirtualFile("", Buf->getBufferSize(), 0); + SourceMgr.overrideFileContents(Entry, Buf); + FileID ID = + SourceMgr.createFileID(Entry, SourceLocation(), clang::SrcMgr::C_User); + for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E; + ++I) { + Replacement Replace("", I->getOffset(), I->getLength(), + I->getReplacementText()); + if (!Replace.apply(Rewrite)) + return ""; + } + std::string Result; + llvm::raw_string_ostream OS(Result); + Rewrite.getEditBuffer(ID).write(OS); + OS.flush(); + return Result; +} + RefactoringTool::RefactoringTool(const CompilationDatabase &Compilations, ArrayRef SourcePaths) : ClangTool(Compilations, SourcePaths) {} -- cgit v1.2.3