Skip to content

Commit 290d9aa

Browse files
committed
[CodeCompletion] Compute InvalidAsyncContext warning when making a completion result contextual
Store whether a result is async in the `ContextFreeCodeCompletionResult` and determine whether an async method is used in a sync context when promoting the context free result to a contextual result. rdar://78317170
1 parent c4fff12 commit 290d9aa

14 files changed

+100
-70
lines changed

include/swift/IDE/CodeCompletionConsumer.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ class CodeCompletionConsumer {
3030
handleResultsAndModules(CodeCompletionContext &context,
3131
ArrayRef<RequestedCachedModule> requestedModules,
3232
const ExpectedTypeContext *TypeContext,
33-
const DeclContext *DC) = 0;
33+
const DeclContext *DC,
34+
bool CanCurrDeclContextHandleAsync) = 0;
3435
};
3536

3637
/// A simplified code completion consumer interface that clients can use to get
@@ -42,7 +43,8 @@ struct SimpleCachingCodeCompletionConsumer : public CodeCompletionConsumer {
4243
void handleResultsAndModules(CodeCompletionContext &context,
4344
ArrayRef<RequestedCachedModule> requestedModules,
4445
const ExpectedTypeContext *TypeContext,
45-
const DeclContext *DCForModules) override;
46+
const DeclContext *DCForModules,
47+
bool CanCurrDeclContextHandleAsync) override;
4648

4749
/// Clients should override this method to receive \p Results.
4850
virtual void handleResults(CodeCompletionContext &context) = 0;

include/swift/IDE/CodeCompletionResult.h

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ class ContextFreeCodeCompletionResult {
326326
static_assert(int(CodeCompletionOperatorKind::MAX_VALUE) < 1 << 6, "");
327327

328328
bool IsSystem : 1;
329+
bool IsAsync : 1;
329330
CodeCompletionString *CompletionString;
330331
NullTerminatedStringRef ModuleName;
331332
NullTerminatedStringRef BriefDocComment;
@@ -356,7 +357,7 @@ class ContextFreeCodeCompletionResult {
356357
/// \c CodeCompletionResultSink as the result itself.
357358
ContextFreeCodeCompletionResult(
358359
CodeCompletionResultKind Kind, uint8_t AssociatedKind,
359-
CodeCompletionOperatorKind KnownOperatorKind, bool IsSystem,
360+
CodeCompletionOperatorKind KnownOperatorKind, bool IsSystem, bool IsAsync,
360361
CodeCompletionString *CompletionString,
361362
NullTerminatedStringRef ModuleName,
362363
NullTerminatedStringRef BriefDocComment,
@@ -368,10 +369,10 @@ class ContextFreeCodeCompletionResult {
368369
NullTerminatedStringRef FilterName,
369370
NullTerminatedStringRef NameForDiagnostics)
370371
: Kind(Kind), KnownOperatorKind(KnownOperatorKind), IsSystem(IsSystem),
371-
CompletionString(CompletionString), ModuleName(ModuleName),
372-
BriefDocComment(BriefDocComment), AssociatedUSRs(AssociatedUSRs),
373-
ResultType(ResultType), NotRecommended(NotRecommended),
374-
DiagnosticSeverity(DiagnosticSeverity),
372+
IsAsync(IsAsync), CompletionString(CompletionString),
373+
ModuleName(ModuleName), BriefDocComment(BriefDocComment),
374+
AssociatedUSRs(AssociatedUSRs), ResultType(ResultType),
375+
NotRecommended(NotRecommended), DiagnosticSeverity(DiagnosticSeverity),
375376
DiagnosticMessage(DiagnosticMessage), FilterName(FilterName),
376377
NameForDiagnostics(NameForDiagnostics) {
377378
this->AssociatedKind.Opaque = AssociatedKind;
@@ -434,15 +435,17 @@ class ContextFreeCodeCompletionResult {
434435
/// \note The caller must ensure that the \p CompletionString and all
435436
/// \c StringRefs outlive this result, typically by storing them in the same
436437
/// \c CodeCompletionResultSink as the result itself.
437-
static ContextFreeCodeCompletionResult *createDeclResult(
438-
CodeCompletionResultSink &Sink, CodeCompletionString *CompletionString,
439-
const Decl *AssociatedDecl, NullTerminatedStringRef ModuleName,
440-
NullTerminatedStringRef BriefDocComment,
441-
ArrayRef<NullTerminatedStringRef> AssociatedUSRs,
442-
CodeCompletionResultType ResultType,
443-
ContextFreeNotRecommendedReason NotRecommended,
444-
CodeCompletionDiagnosticSeverity DiagnosticSeverity,
445-
NullTerminatedStringRef DiagnosticMessage);
438+
static ContextFreeCodeCompletionResult *
439+
createDeclResult(CodeCompletionResultSink &Sink,
440+
CodeCompletionString *CompletionString,
441+
const Decl *AssociatedDecl, bool IsAsync,
442+
NullTerminatedStringRef ModuleName,
443+
NullTerminatedStringRef BriefDocComment,
444+
ArrayRef<NullTerminatedStringRef> AssociatedUSRs,
445+
CodeCompletionResultType ResultType,
446+
ContextFreeNotRecommendedReason NotRecommended,
447+
CodeCompletionDiagnosticSeverity DiagnosticSeverity,
448+
NullTerminatedStringRef DiagnosticMessage);
446449

447450
CodeCompletionResultKind getKind() const { return Kind; }
448451

@@ -472,6 +475,8 @@ class ContextFreeCodeCompletionResult {
472475

473476
bool isSystem() const { return IsSystem; };
474477

478+
bool isAsync() const { return IsAsync; };
479+
475480
CodeCompletionString *getCompletionString() const { return CompletionString; }
476481

477482
NullTerminatedStringRef getModuleName() const { return ModuleName; }
@@ -579,6 +584,7 @@ class CodeCompletionResult {
579584
const ExpectedTypeContext *TypeContext,
580585
const DeclContext *DC,
581586
const USRBasedTypeContext *USRTypeContext,
587+
bool CanCurrDeclContextHandleAsync,
582588
ContextualNotRecommendedReason NotRecommended);
583589

584590
const ContextFreeCodeCompletionResult &getContextFreeResult() const {

include/swift/IDE/CompletionLookup.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
254254

255255
void setIdealExpectedType(Type Ty) { expectedTypeContext.setIdealType(Ty); }
256256

257+
bool canCurrDeclContextHandleAsync() const {
258+
return CanCurrDeclContextHandleAsync;
259+
}
260+
257261
void setCanCurrDeclContextHandleAsync(bool CanCurrDeclContextHandleAsync) {
258262
this->CanCurrDeclContextHandleAsync = CanCurrDeclContextHandleAsync;
259263
}

lib/IDE/CodeCompletion.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1359,7 +1359,8 @@ void swift::ide::deliverCompletionResults(
13591359
/*Sink=*/nullptr);
13601360

13611361
Consumer.handleResultsAndModules(CompletionContext, RequestedModules,
1362-
Lookup.getExpectedTypeContext(), DC);
1362+
Lookup.getExpectedTypeContext(), DC,
1363+
Lookup.canCurrDeclContextHandleAsync());
13631364
}
13641365

13651366
bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {

lib/IDE/CodeCompletionCache.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ CodeCompletionCache::~CodeCompletionCache() {}
104104
/// This should be incremented any time we commit a change to the format of the
105105
/// cached results. This isn't expected to change very often.
106106
static constexpr uint32_t onDiskCompletionCacheVersion =
107-
8; // Store name for diagnostics
107+
9; // Store whether a decl is async
108108

109109
/// Deserializes CodeCompletionResults from \p in and stores them in \p V.
110110
/// \see writeCacheModule.
@@ -235,6 +235,7 @@ static bool readCachedModule(llvm::MemoryBuffer *in,
235235
auto diagSeverity =
236236
static_cast<CodeCompletionDiagnosticSeverity>(*cursor++);
237237
auto isSystem = static_cast<bool>(*cursor++);
238+
auto isAsync = static_cast<bool>(*cursor++);
238239
auto chunkIndex = read32le(cursor);
239240
auto moduleIndex = read32le(cursor);
240241
auto briefDocIndex = read32le(cursor);
@@ -264,7 +265,7 @@ static bool readCachedModule(llvm::MemoryBuffer *in,
264265

265266
ContextFreeCodeCompletionResult *result =
266267
new (*V.Allocator) ContextFreeCodeCompletionResult(
267-
kind, associatedKind, opKind, isSystem, string, moduleName,
268+
kind, associatedKind, opKind, isSystem, isAsync, string, moduleName,
268269
briefDocComment, makeArrayRef(assocUSRs).copy(*V.Allocator),
269270
CodeCompletionResultType(resultTypes), notRecommended, diagSeverity,
270271
diagMessage, filterName, nameForDiagnostics);
@@ -423,6 +424,7 @@ static void writeCachedModule(llvm::raw_ostream &out,
423424
LE.write(static_cast<uint8_t>(R->getNotRecommendedReason()));
424425
LE.write(static_cast<uint8_t>(R->getDiagnosticSeverity()));
425426
LE.write(static_cast<uint8_t>(R->isSystem()));
427+
LE.write(static_cast<uint8_t>(R->isAsync()));
426428
LE.write(
427429
static_cast<uint32_t>(addCompletionString(R->getCompletionString())));
428430
LE.write(addString(R->getModuleName())); // index into strings

lib/IDE/CodeCompletionConsumer.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ using namespace swift::ide;
1919
static MutableArrayRef<CodeCompletionResult *> copyCodeCompletionResults(
2020
CodeCompletionResultSink &targetSink, CodeCompletionCache::Value &source,
2121
bool onlyTypes, bool onlyPrecedenceGroups,
22-
const ExpectedTypeContext *TypeContext, const DeclContext *DC) {
22+
const ExpectedTypeContext *TypeContext, const DeclContext *DC,
23+
bool CanCurrDeclContextHandleAsync) {
2324

2425
// We will be adding foreign results (from another sink) into TargetSink.
2526
// TargetSink should have an owning pointer to the allocator that keeps the
@@ -85,7 +86,7 @@ static MutableArrayRef<CodeCompletionResult *> copyCodeCompletionResults(
8586
*contextFreeResult, SemanticContextKind::OtherModule,
8687
CodeCompletionFlair(),
8788
/*numBytesToErase=*/0, TypeContext, DC, &USRTypeContext,
88-
ContextualNotRecommendedReason::None);
89+
CanCurrDeclContextHandleAsync, ContextualNotRecommendedReason::None);
8990
targetSink.Results.push_back(contextualResult);
9091
}
9192

@@ -96,7 +97,8 @@ static MutableArrayRef<CodeCompletionResult *> copyCodeCompletionResults(
9697
void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
9798
CodeCompletionContext &context,
9899
ArrayRef<RequestedCachedModule> requestedModules,
99-
const ExpectedTypeContext *TypeContext, const DeclContext *DC) {
100+
const ExpectedTypeContext *TypeContext, const DeclContext *DC,
101+
bool CanCurrDeclContextHandleAsync) {
100102

101103
// Use the current SourceFile as the DeclContext so that we can use it to
102104
// perform qualified lookup, and to get the correct visibility for
@@ -141,9 +143,9 @@ void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
141143
context.Cache.set(R.Key, *V);
142144
}
143145
assert(V.hasValue());
144-
auto newItems =
145-
copyCodeCompletionResults(context.getResultSink(), **V, R.OnlyTypes,
146-
R.OnlyPrecedenceGroups, TypeContext, DC);
146+
auto newItems = copyCodeCompletionResults(
147+
context.getResultSink(), **V, R.OnlyTypes, R.OnlyPrecedenceGroups,
148+
TypeContext, DC, CanCurrDeclContextHandleAsync);
147149
postProcessCompletionResults(newItems, context.CodeCompletionKind, DC,
148150
&context.getResultSink());
149151
}

lib/IDE/CodeCompletionResult.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult(
3636
}
3737
return new (Sink.getAllocator()) ContextFreeCodeCompletionResult(
3838
Kind, /*AssociatedKind=*/0, KnownOperatorKind,
39-
/*IsSystem=*/false, CompletionString, /*ModuleName=*/"", BriefDocComment,
39+
/*IsSystem=*/false, /*IsAsync=*/false, CompletionString,
40+
/*ModuleName=*/"", BriefDocComment,
4041
/*AssociatedUSRs=*/{}, ResultType, NotRecommended, DiagnosticSeverity,
4142
DiagnosticMessage,
4243
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()),
@@ -54,7 +55,8 @@ ContextFreeCodeCompletionResult::createKeywordResult(
5455
}
5556
return new (Sink.getAllocator()) ContextFreeCodeCompletionResult(
5657
CodeCompletionResultKind::Keyword, static_cast<uint8_t>(Kind),
57-
CodeCompletionOperatorKind::None, /*IsSystem=*/false, CompletionString,
58+
CodeCompletionOperatorKind::None, /*IsSystem=*/false, /*IsAsync=*/false,
59+
CompletionString,
5860
/*ModuleName=*/"", BriefDocComment,
5961
/*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None,
6062
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"",
@@ -73,7 +75,8 @@ ContextFreeCodeCompletionResult::createLiteralResult(
7375
return new (Sink.getAllocator()) ContextFreeCodeCompletionResult(
7476
CodeCompletionResultKind::Literal, static_cast<uint8_t>(LiteralKind),
7577
CodeCompletionOperatorKind::None,
76-
/*IsSystem=*/false, CompletionString, /*ModuleName=*/"",
78+
/*IsSystem=*/false, /*IsAsync=*/false, CompletionString,
79+
/*ModuleName=*/"",
7780
/*BriefDocComment=*/"",
7881
/*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None,
7982
CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"",
@@ -95,8 +98,8 @@ getDeclNameForDiagnostics(const Decl *D, CodeCompletionResultSink &Sink) {
9598
ContextFreeCodeCompletionResult *
9699
ContextFreeCodeCompletionResult::createDeclResult(
97100
CodeCompletionResultSink &Sink, CodeCompletionString *CompletionString,
98-
const Decl *AssociatedDecl, NullTerminatedStringRef ModuleName,
99-
NullTerminatedStringRef BriefDocComment,
101+
const Decl *AssociatedDecl, bool IsAsync,
102+
NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment,
100103
ArrayRef<NullTerminatedStringRef> AssociatedUSRs,
101104
CodeCompletionResultType ResultType,
102105
ContextFreeNotRecommendedReason NotRecommended,
@@ -110,8 +113,8 @@ ContextFreeCodeCompletionResult::createDeclResult(
110113
CodeCompletionResultKind::Declaration,
111114
static_cast<uint8_t>(getCodeCompletionDeclKind(AssociatedDecl)),
112115
CodeCompletionOperatorKind::None, getDeclIsSystem(AssociatedDecl),
113-
CompletionString, ModuleName, BriefDocComment, AssociatedUSRs, ResultType,
114-
NotRecommended, DiagnosticSeverity, DiagnosticMessage,
116+
IsAsync, CompletionString, ModuleName, BriefDocComment, AssociatedUSRs,
117+
ResultType, NotRecommended, DiagnosticSeverity, DiagnosticMessage,
115118
getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()),
116119
/*NameForDiagnostics=*/getDeclNameForDiagnostics(AssociatedDecl, Sink));
117120
}
@@ -277,14 +280,30 @@ bool ContextFreeCodeCompletionResult::getDeclIsSystem(const Decl *D) {
277280

278281
// MARK: - CodeCompletionResult
279282

283+
static ContextualNotRecommendedReason
284+
getNotRecommenedReason(const ContextFreeCodeCompletionResult &ContextFree,
285+
bool CanCurrDeclContextHandleAsync,
286+
ContextualNotRecommendedReason ExplicitReason) {
287+
if (ExplicitReason != ContextualNotRecommendedReason::None) {
288+
return ExplicitReason;
289+
}
290+
if (ContextFree.isAsync() && !CanCurrDeclContextHandleAsync) {
291+
return ContextualNotRecommendedReason::InvalidAsyncContext;
292+
}
293+
return ContextualNotRecommendedReason::None;
294+
}
295+
280296
CodeCompletionResult::CodeCompletionResult(
281297
const ContextFreeCodeCompletionResult &ContextFree,
282298
SemanticContextKind SemanticContext, CodeCompletionFlair Flair,
283299
uint8_t NumBytesToErase, const ExpectedTypeContext *TypeContext,
284300
const DeclContext *DC, const USRBasedTypeContext *USRTypeContext,
301+
bool CanCurrDeclContextHandleAsync,
285302
ContextualNotRecommendedReason NotRecommended)
286303
: ContextFree(ContextFree), SemanticContext(SemanticContext),
287-
Flair(Flair.toRaw()), NotRecommended(NotRecommended),
304+
Flair(Flair.toRaw()),
305+
NotRecommended(getNotRecommenedReason(
306+
ContextFree, CanCurrDeclContextHandleAsync, NotRecommended)),
288307
NumBytesToErase(NumBytesToErase),
289308
TypeDistance(ContextFree.getResultType().calculateTypeRelation(
290309
TypeContext, DC, USRTypeContext)) {}

lib/IDE/CodeCompletionResultBuilder.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
125125
}
126126

127127
ContextFreeResult = ContextFreeCodeCompletionResult::createDeclResult(
128-
Sink, CCS, AssociatedDecl, ModuleName,
128+
Sink, CCS, AssociatedDecl, IsAsync, ModuleName,
129129
NullTerminatedStringRef(BriefDocComment, Allocator),
130130
copyAssociatedUSRs(Allocator, AssociatedDecl), ResultType,
131131
ContextFreeNotRecReason, ContextFreeDiagnosticSeverity,
@@ -161,6 +161,7 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
161161
*ContextFreeResult, SemanticContextKind::None, CodeCompletionFlair(),
162162
/*NumBytesToErase=*/0, /*TypeContext=*/nullptr,
163163
/*DC=*/nullptr, /*USRTypeContext=*/nullptr,
164+
/*CanCurrDeclContextHandleAsync=*/false,
164165
ContextualNotRecommendedReason::None);
165166
} else {
166167
assert(
@@ -172,7 +173,8 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
172173
// for USRTypeContext.
173174
return new (Allocator) CodeCompletionResult(
174175
*ContextFreeResult, SemanticContext, Flair, NumBytesToErase,
175-
TypeContext, DC, /*USRTypeContext=*/nullptr, ContextualNotRecReason);
176+
TypeContext, DC, /*USRTypeContext=*/nullptr,
177+
CanCurrDeclContextHandleAsync, ContextualNotRecReason);
176178
}
177179
}
178180

lib/IDE/CodeCompletionResultBuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class CodeCompletionResultBuilder {
4343
CodeCompletionFlair Flair;
4444
unsigned NumBytesToErase = 0;
4545
const Decl *AssociatedDecl = nullptr;
46+
bool IsAsync = false;
4647
Optional<CodeCompletionLiteralKind> LiteralKind;
4748
CodeCompletionKeywordKind KeywordKind = CodeCompletionKeywordKind::None;
4849
unsigned CurrentNestingLevel = 0;
@@ -63,6 +64,7 @@ class CodeCompletionResultBuilder {
6364
/// type relation to \c ResultType.
6465
const ExpectedTypeContext *TypeContext = nullptr;
6566
const DeclContext *DC = nullptr;
67+
bool CanCurrDeclContextHandleAsync = false;
6668

6769
void addChunkWithText(CodeCompletionString::Chunk::ChunkKind Kind,
6870
StringRef Text);
@@ -113,6 +115,8 @@ class CodeCompletionResultBuilder {
113115

114116
void setAssociatedDecl(const Decl *D);
115117

118+
void setIsAsync(bool IsAsync) { this->IsAsync = IsAsync; }
119+
116120
void setLiteralKind(CodeCompletionLiteralKind kind) { LiteralKind = kind; }
117121
void setKeywordKind(CodeCompletionKeywordKind kind) { KeywordKind = kind; }
118122
void setContextFreeNotRecommended(ContextFreeNotRecommendedReason Reason) {
@@ -149,6 +153,10 @@ class CodeCompletionResultBuilder {
149153
this->DC = DC;
150154
}
151155

156+
void setCanCurrDeclContextHandleAsync(bool CanCurrDeclContextHandleAsync) {
157+
this->CanCurrDeclContextHandleAsync = CanCurrDeclContextHandleAsync;
158+
}
159+
152160
void withNestedGroup(CodeCompletionString::Chunk::ChunkKind Kind,
153161
llvm::function_ref<void()> body);
154162

0 commit comments

Comments
 (0)