Skip to content

Commit d7f41eb

Browse files
committed
[CodeCompletion] Add fake type annotation to custom attributes
Macros and custom attribute types (i.e. `@resultBuilder`, `@propertyWrapper`, and `@globalActor`) now have fake type annotations. This would be useful to recognize which candidates are actually usable in code completions after `@`. rdar://109062582
1 parent 5036112 commit d7f41eb

File tree

4 files changed

+134
-66
lines changed

4 files changed

+134
-66
lines changed

lib/IDE/CompletionLookup.cpp

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,27 @@ void CompletionLookup::addSubscriptCall(const SubscriptDecl *SD,
16691669
addTypeAnnotation(Builder, resultTy, SD->getGenericSignatureOfContext());
16701670
}
16711671

1672+
static StringRef getTypeAnnotationString(const NominalTypeDecl *NTD,
1673+
SmallVectorImpl<char> &stash) {
1674+
SmallVector<StringRef, 1> attrRoleStrs;
1675+
if (NTD->getAttrs().hasAttribute<PropertyWrapperAttr>())
1676+
attrRoleStrs.push_back("Property Wrapper");
1677+
if (NTD->getAttrs().hasAttribute<ResultBuilderAttr>())
1678+
attrRoleStrs.push_back("Result Builder");
1679+
if (NTD->isGlobalActor())
1680+
attrRoleStrs.push_back("Global Actor");
1681+
1682+
if (attrRoleStrs.empty())
1683+
return StringRef();
1684+
if (attrRoleStrs.size() == 0)
1685+
return attrRoleStrs[0];
1686+
1687+
stash.clear();
1688+
llvm::raw_svector_ostream OS(stash);
1689+
llvm::interleave(attrRoleStrs, OS, ", ");
1690+
return {stash.data(), stash.size()};
1691+
}
1692+
16721693
void CompletionLookup::addNominalTypeRef(const NominalTypeDecl *NTD,
16731694
DeclVisibilityKind Reason,
16741695
DynamicLookupInfo dynamicLookupInfo) {
@@ -1679,7 +1700,14 @@ void CompletionLookup::addNominalTypeRef(const NominalTypeDecl *NTD,
16791700
addLeadingDot(Builder);
16801701
Builder.addBaseName(NTD->getName().str());
16811702

1682-
addTypeAnnotation(Builder, NTD->getDeclaredType());
1703+
// "Fake" annotation for custom attribute types.
1704+
SmallVector<char, 0> stash;
1705+
StringRef customAttributeAnnotation = getTypeAnnotationString(NTD, stash);
1706+
if (!customAttributeAnnotation.empty()) {
1707+
Builder.addTypeAnnotation(customAttributeAnnotation);
1708+
} else {
1709+
addTypeAnnotation(Builder, NTD->getDeclaredType());
1710+
}
16831711

16841712
// Override the type relation for NominalTypes. Use the better relation
16851713
// for the metatypes and the instance type. For example,
@@ -1790,6 +1818,42 @@ void CompletionLookup::addEnumElementRef(const EnumElementDecl *EED,
17901818
Builder.addFlair(CodeCompletionFlairBit::ExpressionSpecific);
17911819
}
17921820

1821+
static StringRef getTypeAnnotationString(const MacroDecl *MD,
1822+
SmallVectorImpl<char> &stash) {
1823+
auto roles = MD->getMacroRoles();
1824+
SmallVector<StringRef, 1> roleStrs;
1825+
if (roles.contains(MacroRole::Accessor))
1826+
roleStrs.push_back("Accessor Macro");
1827+
if (roles.contains(MacroRole::CodeItem))
1828+
roleStrs.push_back("Code Item Macro");
1829+
if (roles.contains(MacroRole::Conformance))
1830+
roleStrs.push_back("Conformance Macro");
1831+
if (roles.contains(MacroRole::Declaration))
1832+
roleStrs.push_back("Declaration Macro");
1833+
if (roles.contains(MacroRole::Expression))
1834+
roleStrs.push_back("Expression Macro");
1835+
if (roles.contains(MacroRole::Extension))
1836+
roleStrs.push_back("Extension Macro");
1837+
if (roles.contains(MacroRole::Member))
1838+
roleStrs.push_back("Member Macro");
1839+
if (roles.contains(MacroRole::MemberAttribute))
1840+
roleStrs.push_back("Member Attribute Macro");
1841+
if (roles.contains(MacroRole::Extension))
1842+
roleStrs.push_back("Extension Macro");
1843+
if (roles.contains(MacroRole::Peer))
1844+
roleStrs.push_back("Peer Macro");
1845+
1846+
if (roleStrs.empty())
1847+
return "Macro";
1848+
if (roleStrs.size() == 1)
1849+
return roleStrs[0];
1850+
1851+
stash.clear();
1852+
llvm::raw_svector_ostream OS(stash);
1853+
llvm::interleave(roleStrs, OS, ", ");
1854+
return {stash.data(), stash.size()};
1855+
}
1856+
17931857
void CompletionLookup::addMacroExpansion(const MacroDecl *MD,
17941858
DeclVisibilityKind Reason) {
17951859
if (!MD->hasName() || !MD->isAccessibleFrom(CurrDeclContext) ||
@@ -1822,9 +1886,13 @@ void CompletionLookup::addMacroExpansion(const MacroDecl *MD,
18221886
Builder.addRightParen();
18231887
}
18241888

1825-
if (!MD->getResultInterfaceType()->isVoid()) {
1889+
auto roles = MD->getMacroRoles();
1890+
if (roles.containsOnly(MacroRole::Extension)) {
18261891
addTypeAnnotation(Builder, MD->getResultInterfaceType(),
18271892
MD->getGenericSignature());
1893+
} else {
1894+
llvm::SmallVector<char, 0> stash;
1895+
Builder.addTypeAnnotation(getTypeAnnotationString(MD, stash));
18281896
}
18291897
}
18301898

test/IDE/complete_decl_attribute.swift

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ actor MyGenericGlobalActor<T> {
111111
// KEYWORD2-NEXT: Keyword/None: backDeployed[#Func Attribute#]; name=backDeployed
112112
// KEYWORD2-NOT: Keyword
113113
// KEYWORD2-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
114-
// KEYWORD2-DAG: Decl[Struct]/CurrModule: MyPropertyWrapper[#MyPropertyWrapper#]; name=MyPropertyWrapper
115-
// KEYWORD2-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#MyResultBuilder#]; name=MyResultBuilder
116-
// KEYWORD2-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#MyGlobalActor#]; name=MyGlobalActor
114+
// KEYWORD2-DAG: Decl[Struct]/CurrModule: MyPropertyWrapper[#Property Wrapper#]; name=MyPropertyWrapper
115+
// KEYWORD2-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#Result Builder#]; name=MyResultBuilder
116+
// KEYWORD2-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#Global Actor#]; name=MyGlobalActor
117117

118118
@#^KEYWORD3^# class C {}
119119

@@ -186,12 +186,12 @@ actor MyGenericGlobalActor<T> {
186186
// ON_GLOBALVAR-DAG: Keyword/None: backDeployed[#Var Attribute#]; name=backDeployed
187187
// ON_GLOBALVAR-NOT: Keyword
188188
// ON_GLOBALVAR-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
189-
// ON_GLOBALVAR-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#MyPropertyWrapper#]; name=MyPropertyWrapper
190-
// ON_GLOBALVAR-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericPropertyWrapper[#MyGenericPropertyWrapper#]; name=MyGenericPropertyWrapper
191-
// ON_GLOBALVAR-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#MyResultBuilder#]; name=MyResultBuilder
192-
// ON_GLOBALVAR-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericResultBuilder[#MyGenericResultBuilder#]; name=MyGenericResultBuilder
193-
// ON_GLOBALVAR-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#MyGlobalActor#]; name=MyGlobalActor
194-
// ON_GLOBALVAR-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGenericGlobalActor[#MyGenericGlobalActor#]; name=MyGenericGlobalActor
189+
// ON_GLOBALVAR-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#Property Wrapper#]; name=MyPropertyWrapper
190+
// ON_GLOBALVAR-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericPropertyWrapper[#Property Wrapper#]; name=MyGenericPropertyWrapper
191+
// ON_GLOBALVAR-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#Result Builder#]; name=MyResultBuilder
192+
// ON_GLOBALVAR-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericResultBuilder[#Result Builder#]; name=MyGenericResultBuilder
193+
// ON_GLOBALVAR-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#Global Actor#]; name=MyGlobalActor
194+
// ON_GLOBALVAR-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGenericGlobalActor[#Global Actor#]; name=MyGenericGlobalActor
195195

196196
struct _S {
197197
@#^ON_INIT^# init()
@@ -223,12 +223,12 @@ struct _S {
223223
// ON_PROPERTY-DAG: Keyword/None: backDeployed[#Var Attribute#]; name=backDeployed
224224
// ON_PROPERTY-NOT: Keyword
225225
// ON_PROPERTY-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
226-
// ON_PROPERTY-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#MyPropertyWrapper#]; name=MyPropertyWrapper
227-
// ON_PROPERTY-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericPropertyWrapper[#MyGenericPropertyWrapper#]; name=MyGenericPropertyWrapper
228-
// ON_PROPERTY-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#MyResultBuilder#]; name=MyResultBuilder
229-
// ON_PROPERTY-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericResultBuilder[#MyGenericResultBuilder#]; name=MyGenericResultBuilder
230-
// ON_PROPERTY-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#MyGlobalActor#]; name=MyGlobalActor
231-
// ON_PROPERTY-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGenericGlobalActor[#MyGenericGlobalActor#]; name=MyGenericGlobalActor
226+
// ON_PROPERTY-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#Property Wrapper#]; name=MyPropertyWrapper
227+
// ON_PROPERTY-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericPropertyWrapper[#Property Wrapper#]; name=MyGenericPropertyWrapper
228+
// ON_PROPERTY-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#Result Builder#]; name=MyResultBuilder
229+
// ON_PROPERTY-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericResultBuilder[#Result Builder#]; name=MyGenericResultBuilder
230+
// ON_PROPERTY-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#Global Actor#]; name=MyGlobalActor
231+
// ON_PROPERTY-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGenericGlobalActor[#Global Actor#]; name=MyGenericGlobalActor
232232
// ON_PROPERTY-NOT: Decl[PrecedenceGroup]
233233

234234
@#^ON_METHOD^# private
@@ -253,21 +253,21 @@ struct _S {
253253
// ON_METHOD-DAG: Keyword/None: backDeployed[#Func Attribute#]; name=backDeployed
254254
// ON_METHOD-NOT: Keyword
255255
// ON_METHOD-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
256-
// ON_METHOD-DAG: Decl[Struct]/CurrModule: MyPropertyWrapper[#MyPropertyWrapper#]; name=MyPropertyWrapper
257-
// ON_METHOD-DAG: Decl[Struct]/CurrModule: MyGenericPropertyWrapper[#MyGenericPropertyWrapper#]; name=MyGenericPropertyWrapper
258-
// ON_METHOD-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#MyResultBuilder#]; name=MyResultBuilder
259-
// ON_METHOD-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericResultBuilder[#MyGenericResultBuilder#]; name=MyGenericResultBuilder
260-
// ON_METHOD-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#MyGlobalActor#]; name=MyGlobalActor
261-
// ON_METHOD-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGenericGlobalActor[#MyGenericGlobalActor#]; name=MyGenericGlobalActor
256+
// ON_METHOD-DAG: Decl[Struct]/CurrModule: MyPropertyWrapper[#Property Wrapper#]; name=MyPropertyWrapper
257+
// ON_METHOD-DAG: Decl[Struct]/CurrModule: MyGenericPropertyWrapper[#Property Wrapper#]; name=MyGenericPropertyWrapper
258+
// ON_METHOD-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#Result Builder#]; name=MyResultBuilder
259+
// ON_METHOD-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericResultBuilder[#Result Builder#]; name=MyGenericResultBuilder
260+
// ON_METHOD-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#Global Actor#]; name=MyGlobalActor
261+
// ON_METHOD-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGenericGlobalActor[#Global Actor#]; name=MyGenericGlobalActor
262262

263263

264264

265265
func bar(@#^ON_PARAM_1^#)
266266
// ON_PARAM-NOT: Keyword
267267
// ON_PARAM-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
268-
// ON_PARAM-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#MyPropertyWrapper#]; name=MyPropertyWrapper
269-
// ON_PARAM-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#MyResultBuilder#]; name=MyResultBuilder
270-
// ON_PARAM-DAG: Decl[Actor]/CurrModule: MyGlobalActor[#MyGlobalActor#]; name=MyGlobalActor
268+
// ON_PARAM-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#Property Wrapper#]; name=MyPropertyWrapper
269+
// ON_PARAM-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#Result Builder#]; name=MyResultBuilder
270+
// ON_PARAM-DAG: Decl[Actor]/CurrModule: MyGlobalActor[#Global Actor#]; name=MyGlobalActor
271271
// ON_PARAM-NOT: Keyword
272272

273273
func bar(
@@ -327,12 +327,12 @@ struct _S {
327327
// ON_MEMBER_LAST-DAG: Keyword/None: storageRestrictions[#Declaration Attribute#]; name=storageRestrictions
328328
// ON_MEMBER_LAST-NOT: Keyword
329329
// ON_MEMBER_LAST-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
330-
// ON_MEMBER_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#MyPropertyWrapper#]; name=MyPropertyWrapper
331-
// ON_MEMBER_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericPropertyWrapper[#MyGenericPropertyWrapper#]; name=MyGenericPropertyWrapper
332-
// ON_MEMBER_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#MyResultBuilder#]; name=MyResultBuilder
333-
// ON_MEMBER_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericResultBuilder[#MyGenericResultBuilder#]; name=MyGenericResultBuilder
334-
// ON_MEMBER_LAST-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#MyGlobalActor#]; name=MyGlobalActor
335-
// ON_MEMBER_LAST-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGenericGlobalActor[#MyGenericGlobalActor#]; name=MyGenericGlobalActor
330+
// ON_MEMBER_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#Property Wrapper#]; name=MyPropertyWrapper
331+
// ON_MEMBER_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericPropertyWrapper[#Property Wrapper#]; name=MyGenericPropertyWrapper
332+
// ON_MEMBER_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#Result Builder#]; name=MyResultBuilder
333+
// ON_MEMBER_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericResultBuilder[#Result Builder#]; name=MyGenericResultBuilder
334+
// ON_MEMBER_LAST-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#Global Actor#]; name=MyGlobalActor
335+
// ON_MEMBER_LAST-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGenericGlobalActor[#Global Actor#]; name=MyGenericGlobalActor
336336
// ON_MEMBER_LAST-NOT: Decl[PrecedenceGroup]
337337
}
338338

@@ -343,9 +343,9 @@ func takeClosure(_: () -> Void) {
343343
}
344344
// FIXME: We should mark MyPropertyWrapper and MyResultBuilder as Unrelated
345345
// IN_CLOSURE-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
346-
// IN_CLOSURE-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#MyPropertyWrapper#]; name=MyPropertyWrapper
347-
// IN_CLOSURE-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#MyResultBuilder#]; name=MyResultBuilder
348-
// IN_CLOSURE-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#MyGlobalActor#]; name=MyGlobalActor
346+
// IN_CLOSURE-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#Property Wrapper#]; name=MyPropertyWrapper
347+
// IN_CLOSURE-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#Result Builder#]; name=MyResultBuilder
348+
// IN_CLOSURE-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#Global Actor#]; name=MyGlobalActor
349349

350350

351351
@#^KEYWORD_INDEPENDENT_1^#
@@ -399,9 +399,9 @@ func dummy2() {}
399399
// KEYWORD_LAST-DAG: Keyword/None: storageRestrictions[#Declaration Attribute#]; name=storageRestrictions
400400
// KEYWORD_LAST-NOT: Keyword
401401
// KEYWORD_LAST-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
402-
// KEYWORD_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericPropertyWrapper[#MyGenericPropertyWrapper#]; name=MyGenericPropertyWrapper
403-
// KEYWORD_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#MyPropertyWrapper#]; name=MyPropertyWrapper
404-
// KEYWORD_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericResultBuilder[#MyGenericResultBuilder#]; name=MyGenericResultBuilder
405-
// KEYWORD_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#MyResultBuilder#]; name=MyResultBuilder
406-
// KEYWORD_LAST-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGenericGlobalActor[#MyGenericGlobalActor#]; name=MyGenericGlobalActor
407-
// KEYWORD_LAST-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#MyGlobalActor#]; name=MyGlobalActor
402+
// KEYWORD_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericPropertyWrapper[#Property Wrapper#]; name=MyGenericPropertyWrapper
403+
// KEYWORD_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyPropertyWrapper[#Property Wrapper#]; name=MyPropertyWrapper
404+
// KEYWORD_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyGenericResultBuilder[#Result Builder#]; name=MyGenericResultBuilder
405+
// KEYWORD_LAST-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#Result Builder#]; name=MyResultBuilder
406+
// KEYWORD_LAST-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGenericGlobalActor[#Global Actor#]; name=MyGenericGlobalActor
407+
// KEYWORD_LAST-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#Global Actor#]; name=MyGlobalActor

0 commit comments

Comments
 (0)