1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
//===--- EditorAdapter.cpp ------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/Basic/SourceLoc.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Migrator/EditorAdapter.h"
#include "swift/Migrator/Replacement.h"
#include "swift/Parse/Lexer.h"
#include "clang/Basic/SourceManager.h"
using namespace swift;
using namespace swift::migrator;
std::pair<unsigned, unsigned>
EditorAdapter::getLocInfo(swift::SourceLoc Loc) const {
auto SwiftBufferID = SwiftSrcMgr.findBufferContainingLoc(Loc);
auto Offset = SwiftSrcMgr.getLocOffsetInBuffer(Loc, SwiftBufferID);
return { SwiftBufferID, Offset };
}
bool
EditorAdapter::cacheReplacement(CharSourceRange Range, StringRef Text) const {
if (!CacheEnabled)
return false;
unsigned SwiftBufferID, Offset;
std::tie(SwiftBufferID, Offset) = getLocInfo(Range.getStart());
Replacement R{Offset, Range.getByteLength(), Text.str()};
if (Replacements.count(R)) {
return true;
} else {
Replacements.insert(R);
}
return false;
}
clang::FileID
EditorAdapter::getClangFileIDForSwiftBufferID(unsigned BufferID) const {
/// Check if we already have a mapping for this BufferID.
auto Found = SwiftToClangBufferMap.find(BufferID);
if (Found != SwiftToClangBufferMap.end()) {
return Found->getSecond();
}
// If we don't copy the corresponding buffer's text into a new buffer
// that the ClangSrcMgr can understand.
auto Text = SwiftSrcMgr.getEntireTextForBuffer(BufferID);
auto NewBuffer = llvm::MemoryBuffer::getMemBufferCopy(Text);
auto NewFileID = ClangSrcMgr.createFileID(std::move(NewBuffer));
SwiftToClangBufferMap.insert({BufferID, NewFileID});
return NewFileID;
}
clang::SourceLocation
EditorAdapter::translateSourceLoc(SourceLoc SwiftLoc) const {
unsigned SwiftBufferID, Offset;
std::tie(SwiftBufferID, Offset) = getLocInfo(SwiftLoc);
auto ClangFileID = getClangFileIDForSwiftBufferID(SwiftBufferID);
return ClangSrcMgr.getLocForStartOfFile(ClangFileID).getLocWithOffset(Offset);
}
clang::SourceRange
EditorAdapter::translateSourceRange(SourceRange SwiftSourceRange) const {
auto Start = translateSourceLoc(SwiftSourceRange.Start);
auto End = translateSourceLoc(SwiftSourceRange.End);
return clang::SourceRange { Start, End };
}
clang::CharSourceRange EditorAdapter::
translateCharSourceRange(CharSourceRange SwiftSourceSourceRange) const {
auto ClangStartLoc = translateSourceLoc(SwiftSourceSourceRange.getStart());
auto ClangEndLoc = translateSourceLoc(SwiftSourceSourceRange.getEnd());
return clang::CharSourceRange::getCharRange(ClangStartLoc, ClangEndLoc);
}
bool EditorAdapter::insert(SourceLoc Loc, StringRef Text, bool AfterToken,
bool BeforePreviousInsertions) {
// We don't have tokens on the clang side, so handle AfterToken in Swift
if (AfterToken)
Loc = Lexer::getLocForEndOfToken(SwiftSrcMgr, Loc);
if (cacheReplacement(CharSourceRange { Loc, 0 }, Text)) {
return true;
}
auto ClangLoc = translateSourceLoc(Loc);
return Edits.insert(ClangLoc, Text, /*AfterToken=*/false, BeforePreviousInsertions);
}
bool EditorAdapter::insertFromRange(SourceLoc Loc, CharSourceRange Range,
bool AfterToken,
bool BeforePreviousInsertions) {
// We don't have tokens on the clang side, so handle AfterToken in Swift
if (AfterToken)
Loc = Lexer::getLocForEndOfToken(SwiftSrcMgr, Loc);
if (cacheReplacement(CharSourceRange { Loc, 0 },
SwiftSrcMgr.extractText(Range))) {
return true;
}
auto ClangLoc = translateSourceLoc(Loc);
auto ClangCharRange = translateCharSourceRange(Range);
return Edits.insertFromRange(ClangLoc, ClangCharRange, /*AfterToken=*/false,
BeforePreviousInsertions);
}
bool EditorAdapter::insertWrap(StringRef Before, CharSourceRange Range,
StringRef After) {
auto ClangRange = translateCharSourceRange(Range);
return Edits.insertWrap(Before, ClangRange, After);
}
bool EditorAdapter::remove(CharSourceRange Range) {
if (cacheReplacement(Range, "")) {
return true;
}
auto ClangRange = translateCharSourceRange(Range);
return Edits.remove(ClangRange);
}
bool EditorAdapter::replace(CharSourceRange Range, StringRef Text) {
if (cacheReplacement(Range, Text)) {
return true;
}
auto ClangRange = translateCharSourceRange(Range);
return Edits.replace(ClangRange, Text);
}
bool EditorAdapter::replaceWithInner(CharSourceRange Range,
CharSourceRange InnerRange) {
if (cacheReplacement(Range, SwiftSrcMgr.extractText(InnerRange))) {
return true;
}
auto ClangRange = translateCharSourceRange(Range);
auto ClangInnerRange = translateCharSourceRange(InnerRange);
return Edits.replaceWithInner(ClangRange, ClangInnerRange);
}
bool EditorAdapter::replaceText(SourceLoc Loc, StringRef Text,
StringRef ReplacementText) {
auto Range = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr,
{ Loc, Loc.getAdvancedLoc(Text.size())});
if (cacheReplacement(Range, Text)) {
return true;
}
auto ClangLoc = translateSourceLoc(Loc);
return Edits.replaceText(ClangLoc, Text, ReplacementText);
}
bool EditorAdapter::insertFromRange(SourceLoc Loc, SourceRange TokenRange,
bool AfterToken,
bool BeforePreviousInsertions) {
auto CharRange = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr, TokenRange);
return insertFromRange(Loc, CharRange,
AfterToken, BeforePreviousInsertions);
}
bool EditorAdapter::insertWrap(StringRef Before, SourceRange TokenRange,
StringRef After) {
auto CharRange = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr, TokenRange);
return insertWrap(Before, CharRange, After);
}
bool EditorAdapter::remove(SourceLoc TokenLoc) {
return remove(Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr,
TokenLoc));
}
bool EditorAdapter::remove(SourceRange TokenRange) {
auto CharRange = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr, TokenRange);
return remove(CharRange);
}
bool EditorAdapter::replace(SourceRange TokenRange, StringRef Text) {
auto CharRange = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr,TokenRange);
return replace(CharRange, Text);
}
bool EditorAdapter::replaceWithInner(SourceRange TokenRange,
SourceRange TokenInnerRange) {
auto CharRange = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr, TokenRange);
auto CharInnerRange = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr, TokenInnerRange);
return replaceWithInner(CharRange, CharInnerRange);
}
bool EditorAdapter::replaceToken(SourceLoc TokenLoc, StringRef Text) {
return replace(Lexer::getTokenAtLocation(SwiftSrcMgr, TokenLoc).getRange(),
Text);
}
|