@@ -129,38 +129,40 @@ static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC,
129
129
130
130
} // namespace
131
131
132
- CompilerInstance * CompletionInstance::getCachedCompilerInstance (
132
+ bool CompletionInstance::performCachedOperaitonIfPossible (
133
133
const swift::CompilerInvocation &Invocation, llvm::hash_code ArgsHash,
134
134
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
135
- DiagnosticConsumer *DiagC) {
136
- if (!EnableASTCaching)
137
- return nullptr ;
135
+ DiagnosticConsumer *DiagC,
136
+ llvm::function_ref<void (CompilerInstance &)> Callback) {
138
137
139
- if (CurrentASTReuseCount >= MaxASTReuseCount) {
140
- CurrentASTReuseCount = 0 ;
141
- return nullptr ;
142
- }
138
+ if (!EnableASTCaching)
139
+ return false ;
143
140
144
- if (!CachedCI)
145
- return nullptr ;
141
+ // Temporary move the CI so other threads don't use the same instance.
142
+ std::shared_ptr<CompilerInstance> CI;
143
+ CI.swap (CachedCI);
146
144
145
+ if (!CI)
146
+ return false ;
147
+ if (CurrentASTReuseCount >= MaxASTReuseCount)
148
+ return false ;
147
149
if (ArgsHash != CachedArgsHash)
148
- return nullptr ;
150
+ return false ;
149
151
150
- auto &oldState = CachedCI ->getPersistentParserState ();
152
+ auto &oldState = CI ->getPersistentParserState ();
151
153
if (!oldState.hasCodeCompletionDelayedDeclState ())
152
- return nullptr ;
154
+ return false ;
153
155
154
- auto &SM = CachedCI ->getSourceMgr ();
156
+ auto &SM = CI ->getSourceMgr ();
155
157
if (SM.getIdentifierForBuffer (SM.getCodeCompletionBufferID ()) !=
156
158
completionBuffer->getBufferIdentifier ())
157
- return nullptr ;
159
+ return false ;
158
160
159
161
auto &oldInfo = oldState.getCodeCompletionDelayedDeclState ();
160
162
161
163
// Currently, only completions within a function body is supported.
162
164
if (oldInfo.Kind != CodeCompletionDelayedDeclKind::FunctionBody)
163
- return nullptr ;
165
+ return false ;
164
166
165
167
auto newBufferID = SM.addMemBufferCopy (completionBuffer);
166
168
SM.setCodeCompletionPoint (newBufferID, Offset);
@@ -185,13 +187,13 @@ CompilerInstance *CompletionInstance::getCachedCompilerInstance(
185
187
parseIntoSourceFileFull (*newSF, BufferID, &newState);
186
188
// Couldn't find any completion token?
187
189
if (!newState.hasCodeCompletionDelayedDeclState ())
188
- return nullptr ;
190
+ return false ;
189
191
190
192
auto &newInfo = newState.getCodeCompletionDelayedDeclState ();
191
193
192
194
// The new completion must happens in function body too.
193
195
if (newInfo.Kind != CodeCompletionDelayedDeclKind::FunctionBody)
194
- return nullptr ;
196
+ return false ;
195
197
196
198
auto *oldSF = oldInfo.ParentContext ->getParentSourceFile ();
197
199
@@ -201,12 +203,12 @@ CompilerInstance *CompletionInstance::getCachedCompilerInstance(
201
203
oldSF->getInterfaceHash (oldInterfaceHash);
202
204
newSF->getInterfaceHash (newInterfaceHash);
203
205
if (oldInterfaceHash != newInterfaceHash)
204
- return nullptr ;
206
+ return false ;
205
207
206
208
DeclContext *DC =
207
209
getEquivalentDeclContextFromSourceFile (newInfo.ParentContext , oldSF);
208
210
if (!DC)
209
- return nullptr ;
211
+ return false ;
210
212
211
213
// OK, we can perform fast completion for this. Update the orignal delayed
212
214
// decl state.
@@ -228,28 +230,33 @@ CompilerInstance *CompletionInstance::getCachedCompilerInstance(
228
230
if (AFD->isBodySkipped ())
229
231
AFD->setBodyDelayed (AFD->getBodySourceRange ());
230
232
if (DiagC)
231
- CachedCI ->addDiagnosticConsumer (DiagC);
233
+ CI ->addDiagnosticConsumer (DiagC);
232
234
233
- CachedCI->getDiags ().diagnose (
234
- SM.getLocForOffset (BufferID, newInfo.StartOffset ),
235
- diag::completion_reusing_astcontext);
235
+ CI->getDiags ().diagnose (SM.getLocForOffset (BufferID, newInfo.StartOffset ),
236
+ diag::completion_reusing_astcontext);
236
237
238
+ Callback (*CI);
239
+
240
+ if (DiagC)
241
+ CI->removeDiagnosticConsumer (DiagC);
242
+
243
+ CachedCI.swap (CI);
244
+ CachedArgsHash = ArgsHash;
237
245
CurrentASTReuseCount += 1 ;
238
246
239
- return CachedCI. get () ;
247
+ return true ;
240
248
}
241
249
242
- CompilerInstance * CompletionInstance::renewCompilerInstance (
250
+ bool CompletionInstance::performNewOperation (
243
251
swift::CompilerInvocation &Invocation, llvm::hash_code ArgsHash,
244
252
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
245
253
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
246
- std::string &Error, DiagnosticConsumer *DiagC) {
254
+ std::string &Error, DiagnosticConsumer *DiagC,
255
+ llvm::function_ref<void (CompilerInstance &)> Callback) {
247
256
CachedCI.reset ();
248
- CachedCI = std::make_unique<CompilerInstance>();
249
- CachedArgsHash = ArgsHash;
250
- auto *CI = CachedCI.get ();
257
+ auto CI = std::make_shared<CompilerInstance>();
251
258
if (DiagC)
252
- CachedCI ->addDiagnosticConsumer (DiagC);
259
+ CI ->addDiagnosticConsumer (DiagC);
253
260
254
261
if (FileSystem != llvm::vfs::getRealFileSystem ())
255
262
CI->getSourceMgr ().setFileSystem (FileSystem);
@@ -258,18 +265,31 @@ CompilerInstance *CompletionInstance::renewCompilerInstance(
258
265
259
266
if (CI->setup (Invocation)) {
260
267
Error = " failed to setup compiler instance" ;
261
- return nullptr ;
268
+ return false ;
262
269
}
263
270
registerIDERequestFunctions (CI->getASTContext ().evaluator );
264
271
265
- return CI;
272
+ CI->performParseAndResolveImportsOnly ();
273
+ Callback (*CI);
274
+
275
+ if (DiagC)
276
+ CI->removeDiagnosticConsumer (DiagC);
277
+
278
+ if (EnableASTCaching) {
279
+ CachedCI.swap (CI);
280
+ CachedArgsHash = ArgsHash;
281
+ CurrentASTReuseCount = 0 ;
282
+ }
283
+
284
+ return true ;
266
285
}
267
286
268
- CompilerInstance * swift::ide::CompletionInstance::getCompilerInstance (
287
+ bool swift::ide::CompletionInstance::performOperation (
269
288
swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
270
289
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
271
290
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
272
- std::string &Error, DiagnosticConsumer *DiagC) {
291
+ std::string &Error, DiagnosticConsumer *DiagC,
292
+ llvm::function_ref<void (CompilerInstance &)> Callback) {
273
293
274
294
// Always disable source location resolutions from .swiftsourceinfo file
275
295
// because they're somewhat heavy operations and aren't needed for completion.
@@ -287,15 +307,14 @@ CompilerInstance *swift::ide::CompletionInstance::getCompilerInstance(
287
307
for (auto arg : Args)
288
308
ArgsHash = llvm::hash_combine (ArgsHash, StringRef (arg));
289
309
290
- if (auto *cached = getCachedCompilerInstance (Invocation, ArgsHash,
291
- completionBuffer, Offset, DiagC))
292
- return cached ;
310
+ if (performCachedOperaitonIfPossible (Invocation, ArgsHash, completionBuffer ,
311
+ Offset, DiagC, Callback ))
312
+ return true ;
293
313
294
- if (auto *renewed =
295
- renewCompilerInstance (Invocation, ArgsHash, FileSystem,
296
- completionBuffer, Offset, Error, DiagC))
297
- return renewed;
314
+ if (performNewOperation (Invocation, ArgsHash, FileSystem, completionBuffer,
315
+ Offset, Error, DiagC, Callback))
316
+ return true ;
298
317
299
318
assert (!Error.empty ());
300
- return nullptr ;
319
+ return false ;
301
320
}
0 commit comments