[Code Completion] Split code completion results into context free part that can be cached and contextual part displayed to the user

This allows makes the distinction between cachable and non-cachable properties cleaner and allows us to more easily compute contextual information (like type relations) for cached items later.
This commit is contained in:
Alex Hoppen
2022-01-14 16:26:32 +01:00
parent bad96793f8
commit fd72674a57
11 changed files with 693 additions and 433 deletions

View File

@@ -41,7 +41,7 @@ namespace swift {
struct CacheValueCostInfo<swift::ide::CodeCompletionCacheImpl::Value> {
static size_t
getCost(const swift::ide::CodeCompletionCacheImpl::Value &V) {
return V.Sink.Allocator->getTotalMemory();
return V.Allocator->getTotalMemory();
}
};
} // namespace sys
@@ -102,7 +102,7 @@ CodeCompletionCache::~CodeCompletionCache() {}
///
/// This should be incremented any time we commit a change to the format of the
/// cached results. This isn't expected to change very often.
static constexpr uint32_t onDiskCompletionCacheVersion = 3; // Removed "source file path".
static constexpr uint32_t onDiskCompletionCacheVersion = 4; // Store ContextFreeCodeCompletionResults in cache
/// Deserializes CodeCompletionResults from \p in and stores them in \p V.
/// \see writeCacheModule.
@@ -166,7 +166,7 @@ static bool readCachedModule(llvm::MemoryBuffer *in,
const char *p = strings + index;
auto size = read32le(p);
auto str = copyString(*V.Sink.Allocator, StringRef(p, size));
auto str = copyString(*V.Allocator, StringRef(p, size));
knownStrings[index] = str;
return str;
};
@@ -192,20 +192,19 @@ static bool readCachedModule(llvm::MemoryBuffer *in,
}
}
return CodeCompletionString::create(*V.Sink.Allocator, chunkList);
return CodeCompletionString::create(*V.Allocator, chunkList);
};
// RESULTS
while (cursor != resultEnd) {
auto kind = static_cast<CodeCompletionResultKind>(*cursor++);
auto declKind = static_cast<CodeCompletionDeclKind>(*cursor++);
auto associatedKind = static_cast<uint8_t>(*cursor++);
auto opKind = static_cast<CodeCompletionOperatorKind>(*cursor++);
auto context = static_cast<SemanticContextKind>(*cursor++);
auto notRecommended = static_cast<NotRecommendedReason>(*cursor++);
auto notRecommended =
static_cast<ContextFreeNotRecommendedReason>(*cursor++);
auto diagSeverity =
static_cast<CodeCompletionDiagnosticSeverity>(*cursor++);
auto isSystem = static_cast<bool>(*cursor++);
auto numBytesToErase = static_cast<unsigned>(*cursor++);
auto chunkIndex = read32le(cursor);
auto moduleIndex = read32le(cursor);
auto briefDocIndex = read32le(cursor);
@@ -222,21 +221,14 @@ static bool readCachedModule(llvm::MemoryBuffer *in,
auto briefDocComment = getString(briefDocIndex);
auto diagMessage = getString(diagMessageIndex);
CodeCompletionResult *result = nullptr;
if (kind == CodeCompletionResultKind::Declaration) {
result = new (*V.Sink.Allocator) CodeCompletionResult(
context, CodeCompletionFlair(), numBytesToErase, string, declKind,
isSystem, moduleName, notRecommended, diagSeverity, diagMessage,
briefDocComment,
copyArray(*V.Sink.Allocator, ArrayRef<StringRef>(assocUSRs)),
CodeCompletionResult::ExpectedTypeRelation::Unknown, opKind);
} else {
result = new (*V.Sink.Allocator) CodeCompletionResult(
kind, context, CodeCompletionFlair(), numBytesToErase, string,
CodeCompletionResult::ExpectedTypeRelation::NotApplicable, opKind);
}
ContextFreeCodeCompletionResult *result =
new (*V.Allocator) ContextFreeCodeCompletionResult(
kind, associatedKind, opKind, isSystem, string, moduleName,
briefDocComment,
copyArray(*V.Allocator, ArrayRef<StringRef>(assocUSRs)),
notRecommended, diagSeverity, diagMessage);
V.Sink.Results.push_back(result);
V.Results.push_back(result);
}
return true;
@@ -342,27 +334,18 @@ static void writeCachedModule(llvm::raw_ostream &out,
// RESULTS
{
endian::Writer LE(results, little);
for (CodeCompletionResult *R : V.Sink.Results) {
assert(!R->getFlair().toRaw() && "Any flairs should not be cached");
assert(R->getNotRecommendedReason() !=
NotRecommendedReason::InvalidAsyncContext &&
"InvalidAsyncContext is decl context specific, cannot be cached");
for (const ContextFreeCodeCompletionResult *R : V.Results) {
// FIXME: compress bitfield
LE.write(static_cast<uint8_t>(R->getKind()));
if (R->getKind() == CodeCompletionResultKind::Declaration)
LE.write(static_cast<uint8_t>(R->getAssociatedDeclKind()));
else
LE.write(static_cast<uint8_t>(~0u));
if (R->isOperator())
LE.write(static_cast<uint8_t>(R->getOperatorKind()));
else
LE.write(static_cast<uint8_t>(R->getOpaqueAssociatedKind()));
if (R->isOperator()) {
LE.write(static_cast<uint8_t>(R->getKnownOperatorKind()));
} else {
LE.write(static_cast<uint8_t>(CodeCompletionOperatorKind::None));
LE.write(static_cast<uint8_t>(R->getSemanticContext()));
}
LE.write(static_cast<uint8_t>(R->getNotRecommendedReason()));
LE.write(static_cast<uint8_t>(R->getDiagnosticSeverity()));
LE.write(static_cast<uint8_t>(R->isSystem()));
LE.write(static_cast<uint8_t>(R->getNumBytesToErase()));
LE.write(
static_cast<uint32_t>(addCompletionString(R->getCompletionString())));
LE.write(addString(R->getModuleName())); // index into strings