21
21
#include " swift/Basic/SourceManager.h"
22
22
#include " swift/Driver/FrontendUtil.h"
23
23
#include " swift/Frontend/Frontend.h"
24
+ #include " swift/Parse/Lexer.h"
24
25
#include " swift/Parse/PersistentParserState.h"
25
26
#include " swift/Subsystems.h"
26
27
#include " llvm/ADT/Hashing.h"
@@ -159,27 +160,27 @@ bool CompletionInstance::performCachedOperaitonIfPossible(
159
160
if (oldInfo.Kind != CodeCompletionDelayedDeclKind::FunctionBody)
160
161
return false ;
161
162
162
- auto newBufferID = SM.addMemBufferCopy (completionBuffer);
163
- SM.setCodeCompletionPoint (newBufferID, Offset);
164
-
165
163
// Parse the new buffer into temporary SourceFile.
164
+ SourceManager tmpSM;
165
+ auto tmpBufferID = tmpSM.addMemBufferCopy (completionBuffer);
166
+ tmpSM.setCodeCompletionPoint (tmpBufferID, Offset);
167
+
166
168
LangOptions langOpts;
167
169
langOpts.DisableParserLookup = true ;
168
170
TypeCheckerOptions typeckOpts;
169
171
SearchPathOptions searchPathOpts;
170
- DiagnosticEngine Diags (SM );
172
+ DiagnosticEngine tmpDiags (tmpSM );
171
173
std::unique_ptr<ASTContext> Ctx (
172
- ASTContext::get (langOpts, typeckOpts, searchPathOpts, SM, Diags ));
174
+ ASTContext::get (langOpts, typeckOpts, searchPathOpts, tmpSM, tmpDiags ));
173
175
registerIDERequestFunctions (Ctx->evaluator );
174
176
registerTypeCheckerRequestFunctions (Ctx->evaluator );
175
177
ModuleDecl *M = ModuleDecl::create (Identifier (), *Ctx);
176
- unsigned BufferID = SM.getCodeCompletionBufferID ();
177
178
PersistentParserState newState;
178
179
SourceFile *newSF =
179
- new (*Ctx) SourceFile (*M, SourceFileKind::Library, BufferID ,
180
+ new (*Ctx) SourceFile (*M, SourceFileKind::Library, tmpBufferID ,
180
181
SourceFile::ImplicitModuleImportKind::None);
181
182
newSF->enableInterfaceHash ();
182
- parseIntoSourceFileFull (*newSF, BufferID , &newState);
183
+ parseIntoSourceFileFull (*newSF, tmpBufferID , &newState);
183
184
// Couldn't find any completion token?
184
185
if (!newState.hasCodeCompletionDelayedDeclState ())
185
186
return false ;
@@ -208,6 +209,36 @@ bool CompletionInstance::performCachedOperaitonIfPossible(
208
209
// OK, we can perform fast completion for this. Update the orignal delayed
209
210
// decl state.
210
211
212
+ // Fast completion keeps the buffer in memory for multiple completions.
213
+ // To reduce the consumption, slice the source buffer so it only holds
214
+ // the portion that is needed for the second pass.
215
+ auto startOffset = newInfo.StartOffset ;
216
+ if (newInfo.PrevOffset != ~0u )
217
+ startOffset = newInfo.PrevOffset ;
218
+ auto startLoc = tmpSM.getLocForOffset (tmpBufferID, startOffset);
219
+ startLoc = Lexer::getLocForStartOfLine (tmpSM, startLoc);
220
+ startOffset = tmpSM.getLocOffsetInBuffer (startLoc, tmpBufferID);
221
+
222
+ auto endOffset = newInfo.EndOffset ;
223
+ auto endLoc = tmpSM.getLocForOffset (tmpBufferID, endOffset);
224
+ endLoc = Lexer::getLocForEndOfToken (tmpSM, endLoc);
225
+ endOffset = tmpSM.getLocOffsetInBuffer (endLoc, tmpBufferID);
226
+
227
+ newInfo.StartOffset -= startOffset;
228
+ newInfo.EndOffset -= startOffset;
229
+ if (newInfo.PrevOffset != ~0u )
230
+ newInfo.PrevOffset -= startOffset;
231
+
232
+ auto sourceText = completionBuffer->getBuffer ().slice (startOffset, endOffset);
233
+ auto newOffset = Offset - startOffset;
234
+
235
+ auto newBufferID =
236
+ SM.addMemBufferCopy (sourceText, completionBuffer->getBufferIdentifier ());
237
+ SM.openVirtualFile (SM.getLocForBufferStart (newBufferID),
238
+ tmpSM.getDisplayNameForLoc (startLoc),
239
+ tmpSM.getLineAndColumn (startLoc).first - 1 );
240
+ SM.setCodeCompletionPoint (newBufferID, newOffset);
241
+
211
242
// Construct dummy scopes. We don't need to restore the original scope
212
243
// because they are probably not 'isResolvable()' anyway.
213
244
auto &SI = oldState.getScopeInfo ();
@@ -227,8 +258,8 @@ bool CompletionInstance::performCachedOperaitonIfPossible(
227
258
if (DiagC)
228
259
CI.addDiagnosticConsumer (DiagC);
229
260
230
- CI.getDiags ().diagnose (SM.getLocForOffset (BufferID , newInfo.StartOffset ),
231
- diag::completion_reusing_astcontext);
261
+ CI.getDiags ().diagnose (SM.getLocForOffset (newBufferID , newInfo.StartOffset ),
262
+ diag::completion_reusing_astcontext);
232
263
233
264
Callback (CI);
234
265
0 commit comments