diff options
Diffstat (limited to 'lib/Tooling/Refactoring.cpp')
-rw-r--r-- | lib/Tooling/Refactoring.cpp | 246 |
1 files changed, 0 insertions, 246 deletions
diff --git a/lib/Tooling/Refactoring.cpp b/lib/Tooling/Refactoring.cpp index c96b8c9..c817306 100644 --- a/lib/Tooling/Refactoring.cpp +++ b/lib/Tooling/Refactoring.cpp @@ -25,252 +25,6 @@ namespace clang { namespace tooling { -static const char * const InvalidLocation = ""; - -Replacement::Replacement() - : FilePath(InvalidLocation) {} - -Replacement::Replacement(StringRef FilePath, unsigned Offset, unsigned Length, - StringRef ReplacementText) - : FilePath(FilePath), ReplacementRange(Offset, Length), - ReplacementText(ReplacementText) {} - -Replacement::Replacement(const SourceManager &Sources, SourceLocation Start, - unsigned Length, StringRef ReplacementText) { - setFromSourceLocation(Sources, Start, Length, ReplacementText); -} - -Replacement::Replacement(const SourceManager &Sources, - const CharSourceRange &Range, - StringRef ReplacementText) { - setFromSourceRange(Sources, Range, ReplacementText); -} - -bool Replacement::isApplicable() const { - return FilePath != InvalidLocation; -} - -bool Replacement::apply(Rewriter &Rewrite) const { - SourceManager &SM = Rewrite.getSourceMgr(); - const FileEntry *Entry = SM.getFileManager().getFile(FilePath); - if (!Entry) - return false; - FileID ID; - // FIXME: Use SM.translateFile directly. - SourceLocation Location = SM.translateFileLineCol(Entry, 1, 1); - ID = Location.isValid() ? - SM.getFileID(Location) : - SM.createFileID(Entry, SourceLocation(), SrcMgr::C_User); - // FIXME: We cannot check whether Offset + Length is in the file, as - // the remapping API is not public in the RewriteBuffer. - const SourceLocation Start = - SM.getLocForStartOfFile(ID). - 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, ReplacementRange.getLength(), ReplacementText); - assert(RewriteSucceeded); - return RewriteSucceeded; -} - -std::string Replacement::toString() const { - std::string result; - llvm::raw_string_ostream stream(result); - stream << FilePath << ": " << ReplacementRange.getOffset() << ":+" - << ReplacementRange.getLength() << ":\"" << ReplacementText << "\""; - return result; -} - -bool operator<(const Replacement &LHS, const Replacement &RHS) { - if (LHS.getOffset() != RHS.getOffset()) - return LHS.getOffset() < RHS.getOffset(); - if (LHS.getLength() != RHS.getLength()) - return LHS.getLength() < RHS.getLength(); - if (LHS.getFilePath() != RHS.getFilePath()) - return LHS.getFilePath() < RHS.getFilePath(); - return LHS.getReplacementText() < RHS.getReplacementText(); -} - -bool operator==(const Replacement &LHS, const Replacement &RHS) { - return LHS.getOffset() == RHS.getOffset() && - LHS.getLength() == RHS.getLength() && - LHS.getFilePath() == RHS.getFilePath() && - LHS.getReplacementText() == RHS.getReplacementText(); -} - -void Replacement::setFromSourceLocation(const SourceManager &Sources, - SourceLocation Start, unsigned Length, - StringRef ReplacementText) { - const std::pair<FileID, unsigned> DecomposedLocation = - Sources.getDecomposedLoc(Start); - const FileEntry *Entry = Sources.getFileEntryForID(DecomposedLocation.first); - if (Entry) { - // Make FilePath absolute so replacements can be applied correctly when - // relative paths for files are used. - llvm::SmallString<256> FilePath(Entry->getName()); - std::error_code EC = llvm::sys::fs::make_absolute(FilePath); - this->FilePath = EC ? FilePath.c_str() : Entry->getName(); - } else { - this->FilePath = InvalidLocation; - } - this->ReplacementRange = Range(DecomposedLocation.second, Length); - this->ReplacementText = ReplacementText; -} - -// FIXME: This should go into the Lexer, but we need to figure out how -// to handle ranges for refactoring in general first - there is no obvious -// good way how to integrate this into the Lexer yet. -static int getRangeSize(const SourceManager &Sources, - const CharSourceRange &Range) { - SourceLocation SpellingBegin = Sources.getSpellingLoc(Range.getBegin()); - SourceLocation SpellingEnd = Sources.getSpellingLoc(Range.getEnd()); - std::pair<FileID, unsigned> Start = Sources.getDecomposedLoc(SpellingBegin); - std::pair<FileID, unsigned> End = Sources.getDecomposedLoc(SpellingEnd); - if (Start.first != End.first) return -1; - if (Range.isTokenRange()) - End.second += Lexer::MeasureTokenLength(SpellingEnd, Sources, - LangOptions()); - return End.second - Start.second; -} - -void Replacement::setFromSourceRange(const SourceManager &Sources, - const CharSourceRange &Range, - StringRef ReplacementText) { - setFromSourceLocation(Sources, Sources.getSpellingLoc(Range.getBegin()), - getRangeSize(Sources, Range), ReplacementText); -} - -bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite) { - bool Result = true; - for (Replacements::const_iterator I = Replaces.begin(), - E = Replaces.end(); - I != E; ++I) { - if (I->isApplicable()) { - Result = I->apply(Rewrite) && Result; - } else { - Result = false; - } - } - return Result; -} - -// FIXME: Remove this function when Replacements is implemented as std::vector -// instead of std::set. -bool applyAllReplacements(const std::vector<Replacement> &Replaces, - Rewriter &Rewrite) { - bool Result = true; - for (std::vector<Replacement>::const_iterator I = Replaces.begin(), - E = Replaces.end(); - I != E; ++I) { - if (I->isApplicable()) { - Result = I->apply(Rewrite) && Result; - } else { - Result = false; - } - } - return Result; -} - -std::string applyAllReplacements(StringRef Code, const Replacements &Replaces) { - FileManager Files((FileSystemOptions())); - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr<DiagnosticIDs>(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, "<stdin>"); - const clang::FileEntry *Entry = - Files.getVirtualFile("<stdin>", Buf->getBufferSize(), 0); - SourceMgr.overrideFileContents(Entry, Buf); - FileID ID = - SourceMgr.createFileID(Entry, SourceLocation(), clang::SrcMgr::C_User); - for (Replacements::const_iterator I = Replaces.begin(), E = Replaces.end(); - I != E; ++I) { - Replacement Replace("<stdin>", 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; -} - -unsigned shiftedCodePosition(const Replacements &Replaces, unsigned Position) { - unsigned NewPosition = Position; - for (Replacements::iterator I = Replaces.begin(), E = Replaces.end(); I != E; - ++I) { - if (I->getOffset() >= Position) - break; - if (I->getOffset() + I->getLength() > Position) - NewPosition += I->getOffset() + I->getLength() - Position; - NewPosition += I->getReplacementText().size() - I->getLength(); - } - return NewPosition; -} - -// FIXME: Remove this function when Replacements is implemented as std::vector -// instead of std::set. -unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces, - unsigned Position) { - unsigned NewPosition = Position; - for (std::vector<Replacement>::const_iterator I = Replaces.begin(), - E = Replaces.end(); - I != E; ++I) { - if (I->getOffset() >= Position) - break; - if (I->getOffset() + I->getLength() > Position) - NewPosition += I->getOffset() + I->getLength() - Position; - NewPosition += I->getReplacementText().size() - I->getLength(); - } - return NewPosition; -} - -void deduplicate(std::vector<Replacement> &Replaces, - std::vector<Range> &Conflicts) { - if (Replaces.empty()) - return; - - // Deduplicate - std::sort(Replaces.begin(), Replaces.end()); - std::vector<Replacement>::iterator End = - std::unique(Replaces.begin(), Replaces.end()); - Replaces.erase(End, Replaces.end()); - - // Detect conflicts - Range ConflictRange(Replaces.front().getOffset(), - Replaces.front().getLength()); - unsigned ConflictStart = 0; - unsigned ConflictLength = 1; - for (unsigned i = 1; i < Replaces.size(); ++i) { - Range Current(Replaces[i].getOffset(), Replaces[i].getLength()); - if (ConflictRange.overlapsWith(Current)) { - // Extend conflicted range - ConflictRange = Range(ConflictRange.getOffset(), - std::max(ConflictRange.getLength(), - Current.getOffset() + Current.getLength() - - ConflictRange.getOffset())); - ++ConflictLength; - } else { - if (ConflictLength > 1) - Conflicts.push_back(Range(ConflictStart, ConflictLength)); - ConflictRange = Current; - ConflictStart = i; - ConflictLength = 1; - } - } - - if (ConflictLength > 1) - Conflicts.push_back(Range(ConflictStart, ConflictLength)); -} - - RefactoringTool::RefactoringTool(const CompilationDatabase &Compilations, ArrayRef<std::string> SourcePaths) : ClangTool(Compilations, SourcePaths) {} |