1f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//===--- Refactoring.cpp - Framework for clang refactoring tools ----------===// 2f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// 3f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// The LLVM Compiler Infrastructure 4f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// 5f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// This file is distributed under the University of Illinois Open Source 6f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// License. See LICENSE.TXT for details. 7f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// 8f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//===----------------------------------------------------------------------===// 9f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// 10f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// Implements tools to support refactorings. 11f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// 12f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek//===----------------------------------------------------------------------===// 13f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 1402c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor#include "clang/Basic/DiagnosticOptions.h" 15f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Basic/FileManager.h" 16f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Basic/SourceManager.h" 17f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Frontend/TextDiagnosticPrinter.h" 18f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Lex/Lexer.h" 19305c613af6cfc40e519c75d9d2c84c6fa9a841c0Ted Kremenek#include "clang/Rewrite/Core/Rewriter.h" 20f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek#include "clang/Tooling/Refactoring.h" 21d11344a728c7ffab17e5557506edfbcbae18d34eAriel J. Bernal#include "llvm/Support/FileSystem.h" 22d11344a728c7ffab17e5557506edfbcbae18d34eAriel J. Bernal#include "llvm/Support/Path.h" 23651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/raw_os_ostream.h" 24f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 25f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimeknamespace clang { 26f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimeknamespace tooling { 27f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 28f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekstatic const char * const InvalidLocation = ""; 29f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 30f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekReplacement::Replacement() 318a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper : FilePath(InvalidLocation) {} 32f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 338a99945769aa83270bda4ae4890f519800aa19ebDaniel JasperReplacement::Replacement(StringRef FilePath, unsigned Offset, unsigned Length, 348a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper StringRef ReplacementText) 358a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper : FilePath(FilePath), ReplacementRange(Offset, Length), 368a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper ReplacementText(ReplacementText) {} 37f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 38651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesReplacement::Replacement(const SourceManager &Sources, SourceLocation Start, 39cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko unsigned Length, StringRef ReplacementText) { 40f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek setFromSourceLocation(Sources, Start, Length, ReplacementText); 41f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 42f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 43651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesReplacement::Replacement(const SourceManager &Sources, 44651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const CharSourceRange &Range, 45cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko StringRef ReplacementText) { 46f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek setFromSourceRange(Sources, Range, ReplacementText); 47f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 48f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 49f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekbool Replacement::isApplicable() const { 50f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek return FilePath != InvalidLocation; 51f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 52f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 53f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimekbool Replacement::apply(Rewriter &Rewrite) const { 54f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SourceManager &SM = Rewrite.getSourceMgr(); 55f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek const FileEntry *Entry = SM.getFileManager().getFile(FilePath); 566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (!Entry) 57f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek return false; 58f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek FileID ID; 59f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // FIXME: Use SM.translateFile directly. 60f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SourceLocation Location = SM.translateFileLineCol(Entry, 1, 1); 61f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek ID = Location.isValid() ? 62f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SM.getFileID(Location) : 63f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SM.createFileID(Entry, SourceLocation(), SrcMgr::C_User); 64f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // FIXME: We cannot check whether Offset + Length is in the file, as 65f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // the remapping API is not public in the RewriteBuffer. 66f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek const SourceLocation Start = 67f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SM.getLocForStartOfFile(ID). 688a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper getLocWithOffset(ReplacementRange.getOffset()); 69f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // ReplaceText returns false on success. 70f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // ReplaceText only fails if the source location is not a file location, in 71f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek // which case we already returned false earlier. 728a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper bool RewriteSucceeded = !Rewrite.ReplaceText( 738a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper Start, ReplacementRange.getLength(), ReplacementText); 74f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek assert(RewriteSucceeded); 75f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek return RewriteSucceeded; 76f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 77f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 785d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimekstd::string Replacement::toString() const { 795d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimek std::string result; 805d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimek llvm::raw_string_ostream stream(result); 818a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper stream << FilePath << ": " << ReplacementRange.getOffset() << ":+" 828a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper << ReplacementRange.getLength() << ":\"" << ReplacementText << "\""; 835d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimek return result; 845d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimek} 855d51e8894624d5a12ed2c4fd80c31112d3d70f80Manuel Klimek 8605e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vanebool operator<(const Replacement &LHS, const Replacement &RHS) { 8705e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vane if (LHS.getOffset() != RHS.getOffset()) 8805e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vane return LHS.getOffset() < RHS.getOffset(); 8905e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vane if (LHS.getLength() != RHS.getLength()) 9005e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vane return LHS.getLength() < RHS.getLength(); 9105e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vane if (LHS.getFilePath() != RHS.getFilePath()) 9205e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vane return LHS.getFilePath() < RHS.getFilePath(); 9305e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vane return LHS.getReplacementText() < RHS.getReplacementText(); 94f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 95f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 9605e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vanebool operator==(const Replacement &LHS, const Replacement &RHS) { 9705e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vane return LHS.getOffset() == RHS.getOffset() && 9805e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vane LHS.getLength() == RHS.getLength() && 9905e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vane LHS.getFilePath() == RHS.getFilePath() && 10005e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vane LHS.getReplacementText() == RHS.getReplacementText(); 101d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane} 102d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane 103651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid Replacement::setFromSourceLocation(const SourceManager &Sources, 104f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SourceLocation Start, unsigned Length, 105cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko StringRef ReplacementText) { 106f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek const std::pair<FileID, unsigned> DecomposedLocation = 107f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Sources.getDecomposedLoc(Start); 108f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek const FileEntry *Entry = Sources.getFileEntryForID(DecomposedLocation.first); 1096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (Entry) { 110d11344a728c7ffab17e5557506edfbcbae18d34eAriel J. Bernal // Make FilePath absolute so replacements can be applied correctly when 11119b60a524c53ada17a31b5c9a96c7885ca48c825Ariel J. Bernal // relative paths for files are used. 11219b60a524c53ada17a31b5c9a96c7885ca48c825Ariel J. Bernal llvm::SmallString<256> FilePath(Entry->getName()); 113ef8225444452a1486bd721f3285301fe84643b00Stephen Hines std::error_code EC = llvm::sys::fs::make_absolute(FilePath); 11419b60a524c53ada17a31b5c9a96c7885ca48c825Ariel J. Bernal this->FilePath = EC ? FilePath.c_str() : Entry->getName(); 115b71aa7af7f4f9140c7bbcccca30aeecc671d767fAriel J. Bernal } else { 116d11344a728c7ffab17e5557506edfbcbae18d34eAriel J. Bernal this->FilePath = InvalidLocation; 117b71aa7af7f4f9140c7bbcccca30aeecc671d767fAriel J. Bernal } 1188a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper this->ReplacementRange = Range(DecomposedLocation.second, Length); 119f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek this->ReplacementText = ReplacementText; 120f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 121f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 122f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// FIXME: This should go into the Lexer, but we need to figure out how 123f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// to handle ranges for refactoring in general first - there is no obvious 124f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek// good way how to integrate this into the Lexer yet. 125651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic int getRangeSize(const SourceManager &Sources, 126651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const CharSourceRange &Range) { 127f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SourceLocation SpellingBegin = Sources.getSpellingLoc(Range.getBegin()); 128f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek SourceLocation SpellingEnd = Sources.getSpellingLoc(Range.getEnd()); 129f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek std::pair<FileID, unsigned> Start = Sources.getDecomposedLoc(SpellingBegin); 130f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek std::pair<FileID, unsigned> End = Sources.getDecomposedLoc(SpellingEnd); 131f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek if (Start.first != End.first) return -1; 132f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek if (Range.isTokenRange()) 133f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek End.second += Lexer::MeasureTokenLength(SpellingEnd, Sources, 134f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek LangOptions()); 135f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek return End.second - Start.second; 136f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 137f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 138651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid Replacement::setFromSourceRange(const SourceManager &Sources, 139f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek const CharSourceRange &Range, 140cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko StringRef ReplacementText) { 141f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek setFromSourceLocation(Sources, Sources.getSpellingLoc(Range.getBegin()), 142f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek getRangeSize(Sources, Range), ReplacementText); 143f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 144f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 14576a2ea3d8a0c3f3a54f293e305ae16f654eab04fDavid Blaikiebool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite) { 146f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek bool Result = true; 147f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek for (Replacements::const_iterator I = Replaces.begin(), 148f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek E = Replaces.end(); 149f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek I != E; ++I) { 150f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek if (I->isApplicable()) { 151f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Result = I->apply(Rewrite) && Result; 152f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } else { 153f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Result = false; 154f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 155f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 156f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek return Result; 157f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 158f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 159b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane// FIXME: Remove this function when Replacements is implemented as std::vector 160b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane// instead of std::set. 161b58cfd93c49727c1d471ce71901502df824556c7Edwin Vanebool applyAllReplacements(const std::vector<Replacement> &Replaces, 162b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane Rewriter &Rewrite) { 163b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane bool Result = true; 164b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane for (std::vector<Replacement>::const_iterator I = Replaces.begin(), 165b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane E = Replaces.end(); 166b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane I != E; ++I) { 167b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane if (I->isApplicable()) { 168b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane Result = I->apply(Rewrite) && Result; 169b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane } else { 170b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane Result = false; 171b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane } 172b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane } 173b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane return Result; 174b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane} 175b58cfd93c49727c1d471ce71901502df824556c7Edwin Vane 17676a2ea3d8a0c3f3a54f293e305ae16f654eab04fDavid Blaikiestd::string applyAllReplacements(StringRef Code, const Replacements &Replaces) { 1778a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper FileManager Files((FileSystemOptions())); 1788a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper DiagnosticsEngine Diagnostics( 1798a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), 1808a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper new DiagnosticOptions); 1818a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper Diagnostics.setClient(new TextDiagnosticPrinter( 1828a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper llvm::outs(), &Diagnostics.getDiagnosticOptions())); 1838a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper SourceManager SourceMgr(Diagnostics, Files); 1848a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper Rewriter Rewrite(SourceMgr, LangOptions()); 1858a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper llvm::MemoryBuffer *Buf = llvm::MemoryBuffer::getMemBuffer(Code, "<stdin>"); 1868a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper const clang::FileEntry *Entry = 1878a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper Files.getVirtualFile("<stdin>", Buf->getBufferSize(), 0); 1888a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper SourceMgr.overrideFileContents(Entry, Buf); 1898a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper FileID ID = 1908a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper SourceMgr.createFileID(Entry, SourceLocation(), clang::SrcMgr::C_User); 19176a2ea3d8a0c3f3a54f293e305ae16f654eab04fDavid Blaikie for (Replacements::const_iterator I = Replaces.begin(), E = Replaces.end(); 19276a2ea3d8a0c3f3a54f293e305ae16f654eab04fDavid Blaikie I != E; ++I) { 1938a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper Replacement Replace("<stdin>", I->getOffset(), I->getLength(), 1948a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper I->getReplacementText()); 1958a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper if (!Replace.apply(Rewrite)) 1968a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper return ""; 1978a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper } 1988a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper std::string Result; 1998a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper llvm::raw_string_ostream OS(Result); 2008a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper Rewrite.getEditBuffer(ID).write(OS); 2018a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper OS.flush(); 2028a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper return Result; 2038a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper} 2048a99945769aa83270bda4ae4890f519800aa19ebDaniel Jasper 2056bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasperunsigned shiftedCodePosition(const Replacements &Replaces, unsigned Position) { 2066bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper unsigned NewPosition = Position; 2076bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E; 2086bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper ++I) { 2096bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper if (I->getOffset() >= Position) 2106bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper break; 2116bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper if (I->getOffset() + I->getLength() > Position) 2126bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper NewPosition += I->getOffset() + I->getLength() - Position; 2136bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper NewPosition += I->getReplacementText().size() - I->getLength(); 2146bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper } 2156bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper return NewPosition; 2166bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper} 2176bd3b93200c6ae141d0f7444ffb4cacd52b183edDaniel Jasper 218a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane// FIXME: Remove this function when Replacements is implemented as std::vector 219a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane// instead of std::set. 220a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vaneunsigned shiftedCodePosition(const std::vector<Replacement> &Replaces, 221a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane unsigned Position) { 222a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane unsigned NewPosition = Position; 223a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane for (std::vector<Replacement>::const_iterator I = Replaces.begin(), 224a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane E = Replaces.end(); 225a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane I != E; ++I) { 226a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane if (I->getOffset() >= Position) 227a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane break; 228a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane if (I->getOffset() + I->getLength() > Position) 229a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane NewPosition += I->getOffset() + I->getLength() - Position; 230a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane NewPosition += I->getReplacementText().size() - I->getLength(); 231a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane } 232a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane return NewPosition; 233a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane} 234a778cde0ddf4c47a63786fb1067f25c1fbfcf19dEdwin Vane 235d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vanevoid deduplicate(std::vector<Replacement> &Replaces, 236d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane std::vector<Range> &Conflicts) { 237d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane if (Replaces.empty()) 238d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane return; 239d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane 240d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane // Deduplicate 24105e4af0b92f8b1febeb5abafd1f128cb5c3e00a4Edwin Vane std::sort(Replaces.begin(), Replaces.end()); 242d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane std::vector<Replacement>::iterator End = 243d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane std::unique(Replaces.begin(), Replaces.end()); 244d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane Replaces.erase(End, Replaces.end()); 245d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane 246d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane // Detect conflicts 247d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane Range ConflictRange(Replaces.front().getOffset(), 248d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane Replaces.front().getLength()); 249d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane unsigned ConflictStart = 0; 250d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane unsigned ConflictLength = 1; 251d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane for (unsigned i = 1; i < Replaces.size(); ++i) { 252d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane Range Current(Replaces[i].getOffset(), Replaces[i].getLength()); 253d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane if (ConflictRange.overlapsWith(Current)) { 254d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane // Extend conflicted range 255d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane ConflictRange = Range(ConflictRange.getOffset(), 25695f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane std::max(ConflictRange.getLength(), 25795f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane Current.getOffset() + Current.getLength() - 25895f0766c1942c8cdc9f913a083ad2bfc4c0c27c9Edwin Vane ConflictRange.getOffset())); 259d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane ++ConflictLength; 260d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane } else { 261d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane if (ConflictLength > 1) 262d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane Conflicts.push_back(Range(ConflictStart, ConflictLength)); 263d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane ConflictRange = Current; 264d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane ConflictStart = i; 265d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane ConflictLength = 1; 266d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane } 267d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane } 268d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane 269d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane if (ConflictLength > 1) 270d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane Conflicts.push_back(Range(ConflictStart, ConflictLength)); 271d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane} 272d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane 273d5692dbfeb97ed2e7ff11bca26059fa735e1b308Edwin Vane 274f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekRefactoringTool::RefactoringTool(const CompilationDatabase &Compilations, 275f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek ArrayRef<std::string> SourcePaths) 276d088a5f966c31462280d5ace29febc6889834611Edwin Vane : ClangTool(Compilations, SourcePaths) {} 277f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 278f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel KlimekReplacements &RefactoringTool::getReplacements() { return Replace; } 279f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 280d088a5f966c31462280d5ace29febc6889834611Edwin Vaneint RefactoringTool::runAndSave(FrontendActionFactory *ActionFactory) { 281d088a5f966c31462280d5ace29febc6889834611Edwin Vane if (int Result = run(ActionFactory)) { 282d088a5f966c31462280d5ace29febc6889834611Edwin Vane return Result; 283d088a5f966c31462280d5ace29febc6889834611Edwin Vane } 284d088a5f966c31462280d5ace29febc6889834611Edwin Vane 285f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek LangOptions DefaultLangOptions; 28602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 28702c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), &*DiagOpts); 288f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek DiagnosticsEngine Diagnostics( 289cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), 29002c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor &*DiagOpts, &DiagnosticPrinter, false); 291d088a5f966c31462280d5ace29febc6889834611Edwin Vane SourceManager Sources(Diagnostics, getFiles()); 292f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek Rewriter Rewrite(Sources, DefaultLangOptions); 293d088a5f966c31462280d5ace29febc6889834611Edwin Vane 294d088a5f966c31462280d5ace29febc6889834611Edwin Vane if (!applyAllReplacements(Rewrite)) { 295f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek llvm::errs() << "Skipped some replacements.\n"; 296f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek } 297d088a5f966c31462280d5ace29febc6889834611Edwin Vane 298d088a5f966c31462280d5ace29febc6889834611Edwin Vane return saveRewrittenFiles(Rewrite); 299d088a5f966c31462280d5ace29febc6889834611Edwin Vane} 300d088a5f966c31462280d5ace29febc6889834611Edwin Vane 301d088a5f966c31462280d5ace29febc6889834611Edwin Vanebool RefactoringTool::applyAllReplacements(Rewriter &Rewrite) { 302d088a5f966c31462280d5ace29febc6889834611Edwin Vane return tooling::applyAllReplacements(Replace, Rewrite); 303d088a5f966c31462280d5ace29febc6889834611Edwin Vane} 304d088a5f966c31462280d5ace29febc6889834611Edwin Vane 305d088a5f966c31462280d5ace29febc6889834611Edwin Vaneint RefactoringTool::saveRewrittenFiles(Rewriter &Rewrite) { 3066bf97fb15c09db9a0238ccb73be2dbf9cd77a7eeAlp Toker return Rewrite.overwriteChangedFiles() ? 1 : 0; 307f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} 308f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek 309f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} // end namespace tooling 310f9d4cbd3dd1eb4cf3ec3c5ec7acc310415beeefdManuel Klimek} // end namespace clang 311