Skip to content

[CodeCompletion] Completion for @storageRestrictions attribute #68603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/swift/IDE/CompletionLookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
TypeInDeclContext,
ImportFromModule,
GenericRequirement,

/// Look up stored properties within a type.
StoredProperty,
};

LookupKind Kind;
Expand Down Expand Up @@ -528,6 +531,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
void getValueExprCompletions(Type ExprType, ValueDecl *VD = nullptr,
bool IsDeclUnapplied = false);

/// Add completions for stored properties of \p D.
void getStoredPropertyCompletions(const NominalTypeDecl *D);

void collectOperators(SmallVectorImpl<OperatorDecl *> &results);

void addPostfixBang(Type resultType);
Expand Down
19 changes: 19 additions & 0 deletions include/swift/Parse/IDEInspectionCallbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,25 @@ enum class CustomSyntaxAttributeKind {
Available,
FreestandingMacro,
AttachedMacro,
StorageRestrictions
};

/// A bit of a hack. When completing inside the '@storageRestrictions'
/// attribute, we use the \c ParamIndex field to communicate where inside the
/// attribute we are performing the completion.
enum class StorageRestrictionsCompletionKind : int {
/// We are completing directly after the '(' and require a 'initializes' or
/// 'accesses' label.
Label,
/// We are completing in a context that only allows arguments (ie. accessed or
/// initialized variables) and doesn't permit an argument label.
Argument,
/// Completion in a context that allows either an argument or the
/// 'initializes' label.
ArgumentOrInitializesLabel,
/// Completion in a context that allows either an argument or the
/// 'accesses' label.
ArgumentOrAccessesLabel
};

/// Parser's interface to code completion.
Expand Down
56 changes: 56 additions & 0 deletions lib/IDE/CompletionLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,7 @@ bool CompletionLookup::isImplicitlyCurriedInstanceMethod(

switch (Kind) {
case LookupKind::ValueExpr:
case LookupKind::StoredProperty:
return ExprType->is<AnyMetatypeType>();
case LookupKind::ValueInDeclContext:
if (InsideStaticMethod)
Expand Down Expand Up @@ -2248,6 +2249,13 @@ void CompletionLookup::foundDecl(ValueDecl *D, DeclVisibilityKind Reason,
}

return;
case LookupKind::StoredProperty:
if (auto *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasStorage()) {
addVarDeclRef(VD, Reason, dynamicLookupInfo);
}
return;
}
}
}

Expand Down Expand Up @@ -2463,6 +2471,17 @@ void CompletionLookup::getValueExprCompletions(Type ExprType, ValueDecl *VD,
/*includeProtocolExtensionMembers*/ true);
}

void CompletionLookup::getStoredPropertyCompletions(const NominalTypeDecl *D) {
Kind = LookupKind::StoredProperty;
NeedLeadingDot = false;

lookupVisibleMemberDecls(*this, D->getDeclaredInterfaceType(),
/*DotLoc=*/SourceLoc(), CurrDeclContext,
/*IncludeInstanceMembers*/ true,
/*includeDerivedRequirements*/ false,
/*includeProtocolExtensionMembers*/ false);
}

void CompletionLookup::collectOperators(
SmallVectorImpl<OperatorDecl *> &results) {
assert(CurrDeclContext);
Expand Down Expand Up @@ -3051,6 +3070,43 @@ void CompletionLookup::getAttributeDeclParamCompletions(
break;
}
break;
case CustomSyntaxAttributeKind::StorageRestrictions: {
bool suggestInitializesLabel = false;
bool suggestAccessesLabel = false;
bool suggestArgument = false;
switch (static_cast<StorageRestrictionsCompletionKind>(ParamIndex)) {
case StorageRestrictionsCompletionKind::Label:
suggestAccessesLabel = true;
suggestInitializesLabel = true;
break;
case StorageRestrictionsCompletionKind::Argument:
suggestArgument = true;
break;
case StorageRestrictionsCompletionKind::ArgumentOrInitializesLabel:
suggestArgument = true;
suggestInitializesLabel = true;
break;
case StorageRestrictionsCompletionKind::ArgumentOrAccessesLabel:
suggestArgument = true;
suggestAccessesLabel = true;
break;
}
if (suggestInitializesLabel) {
addDeclAttrParamKeyword(
"initializes", /*Parameters=*/{},
"Specify stored properties initialized by the accessor", true);
}
if (suggestAccessesLabel) {
addDeclAttrParamKeyword(
"accesses", /*Parameters=*/{},
"Specify stored properties accessed by the accessor", true);
}
if (suggestArgument) {
if (auto NT = dyn_cast<NominalTypeDecl>(CurrDeclContext)) {
getStoredPropertyCompletions(NT);
}
}
}
}
}

Expand Down
Loading