Skip to content

Commit e14d3a3

Browse files
authored
Merge pull request swiftlang#74989 from hamishknight/attr-etc-6.0
[6.0] [Completion] Update type attribute completions
2 parents 32b33fb + f8542d9 commit e14d3a3

15 files changed

+164
-71
lines changed

include/swift/AST/Attr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3055,6 +3055,10 @@ class alignas(1 << AttrAlignInBits) TypeAttribute
30553055
/// Return the name (like "autoclosure") for an attribute ID.
30563056
static const char *getAttrName(TypeAttrKind kind);
30573057

3058+
/// Returns whether the given attribute is considered "user inaccessible",
3059+
/// which affects e.g whether it shows up in code completion.
3060+
static bool isUserInaccessible(TypeAttrKind DK);
3061+
30583062
static TypeAttribute *createSimple(const ASTContext &context,
30593063
TypeAttrKind kind,
30603064
SourceLoc atLoc,

include/swift/AST/TypeAttr.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,9 @@
5353
// Type attributes
5454
SIMPLE_TYPE_ATTR(autoclosure, Autoclosure)
5555
TYPE_ATTR(convention, Convention)
56-
SIMPLE_TYPE_ATTR(noescape, NoEscape)
5756
SIMPLE_TYPE_ATTR(escaping, Escaping)
5857
TYPE_ATTR(differentiable, Differentiable)
5958
SIMPLE_TYPE_ATTR(noDerivative, NoDerivative)
60-
SIMPLE_TYPE_ATTR(async, Async)
6159
SIMPLE_TYPE_ATTR(Sendable, Sendable)
6260
SIMPLE_TYPE_ATTR(retroactive, Retroactive)
6361
SIMPLE_TYPE_ATTR(unchecked, Unchecked)
@@ -68,10 +66,11 @@ TYPE_ATTR(_opaqueReturnTypeOf, OpaqueReturnTypeOf)
6866
TYPE_ATTR(isolated, Isolated)
6967

7068
// SIL-specific attributes
69+
SIMPLE_SIL_TYPE_ATTR(async, Async)
7170
SIMPLE_SIL_TYPE_ATTR(block_storage, BlockStorage)
7271
SIMPLE_SIL_TYPE_ATTR(box, Box)
7372
SIMPLE_SIL_TYPE_ATTR(dynamic_self, DynamicSelf)
74-
#define REF_STORAGE(Name, name, ...) SIMPLE_TYPE_ATTR(sil_##name, SIL##Name)
73+
#define REF_STORAGE(Name, name, ...) SIMPLE_SIL_TYPE_ATTR(sil_##name, SIL##Name)
7574
#include "swift/AST/ReferenceStorage.def"
7675
SIMPLE_SIL_TYPE_ATTR(error, Error)
7776
SIMPLE_SIL_TYPE_ATTR(error_indirect, ErrorIndirect)
@@ -83,6 +82,7 @@ SIMPLE_SIL_TYPE_ATTR(inout, Inout)
8382
SIMPLE_SIL_TYPE_ATTR(inout_aliasable, InoutAliasable)
8483
SIMPLE_SIL_TYPE_ATTR(in_guaranteed, InGuaranteed)
8584
SIMPLE_SIL_TYPE_ATTR(in_constant, InConstant)
85+
SIMPLE_SIL_TYPE_ATTR(noescape, NoEscape)
8686
SIMPLE_SIL_TYPE_ATTR(pack_owned, PackOwned)
8787
SIMPLE_SIL_TYPE_ATTR(pack_guaranteed, PackGuaranteed)
8888
SIMPLE_SIL_TYPE_ATTR(pack_inout, PackInout)

include/swift/IDE/CodeCompletionResult.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ enum class CompletionKind : uint8_t {
229229
StmtLabel,
230230
ForEachPatternBeginning,
231231
TypeAttrBeginning,
232+
TypeAttrInheritanceBeginning,
232233
OptionalBinding,
233234

234235
/// Completion after `~` in an inheritance clause.

include/swift/IDE/CompletionLookup.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
605605
void getAttributeDeclParamCompletions(CustomSyntaxAttributeKind AttrKind,
606606
int ParamIndex, bool HasLabel);
607607

608-
void getTypeAttributeKeywordCompletions();
608+
void getTypeAttributeKeywordCompletions(CompletionKind completionKind);
609609

610610
void collectPrecedenceGroups();
611611

include/swift/Parse/IDEInspectionCallbacks.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ class CodeCompletionCallbacks {
288288

289289
virtual void completeTypeAttrBeginning() {};
290290

291+
virtual void completeTypeAttrInheritanceBeginning() {};
292+
291293
virtual void completeOptionalBinding(){};
292294

293295
virtual void completeWithoutConstraintType(){};

include/swift/Parse/Parser.h

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,45 +1249,10 @@ class Parser {
12491249
return isLifetimeDependenceToken();
12501250
}
12511251

1252-
struct ParsedTypeAttributeList {
1253-
ParamDecl::Specifier Specifier = ParamDecl::Specifier::Default;
1254-
SourceLoc SpecifierLoc;
1255-
SourceLoc IsolatedLoc;
1256-
SourceLoc ConstLoc;
1257-
SourceLoc ResultDependsOnLoc;
1258-
SourceLoc SendingLoc;
1259-
SmallVector<TypeOrCustomAttr> Attributes;
1260-
SmallVector<LifetimeDependenceSpecifier> lifetimeDependenceSpecifiers;
1261-
1262-
/// Main entry point for parsing.
1263-
///
1264-
/// Inline we just have the fast path of failing to match. We call slowParse
1265-
/// that contains the outline of more complex implementation. This is HOT
1266-
/// code!
1267-
ParserStatus parse(Parser &P) {
1268-
auto &Tok = P.Tok;
1269-
if (Tok.is(tok::at_sign) || P.isParameterSpecifier())
1270-
return slowParse(P);
1271-
return makeParserSuccess();
1272-
}
1273-
1274-
TypeRepr *applyAttributesToType(Parser &P, TypeRepr *Type) const;
1275-
1276-
private:
1277-
/// An out of line implementation of the more complicated cases. This
1278-
/// ensures on the inlined fast path we handle the case of not matching.
1279-
ParserStatus slowParse(Parser &P);
1280-
};
1281-
12821252
bool parseConventionAttributeInternal(SourceLoc atLoc, SourceLoc attrLoc,
12831253
ConventionTypeAttr *&result,
12841254
bool justChecking);
12851255

1286-
ParserStatus parseTypeAttribute(TypeOrCustomAttr &result, SourceLoc AtLoc,
1287-
SourceLoc AtEndLoc,
1288-
PatternBindingInitializer *&initContext,
1289-
bool justChecking = false);
1290-
12911256
ParserStatus parseLifetimeDependenceSpecifiers(
12921257
SmallVectorImpl<LifetimeDependenceSpecifier> &specifierList);
12931258

@@ -1426,6 +1391,8 @@ class Parser {
14261391

14271392
/// Whether the type is for a closure attribute.
14281393
CustomAttribute,
1394+
/// A type in an inheritance clause.
1395+
InheritanceClause,
14291396
};
14301397

14311398
ParserResult<TypeRepr> parseTypeScalar(
@@ -1482,6 +1449,44 @@ class Parser {
14821449
/// Parse a dotted type, e.g. 'Foo<X>.Y.Z', 'P.Type', '[X].Y'.
14831450
ParserResult<TypeRepr> parseTypeDotted(ParserResult<TypeRepr> Base);
14841451

1452+
struct ParsedTypeAttributeList {
1453+
ParseTypeReason ParseReason;
1454+
ParamDecl::Specifier Specifier = ParamDecl::Specifier::Default;
1455+
SourceLoc SpecifierLoc;
1456+
SourceLoc IsolatedLoc;
1457+
SourceLoc ConstLoc;
1458+
SourceLoc ResultDependsOnLoc;
1459+
SourceLoc SendingLoc;
1460+
SmallVector<TypeOrCustomAttr> Attributes;
1461+
SmallVector<LifetimeDependenceSpecifier> lifetimeDependenceSpecifiers;
1462+
1463+
ParsedTypeAttributeList(ParseTypeReason reason) : ParseReason(reason) {}
1464+
1465+
/// Main entry point for parsing.
1466+
///
1467+
/// Inline we just have the fast path of failing to match. We call slowParse
1468+
/// that contains the outline of more complex implementation. This is HOT
1469+
/// code!
1470+
ParserStatus parse(Parser &P) {
1471+
auto &Tok = P.Tok;
1472+
if (Tok.is(tok::at_sign) || P.isParameterSpecifier())
1473+
return slowParse(P);
1474+
return makeParserSuccess();
1475+
}
1476+
1477+
TypeRepr *applyAttributesToType(Parser &P, TypeRepr *Type) const;
1478+
1479+
private:
1480+
/// An out of line implementation of the more complicated cases. This
1481+
/// ensures on the inlined fast path we handle the case of not matching.
1482+
ParserStatus slowParse(Parser &P);
1483+
};
1484+
1485+
ParserStatus parseTypeAttribute(TypeOrCustomAttr &result, SourceLoc AtLoc,
1486+
SourceLoc AtEndLoc, ParseTypeReason reason,
1487+
PatternBindingInitializer *&initContext,
1488+
bool justChecking = false);
1489+
14851490
ParserResult<TypeRepr> parseOldStyleProtocolComposition();
14861491
ParserResult<TypeRepr> parseAnyType();
14871492
ParserResult<TypeRepr> parseSILBoxType(GenericParamList *generics,

lib/AST/Attr.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,24 @@ const char *TypeAttribute::getAttrName(TypeAttrKind kind) {
145145
llvm_unreachable("unknown type attribute kind");
146146
}
147147

148+
bool TypeAttribute::isUserInaccessible(TypeAttrKind DK) {
149+
// Currently we can base this off whether it is underscored or for SIL.
150+
// TODO: We could introduce a similar options scheme to DECL_ATTR if we ever
151+
// need a user-inaccessible non-underscored attribute.
152+
switch (DK) {
153+
// SIL attributes are always considered user-inaccessible.
154+
#define SIL_TYPE_ATTR(SPELLING, C) \
155+
case TypeAttrKind::C: \
156+
return true;
157+
// For non-SIL attributes, check whether the spelling is underscored.
158+
#define TYPE_ATTR(SPELLING, C) \
159+
case TypeAttrKind::C: \
160+
return StringRef(#SPELLING).starts_with("_");
161+
#include "swift/AST/TypeAttr.def"
162+
}
163+
llvm_unreachable("unhandled case in switch!");
164+
}
165+
148166
TypeAttribute *TypeAttribute::createSimple(const ASTContext &context,
149167
TypeAttrKind kind,
150168
SourceLoc atLoc,

lib/IDE/CodeCompletion.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks,
302302
void completeStmtLabel(StmtKind ParentKind) override;
303303
void completeForEachPatternBeginning(bool hasTry, bool hasAwait) override;
304304
void completeTypeAttrBeginning() override;
305+
void completeTypeAttrInheritanceBeginning() override;
305306
void completeOptionalBinding() override;
306307
void completeWithoutConstraintType() override;
307308

@@ -654,6 +655,11 @@ void CodeCompletionCallbacksImpl::completeTypeAttrBeginning() {
654655
Kind = CompletionKind::TypeAttrBeginning;
655656
}
656657

658+
void CodeCompletionCallbacksImpl::completeTypeAttrInheritanceBeginning() {
659+
CurDeclContext = P.CurDeclContext;
660+
Kind = CompletionKind::TypeAttrInheritanceBeginning;
661+
}
662+
657663
bool swift::ide::isDynamicLookup(Type T) {
658664
return T->getRValueType()->isAnyObject();
659665
}
@@ -982,6 +988,7 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
982988
case CompletionKind::PrecedenceGroup:
983989
case CompletionKind::StmtLabel:
984990
case CompletionKind::TypeAttrBeginning:
991+
case CompletionKind::TypeAttrInheritanceBeginning:
985992
case CompletionKind::OptionalBinding:
986993
case CompletionKind::WithoutConstraintType:
987994
break;
@@ -1930,14 +1937,14 @@ void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) {
19301937
Lookup.getStmtLabelCompletions(Loc, ParentStmtKind == StmtKind::Continue);
19311938
break;
19321939
}
1933-
case CompletionKind::TypeAttrBeginning: {
1934-
Lookup.getTypeAttributeKeywordCompletions();
1940+
case CompletionKind::TypeAttrBeginning:
1941+
case CompletionKind::TypeAttrInheritanceBeginning: {
1942+
Lookup.getTypeAttributeKeywordCompletions(Kind);
19351943

19361944
// Type names at attribute position after '@'.
19371945
Lookup.getTypeCompletionsInDeclContext(
19381946
P.Context.SourceMgr.getIDEInspectionTargetLoc());
19391947
break;
1940-
19411948
}
19421949
case CompletionKind::OptionalBinding: {
19431950
SourceLoc Loc = P.Context.SourceMgr.getIDEInspectionTargetLoc();

lib/IDE/CompletionLookup.cpp

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3131,18 +3131,39 @@ void CompletionLookup::getAttributeDeclParamCompletions(
31313131
}
31323132
}
31333133

3134-
void CompletionLookup::getTypeAttributeKeywordCompletions() {
3135-
auto addTypeAttr = [&](StringRef Name) {
3134+
void CompletionLookup::getTypeAttributeKeywordCompletions(
3135+
CompletionKind completionKind) {
3136+
auto addTypeAttr = [&](TypeAttrKind Kind, StringRef Name) {
3137+
if (completionKind != CompletionKind::TypeAttrInheritanceBeginning) {
3138+
switch (Kind) {
3139+
case TypeAttrKind::Retroactive:
3140+
case TypeAttrKind::Preconcurrency:
3141+
case TypeAttrKind::Unchecked:
3142+
// These attributes are only available in inheritance clasuses.
3143+
return;
3144+
default:
3145+
break;
3146+
}
3147+
}
31363148
CodeCompletionResultBuilder Builder = makeResultBuilder(
31373149
CodeCompletionResultKind::Keyword, SemanticContextKind::None);
31383150
Builder.addAttributeKeyword(Name, "Type Attribute");
31393151
};
3140-
addTypeAttr("autoclosure");
3141-
addTypeAttr("convention(swift)");
3142-
addTypeAttr("convention(block)");
3143-
addTypeAttr("convention(c)");
3144-
addTypeAttr("convention(thin)");
3145-
addTypeAttr("escaping");
3152+
3153+
// Add simple user-accessible attributes.
3154+
#define SIL_TYPE_ATTR(SPELLING, C)
3155+
#define SIMPLE_SIL_TYPE_ATTR(SPELLING, C)
3156+
#define SIMPLE_TYPE_ATTR(SPELLING, C) \
3157+
if (!TypeAttribute::isUserInaccessible(TypeAttrKind::C)) \
3158+
addTypeAttr(TypeAttrKind::C, #SPELLING);
3159+
#include "swift/AST/TypeAttr.def"
3160+
3161+
// Add non-simple cases.
3162+
addTypeAttr(TypeAttrKind::Convention, "convention(swift)");
3163+
addTypeAttr(TypeAttrKind::Convention, "convention(block)");
3164+
addTypeAttr(TypeAttrKind::Convention, "convention(c)");
3165+
addTypeAttr(TypeAttrKind::Convention, "convention(thin)");
3166+
addTypeAttr(TypeAttrKind::Isolated, "isolated(any)");
31463167
}
31473168

31483169
void CompletionLookup::collectPrecedenceGroups() {

lib/Parse/ParseDecl.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4489,7 +4489,8 @@ bool Parser::canParseTypeAttribute() {
44894489
TypeOrCustomAttr result; // ignored
44904490
PatternBindingInitializer *initContext = nullptr;
44914491
return !parseTypeAttribute(result, /*atLoc=*/SourceLoc(),
4492-
/*atEndLoc=*/SourceLoc(), initContext,
4492+
/*atEndLoc=*/SourceLoc(),
4493+
ParseTypeReason::Unspecified, initContext,
44934494
/*justChecking*/ true)
44944495
.isError();
44954496
}
@@ -4690,6 +4691,7 @@ bool Parser::parseUUIDString(UUID &uuid, Diag<> diagnostic, bool justChecking) {
46904691
/// no need to actually record the attribute
46914692
ParserStatus Parser::parseTypeAttribute(TypeOrCustomAttr &result,
46924693
SourceLoc AtLoc, SourceLoc AtEndLoc,
4694+
ParseTypeReason reason,
46934695
PatternBindingInitializer *&initContext,
46944696
bool justChecking) {
46954697
if (AtEndLoc != Tok.getLoc()) {
@@ -4705,7 +4707,14 @@ ParserStatus Parser::parseTypeAttribute(TypeOrCustomAttr &result,
47054707
if (Tok.is(tok::code_complete)) {
47064708
if (!justChecking) {
47074709
if (CodeCompletionCallbacks) {
4708-
CodeCompletionCallbacks->completeTypeAttrBeginning();
4710+
switch (reason) {
4711+
case ParseTypeReason::InheritanceClause:
4712+
CodeCompletionCallbacks->completeTypeAttrInheritanceBeginning();
4713+
break;
4714+
default:
4715+
CodeCompletionCallbacks->completeTypeAttrBeginning();
4716+
break;
4717+
}
47094718
}
47104719
}
47114720
consumeToken(tok::code_complete);
@@ -5534,7 +5543,8 @@ ParserStatus Parser::ParsedTypeAttributeList::slowParse(Parser &P) {
55345543
TypeOrCustomAttr result;
55355544
SourceLoc AtEndLoc = Tok.getRange().getEnd();
55365545
SourceLoc AtLoc = P.consumeToken();
5537-
status |= P.parseTypeAttribute(result, AtLoc, AtEndLoc, initContext);
5546+
status |=
5547+
P.parseTypeAttribute(result, AtLoc, AtEndLoc, ParseReason, initContext);
55385548
if (status.isError())
55395549
return status;
55405550
if (result)
@@ -6803,7 +6813,8 @@ ParserStatus Parser::parseInheritance(
68036813
continue;
68046814
}
68056815

6806-
auto ParsedTypeResult = parseType();
6816+
auto ParsedTypeResult =
6817+
parseType(diag::expected_type, ParseTypeReason::InheritanceClause);
68076818
Status |= ParsedTypeResult;
68086819

68096820
// Record the type if its a single type.

lib/Parse/ParsePattern.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ SourceLoc Parser::tryCompleteFunctionParamTypeBeginning() {
177177
// Skip over any starting parameter specifiers.
178178
{
179179
CancellableBacktrackingScope backtrack(*this);
180-
ParsedTypeAttributeList attrs;
180+
ParsedTypeAttributeList attrs(ParseTypeReason::Unspecified);
181181
attrs.parse(*this);
182182
if (!Tok.is(tok::code_complete))
183183
return SourceLoc();

lib/Parse/ParseType.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,9 +399,15 @@ ParserResult<TypeRepr> Parser::parseTypeScalar(
399399
ParserStatus status;
400400

401401
// Parse attributes.
402-
ParsedTypeAttributeList parsedAttributeList;
402+
ParsedTypeAttributeList parsedAttributeList(reason);
403403
status |= parsedAttributeList.parse(*this);
404404

405+
// If we have a completion, create an ErrorType.
406+
if (status.hasCodeCompletion()) {
407+
auto *ET = ErrorTypeRepr::create(Context, PreviousLoc);
408+
return makeParserCodeCompletionResult<TypeRepr>(ET);
409+
}
410+
405411
// Parse generic parameters in SIL mode.
406412
GenericParamList *generics = nullptr;
407413
SourceLoc substitutedLoc;

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,8 @@ bool SILParser::parseSILType(SILType &Result,
11281128
}
11291129

11301130
// Parse attributes.
1131-
Parser::ParsedTypeAttributeList parsedAttrs;
1131+
Parser::ParsedTypeAttributeList parsedAttrs(
1132+
Parser::ParseTypeReason::Unspecified);
11321133
parsedAttrs.parse(P);
11331134

11341135
// Global functions are implicitly @convention(thin) if not specified otherwise.

0 commit comments

Comments
 (0)