Skip to content

Commit 3434463

Browse files
committed
[CodeCompletion] Factor out actor isolation analysis
1 parent b2174da commit 3434463

File tree

1 file changed

+66
-99
lines changed

1 file changed

+66
-99
lines changed

lib/IDE/CodeCompletion.cpp

Lines changed: 66 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2516,47 +2516,15 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
25162516
return Type();
25172517
}
25182518

2519-
void addVarDeclRef(const VarDecl *VD, DeclVisibilityKind Reason,
2520-
DynamicLookupInfo dynamicLookupInfo) {
2521-
if (!VD->hasName())
2522-
return;
2523-
2524-
const Identifier Name = VD->getName();
2525-
assert(!Name.empty() && "name should not be empty");
2526-
2527-
CommandWordsPairs Pairs;
2528-
CodeCompletionResultBuilder Builder(
2529-
Sink, CodeCompletionResult::ResultKind::Declaration,
2530-
getSemanticContext(VD, Reason, dynamicLookupInfo), expectedTypeContext);
2531-
Builder.setAssociatedDecl(VD);
2532-
addLeadingDot(Builder);
2533-
addValueBaseName(Builder, Name);
2534-
setClangDeclKeywords(VD, Pairs, Builder);
2519+
void analyzeActorIsolation(
2520+
const ValueDecl *VD, Type T, bool &implicitlyAsync,
2521+
Optional<CodeCompletionResult::NotRecommendedReason> &NotRecommended) {
2522+
auto isolation = getActorIsolation(const_cast<ValueDecl *>(VD));
25352523

2536-
Optional<CodeCompletionResult::NotRecommendedReason> NotRecommended;
2537-
// "not recommended" in its own getter.
2538-
if (Kind == LookupKind::ValueInDeclContext) {
2539-
if (auto accessor = dyn_cast<AccessorDecl>(CurrDeclContext)) {
2540-
if (accessor->getStorage() == VD && accessor->isGetter())
2541-
NotRecommended = CodeCompletionResult::NoReason;
2542-
}
2543-
}
2544-
2545-
if (!VD->hasInterfaceType())
2546-
return;
2547-
2548-
// Add a type annotation.
2549-
Type VarType = getTypeOfMember(VD, dynamicLookupInfo);
2550-
2551-
bool implicitlyAsync = false;
2552-
auto isolation = getActorIsolation(const_cast<VarDecl *>(VD));
25532524
switch (isolation.getKind()) {
25542525
case ActorIsolation::ActorInstance: {
25552526
if (IsCrossActorReference) {
25562527
implicitlyAsync = true;
2557-
if (!isSendableType(CurrDeclContext, VarType)) {
2558-
NotRecommended = CodeCompletionResult::CrossActorReference;
2559-
}
25602528
// TODO: 'NotRecommended' if this is a r-value reference.
25612529
}
25622530
break;
@@ -2568,16 +2536,75 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
25682536
case ActorIsolation::Unspecified:
25692537
case ActorIsolation::Independent:
25702538
case ActorIsolation::IndependentUnsafe:
2571-
break;
2539+
return;
25722540
}
25732541

2542+
// If the reference is 'async', all types must be 'Sendable'.
2543+
if (implicitlyAsync && T) {
2544+
if (isa<VarDecl>(VD)) {
2545+
if (!isSendableType(CurrDeclContext, T)) {
2546+
NotRecommended = CodeCompletionResult::CrossActorReference;
2547+
}
2548+
} else {
2549+
assert(isa<FuncDecl>(VD) || isa<SubscriptDecl>(VD));
2550+
// Check if the result and the param types are all 'Sendable'.
2551+
auto *AFT = T->castTo<AnyFunctionType>();
2552+
if (!isSendableType(CurrDeclContext, AFT->getResult())) {
2553+
NotRecommended = CodeCompletionResult::CrossActorReference;
2554+
} else {
2555+
for (auto &param : AFT->getParams()) {
2556+
Type paramType = param.getPlainType();
2557+
if (!isSendableType(CurrDeclContext, paramType)) {
2558+
NotRecommended = CodeCompletionResult::CrossActorReference;
2559+
break;
2560+
}
2561+
}
2562+
}
2563+
}
2564+
}
2565+
}
2566+
2567+
void addVarDeclRef(const VarDecl *VD, DeclVisibilityKind Reason,
2568+
DynamicLookupInfo dynamicLookupInfo) {
2569+
if (!VD->hasName())
2570+
return;
2571+
2572+
const Identifier Name = VD->getName();
2573+
assert(!Name.empty() && "name should not be empty");
2574+
2575+
Type VarType;
2576+
if (VD->hasInterfaceType())
2577+
VarType = getTypeOfMember(VD, dynamicLookupInfo);
2578+
2579+
Optional<CodeCompletionResult::NotRecommendedReason> NotRecommended;
2580+
// "not recommended" in its own getter.
2581+
if (Kind == LookupKind::ValueInDeclContext) {
2582+
if (auto accessor = dyn_cast<AccessorDecl>(CurrDeclContext)) {
2583+
if (accessor->getStorage() == VD && accessor->isGetter())
2584+
NotRecommended = CodeCompletionResult::NoReason;
2585+
}
2586+
}
2587+
bool implicitlyAsync = false;
2588+
analyzeActorIsolation(VD, VarType, implicitlyAsync, NotRecommended);
25742589
if (!NotRecommended && implicitlyAsync && !CanCurrDeclContextHandleAsync) {
25752590
NotRecommended = CodeCompletionResult::InvalidContext;
25762591
}
25772592

2593+
CommandWordsPairs Pairs;
2594+
CodeCompletionResultBuilder Builder(
2595+
Sink, CodeCompletionResult::ResultKind::Declaration,
2596+
getSemanticContext(VD, Reason, dynamicLookupInfo), expectedTypeContext);
2597+
Builder.setAssociatedDecl(VD);
2598+
addLeadingDot(Builder);
2599+
addValueBaseName(Builder, Name);
2600+
setClangDeclKeywords(VD, Pairs, Builder);
2601+
25782602
if (NotRecommended)
25792603
Builder.setNotRecommended(*NotRecommended);
25802604

2605+
if (!VarType)
2606+
return;
2607+
25812608
if (auto *PD = dyn_cast<ParamDecl>(VD)) {
25822609
if (Name != Ctx.Id_self && PD->isInOut()) {
25832610
// It is useful to show inout for function parameters.
@@ -3013,38 +3040,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
30133040

30143041
Optional<CodeCompletionResult::NotRecommendedReason> NotRecommended;
30153042
bool implictlyAsync = false;
3016-
auto isolation = getActorIsolation(const_cast<FuncDecl *>(FD));
3017-
switch (isolation.getKind()) {
3018-
case ActorIsolation::ActorInstance: {
3019-
if (IsCrossActorReference) {
3020-
implictlyAsync = true;
3021-
3022-
// Check if the result and the param types are all concurrent values.
3023-
if (AFT) {
3024-
if (!isSendableType(CurrDeclContext, AFT->getResult())) {
3025-
NotRecommended = CodeCompletionResult::CrossActorReference;
3026-
} else {
3027-
for (auto &param : AFT->getParams()) {
3028-
Type paramType = param.getPlainType();
3029-
if (!isSendableType(CurrDeclContext, paramType)) {
3030-
NotRecommended = CodeCompletionResult::CrossActorReference;
3031-
break;
3032-
}
3033-
}
3034-
}
3035-
}
3036-
}
3037-
break;
3038-
}
3039-
case ActorIsolation::GlobalActor:
3040-
case ActorIsolation::GlobalActorUnsafe:
3041-
// TODO: implement.
3042-
break;
3043-
case ActorIsolation::Unspecified:
3044-
case ActorIsolation::Independent:
3045-
case ActorIsolation::IndependentUnsafe:
3046-
break;
3047-
}
3043+
analyzeActorIsolation(FD, AFT, implictlyAsync, NotRecommended);
30483044

30493045
if (!NotRecommended && !IsImplicitlyCurriedInstanceMethod &&
30503046
((AFT && AFT->isAsync()) || implictlyAsync) &&
@@ -3300,36 +3296,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
33003296

33013297
Optional<CodeCompletionResult::NotRecommendedReason> NotRecommended;
33023298
bool implictlyAsync = false;
3303-
auto isolation = getActorIsolation(const_cast<SubscriptDecl *>(SD));
3304-
switch (isolation.getKind()) {
3305-
case ActorIsolation::ActorInstance: {
3306-
if (IsCrossActorReference) {
3307-
implictlyAsync = true;
3308-
3309-
// Check if the result and the param types are all concurrent values.
3310-
if (!isSendableType(CurrDeclContext, subscriptType->getResult())) {
3311-
NotRecommended = CodeCompletionResult::CrossActorReference;
3312-
} else {
3313-
for (auto &param : subscriptType->getParams()) {
3314-
Type paramType = param.getPlainType();
3315-
if (!isSendableType(CurrDeclContext, paramType))
3316-
NotRecommended = CodeCompletionResult::CrossActorReference;
3317-
}
3318-
}
3319-
3320-
// TODO: 'NotRecommended' if this is a r-value reference.
3321-
}
3322-
break;
3323-
}
3324-
case ActorIsolation::GlobalActor:
3325-
case ActorIsolation::GlobalActorUnsafe:
3326-
// TODO: implement.
3327-
break;
3328-
case ActorIsolation::Unspecified:
3329-
case ActorIsolation::Independent:
3330-
case ActorIsolation::IndependentUnsafe:
3331-
break;
3332-
}
3299+
analyzeActorIsolation(SD, subscriptType, implictlyAsync, NotRecommended);
33333300

33343301
if (!NotRecommended && implictlyAsync && !CanCurrDeclContextHandleAsync) {
33353302
NotRecommended = CodeCompletionResult::InvalidContext;

0 commit comments

Comments
 (0)