Skip to content

Commit 0f45267

Browse files
committed
[CodeCompletion] Use the arguments to check the equality of the invocation
Checking "selected" properties of CompilerInvocation is hard to keep it up to date. If the arguments are the same, the invocations are the same.
1 parent c5b1ada commit 0f45267

File tree

6 files changed

+31
-85
lines changed

6 files changed

+31
-85
lines changed

include/swift/IDE/CompletionInstance.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_IDE_COMPLETIONINSTANCE_H
1515

1616
#include "swift/Frontend/Frontend.h"
17+
#include "llvm/ADT/Hashing.h"
1718
#include "llvm/ADT/IntrusiveRefCntPtr.h"
1819
#include "llvm/ADT/SmallString.h"
1920
#include "llvm/ADT/StringRef.h"
@@ -37,6 +38,7 @@ makeCodeCompletionMemoryBuffer(const llvm::MemoryBuffer *origBuf,
3738
/// Manages \c CompilerInstance for completion like operations.
3839
class CompletionInstance {
3940
std::unique_ptr<CompilerInstance> CachedCI = nullptr;
41+
llvm::hash_code CachedArgsHash;
4042
bool EnableASTCaching = false;
4143
unsigned MaxASTReuseCount = 100;
4244
unsigned CurrentASTReuseCount = 0;
@@ -48,27 +50,31 @@ class CompletionInstance {
4850
/// bodies, or the interface hash of the file has changed.
4951
swift::CompilerInstance *
5052
getCachedCompilerInstance(const swift::CompilerInvocation &Invocation,
53+
llvm::hash_code ArgsHash,
5154
llvm::MemoryBuffer *completionBuffer,
5255
unsigned int Offset, DiagnosticConsumer *DiagC);
5356

5457
/// Returns new \c CompilerInstance for the completion request. Users still
5558
/// have to call \c performParseAndResolveImportsOnly() , and perform the
5659
/// second pass on it.
5760
swift::CompilerInstance *renewCompilerInstance(
58-
swift::CompilerInvocation &Invocation,
61+
swift::CompilerInvocation &Invocation, llvm::hash_code ArgsHash,
5962
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
6063
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
6164
std::string &Error, DiagnosticConsumer *DiagC);
6265

6366
public:
64-
void setEnableASTCaching(bool Flag) {
65-
EnableASTCaching = Flag;
66-
}
67+
void setEnableASTCaching(bool Flag) { EnableASTCaching = Flag; }
6768

6869
/// Returns \C CompilerInstance for the completion request. Users can check if
6970
/// it's cached or not by 'hasPersistentParserState()'.
71+
///
72+
/// NOTE: \p Args is only used for checking the equaity of the invocation.
73+
/// Since this function assumes that it is already normalized, exact the same
74+
/// arguments including their order is considered as the same invocation.
7075
swift::CompilerInstance *getCompilerInstance(
7176
swift::CompilerInvocation &Invocation,
77+
llvm::ArrayRef<const char *> Args,
7278
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
7379
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
7480
std::string &Error, DiagnosticConsumer *DiagC);

lib/IDE/CompletionInstance.cpp

Lines changed: 16 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
#include "swift/Frontend/Frontend.h"
2424
#include "swift/Parse/PersistentParserState.h"
2525
#include "swift/Subsystems.h"
26-
#include "llvm/Support/MemoryBuffer.h"
2726
#include "llvm/ADT/Hashing.h"
27+
#include "llvm/Support/MemoryBuffer.h"
2828

2929
using namespace swift;
3030
using namespace ide;
@@ -127,76 +127,10 @@ static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC,
127127
return newDC;
128128
}
129129

130-
/// Calculate the hash value of the \c CompilerInvocation.
131-
/// This should take all options affecting completion results into account.
132-
/// If the hashes between multiple completion invocation are different, we
133-
/// cannot reuse the CompilerInstance.
134-
static llvm::hash_code calculateInvocationHash(const CompilerInvocation &Inv) {
135-
llvm::hash_code hash(0);
136-
137-
auto &frontendOpts = Inv.getFrontendOptions();
138-
for (const InputFile &Input : frontendOpts.InputsAndOutputs.getAllInputs())
139-
hash = llvm::hash_combine(hash, Input.file());
140-
hash = llvm::hash_combine(
141-
hash,
142-
frontendOpts.InputKind,
143-
llvm::makeArrayRef(frontendOpts.ImplicitImportModuleNames),
144-
frontendOpts.ImplicitObjCHeaderPath,
145-
frontendOpts.ModuleName,
146-
frontendOpts.PrebuiltModuleCachePath,
147-
llvm::makeArrayRef(frontendOpts.PreferInterfaceForModules),
148-
frontendOpts.ParseStdlib,
149-
frontendOpts.EnableSourceImport,
150-
frontendOpts.ImportUnderlyingModule);
151-
152-
auto &langOpts = Inv.getLangOptions();
153-
hash = llvm::hash_combine(
154-
hash,
155-
langOpts.Target.str(),
156-
llvm::VersionTuple(langOpts.EffectiveLanguageVersion).getAsString(),
157-
llvm::VersionTuple(langOpts.PackageDescriptionVersion).getAsString(),
158-
langOpts.DisableAvailabilityChecking,
159-
langOpts.EnableAccessControl,
160-
langOpts.EnableAppExtensionRestrictions,
161-
langOpts.RequireExplicitAvailability,
162-
langOpts.RequireExplicitAvailabilityTarget,
163-
langOpts.EnableObjCInterop,
164-
langOpts.EnableCXXInterop,
165-
langOpts.InferImportAsMember,
166-
langOpts.EnableSwift3ObjCInference);
167-
168-
auto &searchPathOpts = Inv.getSearchPathOptions();
169-
hash = llvm::hash_combine(
170-
hash,
171-
searchPathOpts.SDKPath,
172-
llvm::makeArrayRef(searchPathOpts.ImportSearchPaths),
173-
llvm::makeArrayRef(searchPathOpts.VFSOverlayFiles),
174-
searchPathOpts.RuntimeResourcePath,
175-
llvm::makeArrayRef(searchPathOpts.RuntimeLibraryImportPaths),
176-
llvm::makeArrayRef(searchPathOpts.SkipRuntimeLibraryImportPaths));
177-
for (auto &P : searchPathOpts.FrameworkSearchPaths)
178-
hash = llvm::hash_combine(hash, P.IsSystem, P.Path);
179-
180-
auto &clangOpts = Inv.getClangImporterOptions();
181-
hash = llvm::hash_combine(
182-
hash,
183-
clangOpts.ModuleCachePath,
184-
llvm::makeArrayRef(clangOpts.ExtraArgs),
185-
clangOpts.OverrideResourceDir,
186-
clangOpts.TargetCPU,
187-
static_cast<uint8_t>(clangOpts.Mode),
188-
clangOpts.ImportForwardDeclarations,
189-
clangOpts.InferImportAsMember,
190-
clangOpts.DisableSwiftBridgeAttr,
191-
clangOpts.DisableOverlayModules);
192-
193-
return hash;
194-
}
195-
196130
} // namespace
197131

198132
CompilerInstance *CompletionInstance::getCachedCompilerInstance(
199-
const swift::CompilerInvocation &Invocation,
133+
const swift::CompilerInvocation &Invocation, llvm::hash_code ArgsHash,
200134
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
201135
DiagnosticConsumer *DiagC) {
202136
if (!EnableASTCaching)
@@ -210,8 +144,7 @@ CompilerInstance *CompletionInstance::getCachedCompilerInstance(
210144
if (!CachedCI)
211145
return nullptr;
212146

213-
if (calculateInvocationHash(Invocation) !=
214-
calculateInvocationHash(CachedCI->getInvocation()))
147+
if (ArgsHash != CachedArgsHash)
215148
return nullptr;
216149

217150
auto &oldState = CachedCI->getPersistentParserState();
@@ -307,12 +240,13 @@ CompilerInstance *CompletionInstance::getCachedCompilerInstance(
307240
}
308241

309242
CompilerInstance *CompletionInstance::renewCompilerInstance(
310-
swift::CompilerInvocation &Invocation,
243+
swift::CompilerInvocation &Invocation, llvm::hash_code ArgsHash,
311244
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
312245
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
313246
std::string &Error, DiagnosticConsumer *DiagC) {
314247
CachedCI.reset();
315248
CachedCI = std::make_unique<CompilerInstance>();
249+
CachedArgsHash = ArgsHash;
316250
auto *CI = CachedCI.get();
317251
if (DiagC)
318252
CachedCI->addDiagnosticConsumer(DiagC);
@@ -332,7 +266,7 @@ CompilerInstance *CompletionInstance::renewCompilerInstance(
332266
}
333267

334268
CompilerInstance *swift::ide::CompletionInstance::getCompilerInstance(
335-
swift::CompilerInvocation &Invocation,
269+
swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
336270
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
337271
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
338272
std::string &Error, DiagnosticConsumer *DiagC) {
@@ -348,12 +282,18 @@ CompilerInstance *swift::ide::CompletionInstance::getCompilerInstance(
348282
// FIXME: ASTScopeLookup doesn't support code completion yet.
349283
Invocation.disableASTScopeLookup();
350284

351-
if (auto *cached = getCachedCompilerInstance(Invocation, completionBuffer,
352-
Offset, DiagC))
285+
// Compute the signature of the invocation.
286+
llvm::hash_code ArgsHash(0);
287+
for (auto arg : Args)
288+
ArgsHash = llvm::hash_combine(ArgsHash, StringRef(arg));
289+
290+
if (auto *cached = getCachedCompilerInstance(Invocation, ArgsHash,
291+
completionBuffer, Offset, DiagC))
353292
return cached;
354293

355-
if (auto *renewed = renewCompilerInstance(
356-
Invocation, FileSystem, completionBuffer, Offset, Error, DiagC))
294+
if (auto *renewed =
295+
renewCompilerInstance(Invocation, ArgsHash, FileSystem,
296+
completionBuffer, Offset, Error, DiagC))
357297
return renewed;
358298

359299
assert(!Error.empty());

tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ static bool swiftCodeCompleteImpl(
176176
// Pin completion instance.
177177
auto CompletionInst = Lang.getCompletionInstance();
178178
CompilerInstance *CI = CompletionInst->getCompilerInstance(
179-
Invocation, FileSystem, newBuffer.get(), Offset, Error, &CIDiags);
179+
Invocation, Args, FileSystem, newBuffer.get(), Offset, Error, &CIDiags);
180180
if (!CI)
181181
return false;
182182
SWIFT_DEFER { CI->removeDiagnosticConsumer(&CIDiags); };

tools/SourceKit/lib/SwiftLang/SwiftConformingMethodList.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ static bool swiftConformingMethodListImpl(
8080
// Pin completion instance.
8181
auto CompletionInst = Lang.getCompletionInstance();
8282
CompilerInstance *CI = CompletionInst->getCompilerInstance(
83-
Invocation, FileSystem, newBuffer.get(), Offset, Error, &CIDiags);
83+
Invocation, Args, FileSystem, newBuffer.get(), Offset, Error, &CIDiags);
8484
if (!CI)
8585
return false;
8686
SWIFT_DEFER { CI->removeDiagnosticConsumer(&CIDiags); };

tools/SourceKit/lib/SwiftLang/SwiftTypeContextInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static bool swiftTypeContextInfoImpl(
7878
// Pin completion instance.
7979
auto CompletionInst = Lang.getCompletionInstance();
8080
CompilerInstance *CI = CompletionInst->getCompilerInstance(
81-
Invocation, FileSystem, newBuffer.get(), Offset, Error, &CIDiags);
81+
Invocation, Args, FileSystem, newBuffer.get(), Offset, Error, &CIDiags);
8282
if (!CI)
8383
return false;
8484
SWIFT_DEFER { CI->removeDiagnosticConsumer(&CIDiags); };

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -758,8 +758,8 @@ static bool doCodeCompletionImpl(
758758
PrintingDiagnosticConsumer PrintDiags;
759759
CompletionInstance CompletionInst;
760760
auto *CI = CompletionInst.getCompilerInstance(
761-
Invocation, llvm::vfs::getRealFileSystem(), CleanFile.get(), Offset,
762-
Error, CodeCompletionDiagnostics ? &PrintDiags : nullptr);
761+
Invocation, /*Args=*/{}, llvm::vfs::getRealFileSystem(), CleanFile.get(),
762+
Offset, Error, CodeCompletionDiagnostics ? &PrintDiags : nullptr);
763763
if (!CI)
764764
return 1;
765765

0 commit comments

Comments
 (0)