forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathEditorAdapter.cpp
205 lines (171 loc) · 7.26 KB
/
EditorAdapter.cpp
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);
}