Merge pull request #58999 from ahoppen/pr/cache-function-asyncness

[CodeCompletion] Cache 'async'-ness of free functions
This commit is contained in:
Alex Hoppen
2022-08-01 10:15:23 +02:00
committed by GitHub
21 changed files with 319 additions and 261 deletions

View File

@@ -17,21 +17,21 @@
ERROR(ide_async_in_nonasync_context, none,
"async %0 used in a context that does not support concurrency",
(DeclName))
(StringRef))
// NOTE: This is WARNING because this is emitted for cross actor references with
// non-'Sendable' types. That is optionally ('-warn-concurrency') warning in
// Swift 5.5.
WARNING(ide_cross_actor_reference_swift5, none,
"actor-isolated %0 should only be referenced from inside the actor",
(DeclName))
(StringRef))
WARNING(ide_redundant_import, none,
"module %0 is already imported", (DeclName))
"module %0 is already imported", (StringRef))
// FIXME: Inform which other 'import' this module came from.
NOTE(ide_redundant_import_indirect, none,
"module %0 is already imported via another module import", (DeclName))
"module %0 is already imported via another module import", (StringRef))
WARNING(ide_availability_softdeprecated, Deprecation,
"%select{getter for |setter for |}0%1 will be deprecated"
@@ -46,6 +46,10 @@ WARNING(ide_availability_softdeprecated_rename, Deprecation,
": renamed to '%6'",
(unsigned, DeclName, bool, StringRef, bool, llvm::VersionTuple, StringRef))
WARNING(ide_recursive_accessor_reference,none,
"attempting to %select{access|modify}1 %0 within its own "
"%select{getter|setter}1", (StringRef, bool))
//===----------------------------------------------------------------------===//
#define UNDEFINE_DIAGNOSTIC_MACROS

View File

@@ -30,7 +30,8 @@ public:
handleResultsAndModules(CodeCompletionContext &context,
ArrayRef<RequestedCachedModule> requestedModules,
const ExpectedTypeContext *TypeContext,
const DeclContext *DC) = 0;
const DeclContext *DC,
bool CanCurrDeclContextHandleAsync) = 0;
};
/// A simplified code completion consumer interface that clients can use to get
@@ -42,7 +43,8 @@ struct SimpleCachingCodeCompletionConsumer : public CodeCompletionConsumer {
void handleResultsAndModules(CodeCompletionContext &context,
ArrayRef<RequestedCachedModule> requestedModules,
const ExpectedTypeContext *TypeContext,
const DeclContext *DCForModules) override;
const DeclContext *DCForModules,
bool CanCurrDeclContextHandleAsync) override;
/// Clients should override this method to receive \p Results.
virtual void handleResults(CodeCompletionContext &context) = 0;

View File

@@ -329,6 +329,7 @@ class ContextFreeCodeCompletionResult {
static_assert(int(CodeCompletionOperatorKind::MAX_VALUE) < 1 << 6, "");
bool IsSystem : 1;
bool IsAsync : 1;
CodeCompletionString *CompletionString;
NullTerminatedStringRef ModuleName;
NullTerminatedStringRef BriefDocComment;
@@ -344,6 +345,10 @@ class ContextFreeCodeCompletionResult {
NullTerminatedStringRef DiagnosticMessage;
NullTerminatedStringRef FilterName;
/// If the result represents a \c ValueDecl the name by which this decl should
/// be refered to in diagnostics.
NullTerminatedStringRef NameForDiagnostics;
public:
/// Memberwise initializer. \p AssociatedKInd is opaque and will be
/// interpreted based on \p Kind. If \p KnownOperatorKind is \c None and the
@@ -355,7 +360,7 @@ public:
/// \c CodeCompletionResultSink as the result itself.
ContextFreeCodeCompletionResult(
CodeCompletionResultKind Kind, uint8_t AssociatedKind,
CodeCompletionOperatorKind KnownOperatorKind, bool IsSystem,
CodeCompletionOperatorKind KnownOperatorKind, bool IsSystem, bool IsAsync,
CodeCompletionString *CompletionString,
NullTerminatedStringRef ModuleName,
NullTerminatedStringRef BriefDocComment,
@@ -364,13 +369,15 @@ public:
ContextFreeNotRecommendedReason NotRecommended,
CodeCompletionDiagnosticSeverity DiagnosticSeverity,
NullTerminatedStringRef DiagnosticMessage,
NullTerminatedStringRef FilterName)
NullTerminatedStringRef FilterName,
NullTerminatedStringRef NameForDiagnostics)
: Kind(Kind), KnownOperatorKind(KnownOperatorKind), IsSystem(IsSystem),
CompletionString(CompletionString), ModuleName(ModuleName),
BriefDocComment(BriefDocComment), AssociatedUSRs(AssociatedUSRs),
ResultType(ResultType), NotRecommended(NotRecommended),
DiagnosticSeverity(DiagnosticSeverity),
DiagnosticMessage(DiagnosticMessage), FilterName(FilterName) {
IsAsync(IsAsync), CompletionString(CompletionString),
ModuleName(ModuleName), BriefDocComment(BriefDocComment),
AssociatedUSRs(AssociatedUSRs), ResultType(ResultType),
NotRecommended(NotRecommended), DiagnosticSeverity(DiagnosticSeverity),
DiagnosticMessage(DiagnosticMessage), FilterName(FilterName),
NameForDiagnostics(NameForDiagnostics) {
this->AssociatedKind.Opaque = AssociatedKind;
assert((NotRecommended == ContextFreeNotRecommendedReason::None) ==
(DiagnosticSeverity == CodeCompletionDiagnosticSeverity::None) &&
@@ -396,7 +403,7 @@ public:
static ContextFreeCodeCompletionResult *createPatternOrBuiltInOperatorResult(
CodeCompletionResultSink &Sink, CodeCompletionResultKind Kind,
CodeCompletionString *CompletionString,
CodeCompletionOperatorKind KnownOperatorKind,
CodeCompletionOperatorKind KnownOperatorKind, bool IsAsync,
NullTerminatedStringRef BriefDocComment,
CodeCompletionResultType ResultType,
ContextFreeNotRecommendedReason NotRecommended,
@@ -431,9 +438,11 @@ public:
/// \note The caller must ensure that the \p CompletionString and all
/// \c StringRefs outlive this result, typically by storing them in the same
/// \c CodeCompletionResultSink as the result itself.
static ContextFreeCodeCompletionResult *createDeclResult(
CodeCompletionResultSink &Sink, CodeCompletionString *CompletionString,
const Decl *AssociatedDecl, NullTerminatedStringRef ModuleName,
static ContextFreeCodeCompletionResult *
createDeclResult(CodeCompletionResultSink &Sink,
CodeCompletionString *CompletionString,
const Decl *AssociatedDecl, bool IsAsync,
NullTerminatedStringRef ModuleName,
NullTerminatedStringRef BriefDocComment,
ArrayRef<NullTerminatedStringRef> AssociatedUSRs,
CodeCompletionResultType ResultType,
@@ -469,6 +478,8 @@ public:
bool isSystem() const { return IsSystem; };
bool isAsync() const { return IsAsync; };
CodeCompletionString *getCompletionString() const { return CompletionString; }
NullTerminatedStringRef getModuleName() const { return ModuleName; }
@@ -494,6 +505,10 @@ public:
NullTerminatedStringRef getFilterName() const { return FilterName; }
NullTerminatedStringRef getNameForDiagnostics() const {
return NameForDiagnostics;
}
bool isOperator() const {
if (getKind() == CodeCompletionResultKind::Declaration) {
switch (getAssociatedDeclKind()) {
@@ -531,11 +546,6 @@ class CodeCompletionResult {
ContextualNotRecommendedReason NotRecommended : 4;
static_assert(int(ContextualNotRecommendedReason::MAX_VALUE) < 1 << 4, "");
CodeCompletionDiagnosticSeverity DiagnosticSeverity : 3;
static_assert(int(CodeCompletionDiagnosticSeverity::MAX_VALUE) < 1 << 3, "");
NullTerminatedStringRef DiagnosticMessage;
/// The number of bytes to the left of the code completion point that
/// should be erased first if this completion string is inserted in the
/// editor buffer.
@@ -556,14 +566,10 @@ private:
SemanticContextKind SemanticContext,
CodeCompletionFlair Flair, uint8_t NumBytesToErase,
CodeCompletionResultTypeRelation TypeDistance,
ContextualNotRecommendedReason NotRecommended,
CodeCompletionDiagnosticSeverity DiagnosticSeverity,
NullTerminatedStringRef DiagnosticMessage)
ContextualNotRecommendedReason NotRecommended)
: ContextFree(ContextFree), SemanticContext(SemanticContext),
Flair(Flair.toRaw()), NotRecommended(NotRecommended),
DiagnosticSeverity(DiagnosticSeverity),
DiagnosticMessage(DiagnosticMessage), NumBytesToErase(NumBytesToErase),
TypeDistance(TypeDistance) {}
NumBytesToErase(NumBytesToErase), TypeDistance(TypeDistance) {}
public:
/// Enrich a \c ContextFreeCodeCompletionResult with the following contextual
@@ -581,9 +587,8 @@ public:
const ExpectedTypeContext *TypeContext,
const DeclContext *DC,
const USRBasedTypeContext *USRTypeContext,
ContextualNotRecommendedReason NotRecommended,
CodeCompletionDiagnosticSeverity DiagnosticSeverity,
NullTerminatedStringRef DiagnosticMessage);
bool CanCurrDeclContextHandleAsync,
ContextualNotRecommendedReason NotRecommended);
const ContextFreeCodeCompletionResult &getContextFreeResult() const {
return ContextFree;
@@ -702,37 +707,23 @@ public:
return getContextFreeResult().getAssociatedUSRs();
}
/// Get the contextual diagnostic severity. This disregards context-free
/// diagnostics.
CodeCompletionDiagnosticSeverity getContextualDiagnosticSeverity() const {
return DiagnosticSeverity;
}
/// Get the contextual diagnostic severity and message. This disregards
/// context-free diagnostics.
std::pair<CodeCompletionDiagnosticSeverity, NullTerminatedStringRef>
getContextualDiagnosticSeverityAndMessage(SmallVectorImpl<char> &Scratch,
const ASTContext &Ctx) const;
/// Get the contextual diagnostic message. This disregards context-free
/// diagnostics.
NullTerminatedStringRef getContextualDiagnosticMessage() const {
return DiagnosticMessage;
}
/// Return the contextual diagnostic severity if there was a contextual
/// diagnostic. If there is no contextual diagnostic, return the context-free
/// diagnostic severity.
CodeCompletionDiagnosticSeverity getDiagnosticSeverity() const {
/// Return the contextual diagnostic severity and message if there was a
/// contextual diagnostic. If there is no contextual diagnostic, return the
/// context-free diagnostic severity and message.
std::pair<CodeCompletionDiagnosticSeverity, NullTerminatedStringRef>
getDiagnosticSeverityAndMessage(SmallVectorImpl<char> &Scratch,
const ASTContext &Ctx) const {
if (NotRecommended != ContextualNotRecommendedReason::None) {
return DiagnosticSeverity;
return getContextualDiagnosticSeverityAndMessage(Scratch, Ctx);
} else {
return getContextFreeResult().getDiagnosticSeverity();
}
}
/// Return the contextual diagnostic message if there was a contextual
/// diagnostic. If there is no contextual diagnostic, return the context-free
/// diagnostic message.
NullTerminatedStringRef getDiagnosticMessage() const {
if (NotRecommended != ContextualNotRecommendedReason::None) {
return DiagnosticMessage;
} else {
return getContextFreeResult().getDiagnosticMessage();
return std::make_pair(getContextFreeResult().getDiagnosticSeverity(),
getContextFreeResult().getDiagnosticMessage());
}
}

View File

@@ -46,7 +46,7 @@ makeCodeCompletionMemoryBuffer(const llvm::MemoryBuffer *origBuf,
/// The result returned via the callback from the perform*Operation methods.
struct CompletionInstanceResult {
/// The compiler instance that is prepared for the second pass.
CompilerInstance &CI;
std::shared_ptr<CompilerInstance> CI;
/// Whether an AST was reused.
bool DidReuseAST;
/// Whether the CompletionInstance found a code completion token in the source
@@ -87,14 +87,14 @@ class CompletionInstance {
std::mutex mtx;
std::unique_ptr<CompilerInstance> CachedCI;
std::shared_ptr<CompilerInstance> CachedCI;
llvm::hash_code CachedArgHash;
llvm::sys::TimePoint<> DependencyCheckedTimestamp;
llvm::StringMap<llvm::hash_code> InMemoryDependencyHash;
unsigned CachedReuseCount = 0;
std::atomic<bool> CachedCIShouldBeInvalidated;
void cacheCompilerInstance(std::unique_ptr<CompilerInstance> CI,
void cacheCompilerInstance(std::shared_ptr<CompilerInstance> CI,
llvm::hash_code ArgsHash);
bool shouldCheckDependencies() const;

View File

@@ -254,6 +254,10 @@ public:
void setIdealExpectedType(Type Ty) { expectedTypeContext.setIdealType(Ty); }
bool canCurrDeclContextHandleAsync() const {
return CanCurrDeclContextHandleAsync;
}
void setCanCurrDeclContextHandleAsync(bool CanCurrDeclContextHandleAsync) {
this->CanCurrDeclContextHandleAsync = CanCurrDeclContextHandleAsync;
}

View File

@@ -20,8 +20,7 @@ namespace swift {
namespace ide {
struct SwiftCompletionInfo {
swift::ASTContext *swiftASTContext = nullptr;
const swift::CompilerInvocation *invocation = nullptr;
std::shared_ptr<CompilerInstance> compilerInstance = nullptr;
CodeCompletionContext *completionContext = nullptr;
};

View File

@@ -1369,7 +1369,8 @@ void swift::ide::deliverCompletionResults(
/*Sink=*/nullptr);
Consumer.handleResultsAndModules(CompletionContext, RequestedModules,
Lookup.getExpectedTypeContext(), DC);
Lookup.getExpectedTypeContext(), DC,
Lookup.canCurrDeclContextHandleAsync());
}
bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {

View File

@@ -103,7 +103,8 @@ 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 = 7; // Store whether a type can be used as attribute
static constexpr uint32_t onDiskCompletionCacheVersion =
9; // Store whether a decl is async
/// Deserializes CodeCompletionResults from \p in and stores them in \p V.
/// \see writeCacheModule.
@@ -234,11 +235,13 @@ static bool readCachedModule(llvm::MemoryBuffer *in,
auto diagSeverity =
static_cast<CodeCompletionDiagnosticSeverity>(*cursor++);
auto isSystem = static_cast<bool>(*cursor++);
auto isAsync = static_cast<bool>(*cursor++);
auto chunkIndex = read32le(cursor);
auto moduleIndex = read32le(cursor);
auto briefDocIndex = read32le(cursor);
auto diagMessageIndex = read32le(cursor);
auto filterNameIndex = read32le(cursor);
auto nameForDiagnosticsIndex = read32le(cursor);
auto assocUSRCount = read32le(cursor);
SmallVector<NullTerminatedStringRef, 4> assocUSRs;
@@ -258,13 +261,14 @@ static bool readCachedModule(llvm::MemoryBuffer *in,
auto briefDocComment = getString(briefDocIndex);
auto diagMessage = getString(diagMessageIndex);
auto filterName = getString(filterNameIndex);
auto nameForDiagnostics = getString(nameForDiagnosticsIndex);
ContextFreeCodeCompletionResult *result =
new (*V.Allocator) ContextFreeCodeCompletionResult(
kind, associatedKind, opKind, isSystem, string, moduleName,
kind, associatedKind, opKind, isSystem, isAsync, string, moduleName,
briefDocComment, makeArrayRef(assocUSRs).copy(*V.Allocator),
CodeCompletionResultType(resultTypes), notRecommended, diagSeverity,
diagMessage, filterName);
diagMessage, filterName, nameForDiagnostics);
V.Results.push_back(result);
}
@@ -420,12 +424,14 @@ static void writeCachedModule(llvm::raw_ostream &out,
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->isAsync()));
LE.write(
static_cast<uint32_t>(addCompletionString(R->getCompletionString())));
LE.write(addString(R->getModuleName())); // index into strings
LE.write(addString(R->getBriefDocComment())); // index into strings
LE.write(addString(R->getDiagnosticMessage())); // index into strings
LE.write(addString(R->getFilterName())); // index into strings
LE.write(addString(R->getNameForDiagnostics())); // index into strings
LE.write(static_cast<uint32_t>(R->getAssociatedUSRs().size()));
for (unsigned i = 0; i < R->getAssociatedUSRs().size(); ++i) {

View File

@@ -19,7 +19,8 @@ using namespace swift::ide;
static MutableArrayRef<CodeCompletionResult *> copyCodeCompletionResults(
CodeCompletionResultSink &targetSink, CodeCompletionCache::Value &source,
bool onlyTypes, bool onlyPrecedenceGroups,
const ExpectedTypeContext *TypeContext, const DeclContext *DC) {
const ExpectedTypeContext *TypeContext, const DeclContext *DC,
bool CanCurrDeclContextHandleAsync) {
// We will be adding foreign results (from another sink) into TargetSink.
// TargetSink should have an owning pointer to the allocator that keeps the
@@ -87,8 +88,7 @@ static MutableArrayRef<CodeCompletionResult *> copyCodeCompletionResults(
*contextFreeResult, SemanticContextKind::OtherModule,
CodeCompletionFlair(),
/*numBytesToErase=*/0, TypeContext, DC, &USRTypeContext,
ContextualNotRecommendedReason::None,
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"");
CanCurrDeclContextHandleAsync, ContextualNotRecommendedReason::None);
targetSink.Results.push_back(contextualResult);
}
@@ -99,7 +99,8 @@ static MutableArrayRef<CodeCompletionResult *> copyCodeCompletionResults(
void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
CodeCompletionContext &context,
ArrayRef<RequestedCachedModule> requestedModules,
const ExpectedTypeContext *TypeContext, const DeclContext *DC) {
const ExpectedTypeContext *TypeContext, const DeclContext *DC,
bool CanCurrDeclContextHandleAsync) {
// Use the current SourceFile as the DeclContext so that we can use it to
// perform qualified lookup, and to get the correct visibility for
@@ -144,9 +145,9 @@ void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
context.Cache.set(R.Key, *V);
}
assert(V.hasValue());
auto newItems =
copyCodeCompletionResults(context.getResultSink(), **V, R.OnlyTypes,
R.OnlyPrecedenceGroups, TypeContext, DC);
auto newItems = copyCodeCompletionResults(
context.getResultSink(), **V, R.OnlyTypes, R.OnlyPrecedenceGroups,
TypeContext, DC, CanCurrDeclContextHandleAsync);
postProcessCompletionResults(newItems, context.CodeCompletionKind, DC,
&context.getResultSink());
}

View File

@@ -42,11 +42,12 @@ CodeCompletionDiagnosticSeverity getSeverity(DiagnosticKind DiagKind) {
}
class CodeCompletionDiagnostics {
ASTContext &Ctx;
const ASTContext &Ctx;
DiagnosticEngine &Engine;
public:
CodeCompletionDiagnostics(ASTContext &Ctx) : Ctx(Ctx), Engine(Ctx.Diags) {}
CodeCompletionDiagnostics(const ASTContext &Ctx)
: Ctx(Ctx), Engine(Ctx.Diags) {}
template <typename... ArgTypes>
bool
@@ -159,27 +160,29 @@ bool swift::ide::getContextFreeCompletionDiagnostics(
}
bool swift::ide::getContextualCompletionDiagnostics(
ContextualNotRecommendedReason Reason, const ValueDecl *D,
CodeCompletionDiagnosticSeverity &Severity, llvm::raw_ostream &Out) {
CodeCompletionDiagnostics Diag(D->getASTContext());
ContextualNotRecommendedReason Reason, StringRef NameForDiagnostics,
CodeCompletionDiagnosticSeverity &Severity, llvm::raw_ostream &Out,
const ASTContext &Ctx) {
CodeCompletionDiagnostics Diag(Ctx);
switch (Reason) {
case ContextualNotRecommendedReason::InvalidAsyncContext:
// FIXME: Could we use 'diag::async_in_nonasync_function'?
return Diag.getDiagnostics(
Severity, Out, diag::ide_async_in_nonasync_context, D->getName());
Severity, Out, diag::ide_async_in_nonasync_context, NameForDiagnostics);
case ContextualNotRecommendedReason::CrossActorReference:
return Diag.getDiagnostics(
Severity, Out, diag::ide_cross_actor_reference_swift5, D->getName());
return Diag.getDiagnostics(Severity, Out,
diag::ide_cross_actor_reference_swift5,
NameForDiagnostics);
case ContextualNotRecommendedReason::RedundantImport:
return Diag.getDiagnostics(Severity, Out, diag::ide_redundant_import,
D->getName());
NameForDiagnostics);
case ContextualNotRecommendedReason::RedundantImportIndirect:
return Diag.getDiagnostics(
Severity, Out, diag::ide_redundant_import_indirect, D->getName());
Severity, Out, diag::ide_redundant_import_indirect, NameForDiagnostics);
case ContextualNotRecommendedReason::VariableUsedInOwnDefinition:
return Diag.getDiagnostics(
Severity, Out, diag::recursive_accessor_reference,
D->getName().getBaseIdentifier(), /*"getter"*/ 0);
return Diag.getDiagnostics(Severity, Out,
diag::ide_recursive_accessor_reference,
NameForDiagnostics, /*"getter"*/ 0);
case ContextualNotRecommendedReason::None:
llvm_unreachable("invalid not recommended reason");
}

View File

@@ -29,13 +29,17 @@ bool getContextFreeCompletionDiagnostics(
ContextFreeNotRecommendedReason reason, const ValueDecl *D,
CodeCompletionDiagnosticSeverity &severity, llvm::raw_ostream &Out);
/// Populate \p severity and \p Out with the contextual diagnostics for \p D.
/// Populate \p severity and \p Out with the contextual for \p reason.
/// \p NameForDiagnostic is the name of the decl that produced this diagnostic.
/// \p Ctx is a context that's purely used to have a reference to a diagnostic
/// engine.
/// See \c NotRecommendedReason for an explaination of context-free vs.
/// contextual diagnostics.
/// Returns \c true if it fails to generate the diagnostics.
bool getContextualCompletionDiagnostics(
ContextualNotRecommendedReason reason, const ValueDecl *D,
CodeCompletionDiagnosticSeverity &severity, llvm::raw_ostream &Out);
ContextualNotRecommendedReason Reason, StringRef NameForDiagnostics,
CodeCompletionDiagnosticSeverity &Severity, llvm::raw_ostream &Out,
const ASTContext &Ctx);
} // namespace ide
} // namespace swift

View File

@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "swift/IDE/CodeCompletionResult.h"
#include "CodeCompletionDiagnostics.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Module.h"
#include "swift/IDE/CodeCompletionResultPrinter.h"
@@ -25,7 +26,7 @@ ContextFreeCodeCompletionResult *
ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult(
CodeCompletionResultSink &Sink, CodeCompletionResultKind Kind,
CodeCompletionString *CompletionString,
CodeCompletionOperatorKind KnownOperatorKind,
CodeCompletionOperatorKind KnownOperatorKind, bool IsAsync,
NullTerminatedStringRef BriefDocComment,
CodeCompletionResultType ResultType,
ContextFreeNotRecommendedReason NotRecommended,
@@ -34,12 +35,20 @@ ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult(
if (Sink.shouldProduceContextFreeResults()) {
ResultType = ResultType.usrBasedType(Sink.getUSRTypeArena());
}
NullTerminatedStringRef NameForDiagnostics;
if (KnownOperatorKind == CodeCompletionOperatorKind::None) {
NameForDiagnostics = "function";
} else {
NameForDiagnostics = "operator";
}
return new (Sink.getAllocator()) ContextFreeCodeCompletionResult(
Kind, /*AssociatedKind=*/0, KnownOperatorKind,
/*IsSystem=*/false, CompletionString, /*ModuleName=*/"", BriefDocComment,
/*IsSystem=*/false, IsAsync, CompletionString,
/*ModuleName=*/"", BriefDocComment,
/*AssociatedUSRs=*/{}, ResultType, NotRecommended, DiagnosticSeverity,
DiagnosticMessage,
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()));
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()),
NameForDiagnostics);
}
ContextFreeCodeCompletionResult *
@@ -53,11 +62,13 @@ ContextFreeCodeCompletionResult::createKeywordResult(
}
return new (Sink.getAllocator()) ContextFreeCodeCompletionResult(
CodeCompletionResultKind::Keyword, static_cast<uint8_t>(Kind),
CodeCompletionOperatorKind::None, /*IsSystem=*/false, CompletionString,
CodeCompletionOperatorKind::None, /*IsSystem=*/false, /*IsAsync=*/false,
CompletionString,
/*ModuleName=*/"", BriefDocComment,
/*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None,
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"",
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()));
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()),
/*NameForDiagnostics=*/"");
}
ContextFreeCodeCompletionResult *
@@ -71,18 +82,35 @@ ContextFreeCodeCompletionResult::createLiteralResult(
return new (Sink.getAllocator()) ContextFreeCodeCompletionResult(
CodeCompletionResultKind::Literal, static_cast<uint8_t>(LiteralKind),
CodeCompletionOperatorKind::None,
/*IsSystem=*/false, CompletionString, /*ModuleName=*/"",
/*IsSystem=*/false, /*IsAsync=*/false, CompletionString,
/*ModuleName=*/"",
/*BriefDocComment=*/"",
/*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None,
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"",
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()));
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()),
/*NameForDiagnostics=*/"");
}
static NullTerminatedStringRef
getDeclNameForDiagnostics(const Decl *D, CodeCompletionResultSink &Sink) {
if (auto VD = dyn_cast<ValueDecl>(D)) {
llvm::SmallString<64> Name;
llvm::raw_svector_ostream NameOS(Name);
NameOS << "'";
llvm::SmallString<64> Scratch;
VD->getName().printPretty(NameOS);
NameOS << "'";
return NullTerminatedStringRef(NameOS.str(), Sink.getAllocator());
} else {
return "";
}
}
ContextFreeCodeCompletionResult *
ContextFreeCodeCompletionResult::createDeclResult(
CodeCompletionResultSink &Sink, CodeCompletionString *CompletionString,
const Decl *AssociatedDecl, NullTerminatedStringRef ModuleName,
NullTerminatedStringRef BriefDocComment,
const Decl *AssociatedDecl, bool IsAsync,
NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment,
ArrayRef<NullTerminatedStringRef> AssociatedUSRs,
CodeCompletionResultType ResultType,
ContextFreeNotRecommendedReason NotRecommended,
@@ -96,9 +124,10 @@ ContextFreeCodeCompletionResult::createDeclResult(
CodeCompletionResultKind::Declaration,
static_cast<uint8_t>(getCodeCompletionDeclKind(AssociatedDecl)),
CodeCompletionOperatorKind::None, getDeclIsSystem(AssociatedDecl),
CompletionString, ModuleName, BriefDocComment, AssociatedUSRs, ResultType,
NotRecommended, DiagnosticSeverity, DiagnosticMessage,
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()));
IsAsync, CompletionString, ModuleName, BriefDocComment, AssociatedUSRs,
ResultType, NotRecommended, DiagnosticSeverity, DiagnosticMessage,
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()),
/*NameForDiagnostics=*/getDeclNameForDiagnostics(AssociatedDecl, Sink));
}
CodeCompletionOperatorKind
@@ -262,27 +291,40 @@ bool ContextFreeCodeCompletionResult::getDeclIsSystem(const Decl *D) {
// MARK: - CodeCompletionResult
static ContextualNotRecommendedReason
getNotRecommenedReason(const ContextFreeCodeCompletionResult &ContextFree,
bool CanCurrDeclContextHandleAsync,
ContextualNotRecommendedReason ExplicitReason) {
if (ExplicitReason != ContextualNotRecommendedReason::None) {
return ExplicitReason;
}
if (ContextFree.isAsync() && !CanCurrDeclContextHandleAsync) {
return ContextualNotRecommendedReason::InvalidAsyncContext;
}
return ContextualNotRecommendedReason::None;
}
CodeCompletionResult::CodeCompletionResult(
const ContextFreeCodeCompletionResult &ContextFree,
SemanticContextKind SemanticContext, CodeCompletionFlair Flair,
uint8_t NumBytesToErase, const ExpectedTypeContext *TypeContext,
const DeclContext *DC, const USRBasedTypeContext *USRTypeContext,
ContextualNotRecommendedReason NotRecommended,
CodeCompletionDiagnosticSeverity DiagnosticSeverity,
NullTerminatedStringRef DiagnosticMessage)
bool CanCurrDeclContextHandleAsync,
ContextualNotRecommendedReason NotRecommended)
: ContextFree(ContextFree), SemanticContext(SemanticContext),
Flair(Flair.toRaw()), NotRecommended(NotRecommended),
DiagnosticSeverity(DiagnosticSeverity),
DiagnosticMessage(DiagnosticMessage), NumBytesToErase(NumBytesToErase),
Flair(Flair.toRaw()),
NotRecommended(getNotRecommenedReason(
ContextFree, CanCurrDeclContextHandleAsync, NotRecommended)),
NumBytesToErase(NumBytesToErase),
TypeDistance(ContextFree.getResultType().calculateTypeRelation(
TypeContext, DC, USRTypeContext)) {}
CodeCompletionResult *
CodeCompletionResult::withFlair(CodeCompletionFlair NewFlair,
CodeCompletionResultSink &Sink) const {
return new (*Sink.Allocator) CodeCompletionResult(
ContextFree, SemanticContext, NewFlair, NumBytesToErase, TypeDistance,
NotRecommended, DiagnosticSeverity, DiagnosticMessage);
return new (*Sink.Allocator)
CodeCompletionResult(ContextFree, SemanticContext, NewFlair,
NumBytesToErase, TypeDistance, NotRecommended);
}
CodeCompletionResult *
@@ -290,9 +332,21 @@ CodeCompletionResult::withContextFreeResultSemanticContextAndFlair(
const ContextFreeCodeCompletionResult &NewContextFree,
SemanticContextKind NewSemanticContext, CodeCompletionFlair NewFlair,
CodeCompletionResultSink &Sink) const {
return new (*Sink.Allocator) CodeCompletionResult(
NewContextFree, NewSemanticContext, NewFlair, NumBytesToErase,
TypeDistance, NotRecommended, DiagnosticSeverity, DiagnosticMessage);
return new (*Sink.Allocator)
CodeCompletionResult(NewContextFree, NewSemanticContext, NewFlair,
NumBytesToErase, TypeDistance, NotRecommended);
}
std::pair<CodeCompletionDiagnosticSeverity, NullTerminatedStringRef>
CodeCompletionResult::getContextualDiagnosticSeverityAndMessage(
SmallVectorImpl<char> &Scratch, const ASTContext &Ctx) const {
llvm::raw_svector_ostream Out(Scratch);
CodeCompletionDiagnosticSeverity Severity;
getContextualCompletionDiagnostics(
NotRecommended, ContextFree.getNameForDiagnostics(), Severity, Out, Ctx);
Out << '\0';
NullTerminatedStringRef Message(Out.str().data(), Out.str().size() - 1);
return std::make_pair(Severity, Message);
}
void CodeCompletionResult::printPrefix(raw_ostream &OS) const {

View File

@@ -128,7 +128,7 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
}
ContextFreeResult = ContextFreeCodeCompletionResult::createDeclResult(
Sink, CCS, AssociatedDecl, ModuleName,
Sink, CCS, AssociatedDecl, IsAsync, ModuleName,
NullTerminatedStringRef(BriefDocComment, Allocator),
copyAssociatedUSRs(Allocator, AssociatedDecl), ResultType,
ContextFreeNotRecReason, ContextFreeDiagnosticSeverity,
@@ -145,7 +145,7 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
case CodeCompletionResultKind::Pattern:
ContextFreeResult =
ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult(
Sink, Kind, CCS, CodeCompletionOperatorKind::None,
Sink, Kind, CCS, CodeCompletionOperatorKind::None, IsAsync,
NullTerminatedStringRef(BriefDocComment, Allocator), ResultType,
ContextFreeNotRecReason, ContextFreeDiagnosticSeverity,
ContextFreeDiagnosticMessage);
@@ -164,35 +164,9 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
*ContextFreeResult, SemanticContextKind::None, CodeCompletionFlair(),
/*NumBytesToErase=*/0, /*TypeContext=*/nullptr,
/*DC=*/nullptr, /*USRTypeContext=*/nullptr,
ContextualNotRecommendedReason::None,
CodeCompletionDiagnosticSeverity::None, "");
/*CanCurrDeclContextHandleAsync=*/false,
ContextualNotRecommendedReason::None);
} else {
CodeCompletionDiagnosticSeverity ContextualDiagnosticSeverity =
CodeCompletionDiagnosticSeverity::None;
NullTerminatedStringRef ContextualDiagnosticMessage;
if (ContextualNotRecReason != ContextualNotRecommendedReason::None) {
// FIXME: We should generate the message lazily.
//
// NOTE(rdar://95306033): dyn_cast_or_null because 'nullptr' happens in
// cases like:
//
// func test(fn: () async -> Void) { fn(#HERE#) }
//
// In this case, it's 'InvalidAsyncContext' but there's no associated decl
// because the callee is a random expression.
// FIXME: Emit a diagnostic even without an associated decl.
if (const auto *VD = dyn_cast_or_null<ValueDecl>(AssociatedDecl)) {
CodeCompletionDiagnosticSeverity severity;
SmallString<256> message;
llvm::raw_svector_ostream messageOS(message);
if (!getContextualCompletionDiagnostics(ContextualNotRecReason, VD,
severity, messageOS)) {
ContextualDiagnosticSeverity = severity;
ContextualDiagnosticMessage =
NullTerminatedStringRef(message, Allocator);
}
}
}
assert(
ContextFreeResult != nullptr &&
"ContextFreeResult should have been constructed by the switch above");
@@ -202,8 +176,8 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
// for USRTypeContext.
return new (Allocator) CodeCompletionResult(
*ContextFreeResult, SemanticContext, Flair, NumBytesToErase,
TypeContext, DC, /*USRTypeContext=*/nullptr, ContextualNotRecReason,
ContextualDiagnosticSeverity, ContextualDiagnosticMessage);
TypeContext, DC, /*USRTypeContext=*/nullptr,
CanCurrDeclContextHandleAsync, ContextualNotRecReason);
}
}

View File

@@ -43,6 +43,7 @@ class CodeCompletionResultBuilder {
CodeCompletionFlair Flair;
unsigned NumBytesToErase = 0;
const Decl *AssociatedDecl = nullptr;
bool IsAsync = false;
Optional<CodeCompletionLiteralKind> LiteralKind;
CodeCompletionKeywordKind KeywordKind = CodeCompletionKeywordKind::None;
unsigned CurrentNestingLevel = 0;
@@ -63,6 +64,7 @@ class CodeCompletionResultBuilder {
/// type relation to \c ResultType.
const ExpectedTypeContext *TypeContext = nullptr;
const DeclContext *DC = nullptr;
bool CanCurrDeclContextHandleAsync = false;
void addChunkWithText(CodeCompletionString::Chunk::ChunkKind Kind,
StringRef Text);
@@ -113,6 +115,8 @@ public:
void setAssociatedDecl(const Decl *D);
void setIsAsync(bool IsAsync) { this->IsAsync = IsAsync; }
void setLiteralKind(CodeCompletionLiteralKind kind) { LiteralKind = kind; }
void setKeywordKind(CodeCompletionKeywordKind kind) { KeywordKind = kind; }
void setContextFreeNotRecommended(ContextFreeNotRecommendedReason Reason) {
@@ -149,6 +153,10 @@ public:
this->DC = DC;
}
void setCanCurrDeclContextHandleAsync(bool CanCurrDeclContextHandleAsync) {
this->CanCurrDeclContextHandleAsync = CanCurrDeclContextHandleAsync;
}
void withNestedGroup(CodeCompletionString::Chunk::ChunkKind Kind,
llvm::function_ref<void()> body);

View File

@@ -197,15 +197,14 @@ bool CompletionInstance::performCachedOperationIfPossible(
if (CachedArgHash != ArgsHash)
return false;
auto &CI = *CachedCI;
auto *oldSF = CI.getCodeCompletionFile();
auto *oldSF = CachedCI->getCodeCompletionFile();
assert(oldSF->getBufferID());
auto *oldState = oldSF->getDelayedParserState();
assert(oldState->hasCodeCompletionDelayedDeclState());
auto &oldInfo = oldState->getCodeCompletionDelayedDeclState();
auto &SM = CI.getSourceMgr();
auto &SM = CachedCI->getSourceMgr();
auto bufferName = completionBuffer->getBufferIdentifier();
if (SM.getIdentifierForBuffer(*oldSF->getBufferID()) != bufferName)
return false;
@@ -222,7 +221,7 @@ bool CompletionInstance::performCachedOperationIfPossible(
}
if (areAnyDependentFilesInvalidated(
CI, *FileSystem, *oldSF->getBufferID(),
*CachedCI, *FileSystem, *oldSF->getBufferID(),
DependencyCheckedTimestamp, InMemoryDependencyHash))
return false;
DependencyCheckedTimestamp = std::chrono::system_clock::now();
@@ -233,10 +232,10 @@ bool CompletionInstance::performCachedOperationIfPossible(
auto tmpBufferID = tmpSM.addMemBufferCopy(completionBuffer);
tmpSM.setCodeCompletionPoint(tmpBufferID, Offset);
LangOptions langOpts = CI.getASTContext().LangOpts;
TypeCheckerOptions typeckOpts = CI.getASTContext().TypeCheckerOpts;
SILOptions silOpts = CI.getASTContext().SILOpts;
SearchPathOptions searchPathOpts = CI.getASTContext().SearchPathOpts;
LangOptions langOpts = CachedCI->getASTContext().LangOpts;
TypeCheckerOptions typeckOpts = CachedCI->getASTContext().TypeCheckerOpts;
SILOptions silOpts = CachedCI->getASTContext().SILOpts;
SearchPathOptions searchPathOpts = CachedCI->getASTContext().SearchPathOpts;
DiagnosticEngine tmpDiags(tmpSM);
ClangImporterOptions clangOpts;
symbolgraphgen::SymbolGraphOptions symbolOpts;
@@ -382,7 +381,7 @@ bool CompletionInstance::performCachedOperationIfPossible(
newM->addFile(*newSF);
// Tell the compiler instance we've replaced the main module.
CI.setMainModule(newM);
CachedCI->setMainModule(newM);
// Re-process the whole file (parsing will be lazily triggered). Still
// re-use imported modules.
@@ -407,22 +406,22 @@ bool CompletionInstance::performCachedOperationIfPossible(
// The diagnostic engine is keeping track of state which might modify
// parsing and type checking behaviour. Clear the flags.
CI.getDiags().resetHadAnyError();
CI.getASTContext().CancellationFlag = CancellationFlag;
CachedCI->getDiags().resetHadAnyError();
CachedCI->getASTContext().CancellationFlag = CancellationFlag;
if (DiagC)
CI.addDiagnosticConsumer(DiagC);
CachedCI->addDiagnosticConsumer(DiagC);
if (CancellationFlag && CancellationFlag->load(std::memory_order_relaxed)) {
Callback(CancellableResult<CompletionInstanceResult>::cancelled());
} else {
Callback(CancellableResult<CompletionInstanceResult>::success(
{CI, /*reusingASTContext=*/true,
{CachedCI, /*reusingASTContext=*/true,
/*DidFindCodeCompletionToken=*/true}));
}
if (DiagC)
CI.removeDiagnosticConsumer(DiagC);
CachedCI->removeDiagnosticConsumer(DiagC);
}
CachedReuseCount += 1;
@@ -443,7 +442,7 @@ void CompletionInstance::performNewOperation(
// If ArgsHash is None we shouldn't cache the compiler instance.
bool ShouldCacheCompilerInstance = ArgsHash.hasValue();
auto TheInstance = std::make_unique<CompilerInstance>();
auto CI = std::make_shared<CompilerInstance>();
// Track non-system dependencies in fast-completion mode to invalidate the
// compiler instance if any dependent files are modified.
@@ -451,37 +450,36 @@ void CompletionInstance::performNewOperation(
IntermoduleDepTrackingMode::ExcludeSystem;
{
auto &CI = *TheInstance;
if (DiagC)
CI.addDiagnosticConsumer(DiagC);
CI->addDiagnosticConsumer(DiagC);
SWIFT_DEFER {
if (DiagC)
CI.removeDiagnosticConsumer(DiagC);
CI->removeDiagnosticConsumer(DiagC);
};
if (FileSystem != llvm::vfs::getRealFileSystem())
CI.getSourceMgr().setFileSystem(FileSystem);
CI->getSourceMgr().setFileSystem(FileSystem);
Invocation.setCodeCompletionPoint(completionBuffer, Offset);
std::string InstanceSetupError;
if (CI.setup(Invocation, InstanceSetupError)) {
if (CI->setup(Invocation, InstanceSetupError)) {
Callback(CancellableResult<CompletionInstanceResult>::failure(
InstanceSetupError));
return;
}
CI.getASTContext().CancellationFlag = CancellationFlag;
registerIDERequestFunctions(CI.getASTContext().evaluator);
CI->getASTContext().CancellationFlag = CancellationFlag;
registerIDERequestFunctions(CI->getASTContext().evaluator);
CI.performParseAndResolveImportsOnly();
CI->performParseAndResolveImportsOnly();
bool DidFindCodeCompletionToken = CI.getCodeCompletionFile()
bool DidFindCodeCompletionToken = CI->getCodeCompletionFile()
->getDelayedParserState()
->hasCodeCompletionDelayedDeclState();
ShouldCacheCompilerInstance &= DidFindCodeCompletionToken;
auto CancellationFlag = CI.getASTContext().CancellationFlag;
auto CancellationFlag = CI->getASTContext().CancellationFlag;
if (CancellationFlag && CancellationFlag->load(std::memory_order_relaxed)) {
Callback(CancellableResult<CompletionInstanceResult>::cancelled());
// The completion instance may be in an invalid state when it's been
@@ -502,11 +500,11 @@ void CompletionInstance::performNewOperation(
// because performCachedOperationIfPossible wouldn't have an old code
// completion state to compare the new one to.
if (ShouldCacheCompilerInstance)
cacheCompilerInstance(std::move(TheInstance), *ArgsHash);
cacheCompilerInstance(std::move(CI), *ArgsHash);
}
void CompletionInstance::cacheCompilerInstance(
std::unique_ptr<CompilerInstance> CI, llvm::hash_code ArgsHash) {
std::shared_ptr<CompilerInstance> CI, llvm::hash_code ArgsHash) {
CachedCI = std::move(CI);
CachedArgHash = ArgsHash;
auto now = std::chrono::system_clock::now();
@@ -602,11 +600,9 @@ void swift::ide::CompletionInstance::codeComplete(
: ImportDep(ImportDep), CancellationFlag(CancellationFlag),
Callback(Callback) {}
void setContext(swift::ASTContext *context,
const swift::CompilerInvocation *invocation,
void setContext(std::shared_ptr<CompilerInstance> compilerInstance,
swift::ide::CodeCompletionContext *completionContext) {
SwiftContext.swiftASTContext = context;
SwiftContext.invocation = invocation;
SwiftContext.compilerInstance = std::move(compilerInstance);
SwiftContext.completionContext = completionContext;
}
void clearContext() { SwiftContext = SwiftCompletionInfo(); }
@@ -617,7 +613,7 @@ void swift::ide::CompletionInstance::codeComplete(
CancellationFlag->load(std::memory_order_relaxed)) {
Callback(ResultType::cancelled());
} else {
assert(SwiftContext.swiftASTContext);
assert(SwiftContext.compilerInstance);
Callback(ResultType::success({context.getResultSink(), SwiftContext, ImportDep}));
}
}
@@ -631,9 +627,9 @@ void swift::ide::CompletionInstance::codeComplete(
[&CompletionContext, &CancellationFlag](auto &Result,
auto DeliverTransformed) {
CompletionContext.ReusingASTContext = Result.DidReuseAST;
CompilerInstance &CI = Result.CI;
ImportDepth ImportDep{CI.getASTContext(),
CI.getInvocation().getFrontendOptions()};
std::shared_ptr<CompilerInstance> CI = Result.CI;
ImportDepth ImportDep{CI->getASTContext(),
CI->getInvocation().getFrontendOptions()};
ConsumerToCallbackAdapter Consumer(ImportDep, CancellationFlag,
DeliverTransformed);
@@ -642,17 +638,14 @@ void swift::ide::CompletionInstance::codeComplete(
Consumer));
if (!Result.DidFindCodeCompletionToken) {
SwiftCompletionInfo Info{&CI.getASTContext(),
&CI.getInvocation(),
&CompletionContext};
SwiftCompletionInfo Info{CI, &CompletionContext};
CodeCompletionResultSink ResultSink;
DeliverTransformed(ResultType::success({ResultSink, Info, ImportDep}));
return;
}
Consumer.setContext(&CI.getASTContext(), &CI.getInvocation(),
&CompletionContext);
performCodeCompletionSecondPass(*CI.getCodeCompletionFile(),
Consumer.setContext(CI, &CompletionContext);
performCodeCompletionSecondPass(*CI->getCodeCompletionFile(),
*callbacksFactory);
Consumer.clearContext();
if (!Consumer.HandleResultsCalled) {
@@ -660,9 +653,7 @@ void swift::ide::CompletionInstance::codeComplete(
// pass, we didn't receive any results. To make sure Callback
// gets called exactly once, call it manually with no results
// here.
SwiftCompletionInfo Info{&CI.getASTContext(),
&CI.getInvocation(),
&CompletionContext};
SwiftCompletionInfo Info{CI, &CompletionContext};
CodeCompletionResultSink ResultSink;
DeliverTransformed(ResultType::success({ResultSink, Info, ImportDep}));
}
@@ -724,7 +715,7 @@ void swift::ide::CompletionInstance::typeContextInfo(
}
performCodeCompletionSecondPass(
*Result.CI.getCodeCompletionFile(), *callbacksFactory);
*Result.CI->getCodeCompletionFile(), *callbacksFactory);
if (!Consumer.HandleResultsCalled) {
// If we didn't receive a handleResult call from the second
// pass, we didn't receive any results. To make sure Callback
@@ -792,7 +783,7 @@ void swift::ide::CompletionInstance::conformingMethodList(
}
performCodeCompletionSecondPass(
*Result.CI.getCodeCompletionFile(), *callbacksFactory);
*Result.CI->getCodeCompletionFile(), *callbacksFactory);
if (!Consumer.HandleResultsCalled) {
// If we didn't receive a handleResult call from the second
// pass, we didn't receive any results. To make sure Callback

View File

@@ -824,14 +824,15 @@ void CompletionLookup::addVarDeclRef(const VarDecl *VD,
}
bool implicitlyAsync = false;
analyzeActorIsolation(VD, VarType, implicitlyAsync, NotRecommended);
if (!isForCaching() && !NotRecommended && implicitlyAsync &&
!CanCurrDeclContextHandleAsync) {
NotRecommended = ContextualNotRecommendedReason::InvalidAsyncContext;
bool explicitlyAsync = false;
if (auto accessor = VD->getEffectfulGetAccessor()) {
explicitlyAsync = accessor->hasAsync();
}
CodeCompletionResultBuilder Builder(
Sink, CodeCompletionResultKind::Declaration,
getSemanticContext(VD, Reason, dynamicLookupInfo));
Builder.setIsAsync(explicitlyAsync || implicitlyAsync);
Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
Builder.setAssociatedDecl(VD);
addLeadingDot(Builder);
addValueBaseName(Builder, Name);
@@ -1228,11 +1229,8 @@ void CompletionLookup::addFunctionCallPattern(
else
addTypeAnnotation(Builder, AFT->getResult(), genericSig);
if (!isForCaching() && AFT->hasExtInfo() && AFT->isAsync() &&
!CanCurrDeclContextHandleAsync) {
Builder.setContextualNotRecommended(
ContextualNotRecommendedReason::InvalidAsyncContext);
}
Builder.setIsAsync(AFT->hasExtInfo() && AFT->isAsync());
Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
};
if (!AFD || !AFD->getInterfaceType()->is<AnyFunctionType>()) {
@@ -1346,19 +1344,14 @@ void CompletionLookup::addMethodCall(const FuncDecl *FD,
bool implictlyAsync = false;
analyzeActorIsolation(FD, AFT, implictlyAsync, NotRecommended);
if (!isForCaching() && !NotRecommended &&
!IsImplicitlyCurriedInstanceMethod &&
((AFT && AFT->isAsync()) || implictlyAsync) &&
!CanCurrDeclContextHandleAsync) {
NotRecommended = ContextualNotRecommendedReason::InvalidAsyncContext;
}
// Add the method, possibly including any default arguments.
auto addMethodImpl = [&](bool includeDefaultArgs = true,
bool trivialTrailingClosure = false) {
CodeCompletionResultBuilder Builder(
Sink, CodeCompletionResultKind::Declaration,
getSemanticContext(FD, Reason, dynamicLookupInfo));
Builder.setIsAsync(implictlyAsync || (AFT->hasExtInfo() && AFT->isAsync()));
Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
Builder.setAssociatedDecl(FD);
if (IsSuperRefExpr && CurrentMethod &&
@@ -1547,11 +1540,9 @@ void CompletionLookup::addConstructorCall(const ConstructorDecl *CD,
addTypeAnnotation(Builder, *Result, CD->getGenericSignatureOfContext());
}
if (!isForCaching() && ConstructorType->isAsync() &&
!CanCurrDeclContextHandleAsync) {
Builder.setContextualNotRecommended(
ContextualNotRecommendedReason::InvalidAsyncContext);
}
Builder.setIsAsync(ConstructorType->hasExtInfo() &&
ConstructorType->isAsync());
Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
};
if (ConstructorType && shouldAddItemWithoutDefaultArgs(CD))
@@ -1610,14 +1601,11 @@ void CompletionLookup::addSubscriptCall(const SubscriptDecl *SD,
bool implictlyAsync = false;
analyzeActorIsolation(SD, subscriptType, implictlyAsync, NotRecommended);
if (!isForCaching() && !NotRecommended && implictlyAsync &&
!CanCurrDeclContextHandleAsync) {
NotRecommended = ContextualNotRecommendedReason::InvalidAsyncContext;
}
CodeCompletionResultBuilder Builder(
Sink, CodeCompletionResultKind::Declaration,
getSemanticContext(SD, Reason, dynamicLookupInfo));
Builder.setIsAsync(implictlyAsync);
Builder.setCanCurrDeclContextHandleAsync(CanCurrDeclContextHandleAsync);
Builder.setAssociatedDecl(SD);
if (NotRecommended)

View File

@@ -20,12 +20,8 @@ import MyModule
func testSync() -> Int{
#^GLOBAL_IN_SYNC^#
// FIXME: 'globalAsyncFunc()' *should* be "NotRecommended" because it's 'async'
// The curently behavior is due to completion cache. We should remember
// 'async'-ness in the cache. (rdar://78317170)
// GLOBAL_IN_SYNC: Begin completions
// GLOBAL_IN_SYNC-DAG: Decl[FreeFunction]/OtherModule[MyModule]/TypeRelation[Convertible]: globalAsyncFunc()[' async'][#Int#];
// GLOBAL_IN_SYNC-DAG: Decl[FreeFunction]/OtherModule[MyModule]/NotRecommended/TypeRelation[Convertible]: globalAsyncFunc()[' async'][#Int#];
// GLOBAL_IN_SYNC-DAG: Decl[FreeFunction]/OtherModule[MyModule]/NotRecommended: deprecatedFunc()[#Void#];
// GLOBAL_IN_SYNC-DAG: Decl[Actor]/OtherModule[MyModule]: MyActor[#MyActor#];
// GLOBAL_IN_SYNC: End completions

View File

@@ -33,8 +33,31 @@ func testActor(obj: MyActor) async {
func testClosure(obj: (Int) async -> Void) {
obj(#^CLOSURE_CALL^#)
// FIXME: Emit diagnostics
// CLOSURE_CALL: Begin completions
// CLOSURE_CALL-DAG: Pattern/CurrModule/Flair[ArgLabels]/NotRecommended: ['(']{#Int#}[')'][' async'][#Void#]; name={{$}}
// CLOSURE_CALL-DAG: Pattern/CurrModule/Flair[ArgLabels]/NotRecommended: ['(']{#Int#}[')'][' async'][#Void#]; name=; diagnostics=error:async function used in a context that does not support concurrency
// CLOSURE_CALL: End completions
}
func test() {
struct Foo {
var value: String? {
get async { nil }
}
}
var globalValue: String? {
get async { nil }
}
let foo = Foo()
foo.#^EXPLICITLY_ASYNC_PROPERTY^#
// EXPLICITLY_ASYNC_PROPERTY: Begin completions
// EXPLICITLY_ASYNC_PROPERTY-DAG: Decl[InstanceVar]/CurrNominal/NotRecommended: value[#String?#][' async']; name=value; diagnostics=error:async 'value' used in a context that does not support concurrency
// EXPLICITLY_ASYNC_PROPERTY: End completions
#^EXPLICIT_GLOBAL_VAR^#
// EXPLICIT_GLOBAL_VAR: Begin completions
// EXPLICIT_GLOBAL_VAR-DAG: Decl[LocalVar]/Local/NotRecommended: globalValue[#String?#][' async']; name=globalValue; diagnostics=error:async 'globalValue' used in a context that does not support concurrency
// EXPLICIT_GLOBAL_VAR: End completions
}

View File

@@ -76,10 +76,11 @@ std::vector<Completion *> SourceKit::CodeCompletion::extendCompletions(
const Options &options, Completion *prefix, bool clearFlair) {
ImportDepth depth;
if (info.swiftASTContext) {
if (info.compilerInstance) {
// Build import depth map.
depth = ImportDepth(*info.swiftASTContext,
info.invocation->getFrontendOptions());
depth = ImportDepth(
info.compilerInstance->getASTContext(),
info.compilerInstance->getInvocation().getFrontendOptions());
}
if (info.completionContext)
@@ -134,16 +135,16 @@ bool SourceKit::CodeCompletion::addCustomCompletions(
auto *contextFreeResult =
ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult(
sink.swiftSink, CodeCompletionResultKind::Pattern, completionString,
CodeCompletionOperatorKind::None, /*BriefDocComment=*/"",
CodeCompletionResultType::unknown(),
CodeCompletionOperatorKind::None, /*IsAsync=*/false,
/*BriefDocComment=*/"", CodeCompletionResultType::unknown(),
ContextFreeNotRecommendedReason::None,
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"");
auto *swiftResult = new (sink.allocator) CodeCompletion::SwiftResult(
*contextFreeResult, SemanticContextKind::Local,
CodeCompletionFlairBit::ExpressionSpecific,
/*NumBytesToErase=*/0, /*TypeContext=*/nullptr, /*DC=*/nullptr,
/*USRTypeContext=*/nullptr, ContextualNotRecommendedReason::None,
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"");
/*USRTypeContext=*/nullptr, /*CanCurrDeclContextHandleAsync=*/false,
ContextualNotRecommendedReason::None);
CompletionBuilder builder(sink, *swiftResult);
builder.setCustomKind(customCompletion.Kind);
@@ -1166,15 +1167,15 @@ Completion *CompletionBuilder::finish() {
new (sink.allocator) ContextFreeCodeCompletionResult(
contextFreeBase.getKind(),
contextFreeBase.getOpaqueAssociatedKind(), opKind,
contextFreeBase.isSystem(), newCompletionString,
contextFreeBase.getModuleName(),
contextFreeBase.isSystem(), contextFreeBase.isAsync(),
newCompletionString, contextFreeBase.getModuleName(),
contextFreeBase.getBriefDocComment(),
contextFreeBase.getAssociatedUSRs(),
contextFreeBase.getResultType(),
contextFreeBase.getNotRecommendedReason(),
contextFreeBase.getDiagnosticSeverity(),
contextFreeBase.getDiagnosticMessage(),
newFilterName);
contextFreeBase.getDiagnosticMessage(), newFilterName,
contextFreeBase.getNameForDiagnostics());
newBase = base.withContextFreeResultSemanticContextAndFlair(
*contextFreeResult, semanticContext, flair, sink.swiftSink);
}

View File

@@ -910,6 +910,7 @@ static void transformAndForwardResults(
ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult(
innerSink.swiftSink, CodeCompletionResultKind::BuiltinOperator,
completionString, CodeCompletionOperatorKind::None,
/*IsAsync=*/false,
/*BriefDocComment=*/"", CodeCompletionResultType::notApplicable(),
ContextFreeNotRecommendedReason::None,
CodeCompletionDiagnosticSeverity::None,
@@ -919,8 +920,8 @@ static void transformAndForwardResults(
CodeCompletionFlairBit::ExpressionSpecific,
exactMatch ? exactMatch->getNumBytesToErase() : 0,
/*TypeContext=*/nullptr, /*DC=*/nullptr, /*USRTypeContext=*/nullptr,
ContextualNotRecommendedReason::None,
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"");
/*CanCurrDeclContextHandleAsync=*/false,
ContextualNotRecommendedReason::None);
SwiftCompletionInfo info;
std::vector<Completion *> extended = extendCompletions(

View File

@@ -1087,11 +1087,10 @@ doConformingMethodList(const CompilerInvocation &InitInvok,
});
}
static void
printCodeCompletionResultsImpl(ArrayRef<CodeCompletionResult *> Results,
llvm::raw_ostream &OS, bool IncludeKeywords,
bool IncludeComments, bool IncludeSourceText,
bool PrintAnnotatedDescription) {
static void printCodeCompletionResultsImpl(
ArrayRef<CodeCompletionResult *> Results, llvm::raw_ostream &OS,
bool IncludeKeywords, bool IncludeComments, bool IncludeSourceText,
bool PrintAnnotatedDescription, const ASTContext &Ctx) {
unsigned NumResults = 0;
for (auto Result : Results) {
if (!IncludeKeywords &&
@@ -1134,10 +1133,13 @@ printCodeCompletionResultsImpl(ArrayRef<CodeCompletionResult *> Results,
OS << "; comment=" << comment;
}
if (Result->getDiagnosticSeverity() !=
SmallString<256> Scratch;
auto DiagSeverityAndMessage =
Result->getDiagnosticSeverityAndMessage(Scratch, Ctx);
if (DiagSeverityAndMessage.first !=
CodeCompletionDiagnosticSeverity::None) {
OS << "; diagnostics=" << comment;
switch (Result->getDiagnosticSeverity()) {
switch (DiagSeverityAndMessage.first) {
case CodeCompletionDiagnosticSeverity::Error:
OS << "error";
break;
@@ -1153,7 +1155,8 @@ printCodeCompletionResultsImpl(ArrayRef<CodeCompletionResult *> Results,
case CodeCompletionDiagnosticSeverity::None:
llvm_unreachable("none");
}
OS << ":" << Result->getDiagnosticMessage();
SmallString<256> Scratch;
OS << ":" << DiagSeverityAndMessage.second;
}
OS << "\n";
@@ -1169,7 +1172,8 @@ static int printCodeCompletionResults(
CancellableResult, [&](CodeCompleteResult &Result) {
printCodeCompletionResultsImpl(
Result.ResultSink.Results, llvm::outs(), IncludeKeywords,
IncludeComments, IncludeSourceText, PrintAnnotatedDescription);
IncludeComments, IncludeSourceText, PrintAnnotatedDescription,
Result.Info.compilerInstance->getASTContext());
return 0;
});
}
@@ -1545,10 +1549,11 @@ static int doBatchCodeCompletion(const CompilerInvocation &InitInvok,
case CancellableResultKind::Success: {
wasASTContextReused =
Result->Info.completionContext->ReusingASTContext;
printCodeCompletionResultsImpl(Result->ResultSink.Results, OS,
IncludeKeywords, IncludeComments,
IncludeSourceText,
CodeCompletionAnnotateResults);
printCodeCompletionResultsImpl(
Result->ResultSink.Results, OS, IncludeKeywords,
IncludeComments, IncludeSourceText,
CodeCompletionAnnotateResults,
Result->Info.compilerInstance->getASTContext());
break;
}
case CancellableResultKind::Failure:
@@ -4227,14 +4232,16 @@ int main(int argc, char *argv[]) {
*contextFreeResult, SemanticContextKind::OtherModule,
CodeCompletionFlair(),
/*numBytesToErase=*/0, /*TypeContext=*/nullptr, /*DC=*/nullptr,
/*USRTypeContext=*/nullptr, ContextualNotRecommendedReason::None,
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"");
/*USRTypeContext=*/nullptr, /*CanCurrDeclContextHandleAsync=*/false,
ContextualNotRecommendedReason::None);
contextualResults.push_back(contextualResult);
}
auto CompInstance = std::make_unique<CompilerInstance>();
printCodeCompletionResultsImpl(
contextualResults, llvm::outs(), options::CodeCompletionKeywords,
options::CodeCompletionComments, options::CodeCompletionSourceText,
options::CodeCompletionAnnotateResults);
options::CodeCompletionAnnotateResults,
CompInstance->getASTContext());
}
return 0;