Skip to content

Commit 053d215

Browse files
authored
Merge pull request #65427 from ahoppen/ahoppen/macro-attribute-completions
[CodeCompletion] Support completion for macro roles and the 'names:' argument label
2 parents 366213d + 6098a3c commit 053d215

13 files changed

+246
-109
lines changed

include/swift/AST/DiagnosticsCommon.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ ERROR(unknown_attribute,none,
223223
NOTE(in_macro_expansion,none,
224224
"in expansion of macro %0 here", (DeclName))
225225
ERROR(macro_experimental,none,
226-
"%0 macros are an experimental feature that is not enabled (%1)",
226+
"%0 macros are an experimental feature that is not enabled %select{|(%1)}1",
227227
(StringRef, StringRef))
228228
ERROR(ambiguous_macro_reference,none,
229229
"ambiguous reference to macro %0", (DeclName))

include/swift/AST/MacroDeclaration.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,13 @@ enum class MacroRole: uint32_t {
5858
/// A freestanding macro that expands to expressions, statements and
5959
/// declarations in a code block.
6060
CodeItem = 0x80,
61+
62+
// NOTE: When adding a new macro role, also add it to `getAllMacroRoles`.
6163
};
6264

65+
/// Returns an enumeratable list of all macro roles.
66+
std::vector<MacroRole> getAllMacroRoles();
67+
6368
/// The contexts in which a particular macro declaration can be used.
6469
using MacroRoles = OptionSet<MacroRole>;
6570

@@ -83,6 +88,9 @@ bool isAttachedMacro(MacroRoles contexts);
8388

8489
MacroRoles getAttachedMacroRoles();
8590

91+
/// Checks if the macro is supported or guarded behind an experimental flag.
92+
bool isMacroSupported(MacroRole role, ASTContext &ctx);
93+
8694
enum class MacroIntroducedDeclNameKind {
8795
Named,
8896
Overloaded,

include/swift/IDE/CompletionLookup.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
585585

586586
void getAttributeDeclCompletions(bool IsInSil, Optional<DeclKind> DK);
587587

588-
void getAttributeDeclParamCompletions(DeclAttrKind AttrKind, int ParamIndex);
588+
void getAttributeDeclParamCompletions(CustomSyntaxAttributeKind AttrKind,
589+
int ParamIndex);
589590

590591
void getTypeAttributeKeywordCompletions();
591592

include/swift/Parse/IDEInspectionCallbacks.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ enum class ObjCSelectorContext {
2929
SetterSelector
3030
};
3131

32+
/// Attributes that have syntax which can't be modelled using a function call.
33+
/// This can't be \c DeclAttrKind because '@freestandig' and '@attached' have
34+
/// the same attribute kind but take different macro roles as arguemnts.
35+
enum class CustomSyntaxAttributeKind {
36+
Available,
37+
FreestandingMacro,
38+
AttachedMacro,
39+
};
40+
3241
/// Parser's interface to code completion.
3342
class CodeCompletionCallbacks {
3443
protected:
@@ -185,7 +194,7 @@ class CodeCompletionCallbacks {
185194

186195
/// Complete the parameters in attribute, for instance, version specifier for
187196
/// @available.
188-
virtual void completeDeclAttrParam(DeclAttrKind DK, int Index) {};
197+
virtual void completeDeclAttrParam(CustomSyntaxAttributeKind DK, int Index){};
189198

190199
/// Complete 'async' and 'throws' at effects specifier position.
191200
virtual void completeEffectsSpecifier(bool hasAsync, bool hasThrows) {};

include/swift/Parse/Parser.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,9 +1019,10 @@ class Parser {
10191019
PatternBindingInitializer *initContext);
10201020

10211021
/// Parse the optional modifiers before a declaration.
1022-
bool parseDeclModifierList(DeclAttributes &Attributes, SourceLoc &StaticLoc,
1023-
StaticSpellingKind &StaticSpelling,
1024-
bool isFromClangAttribute = false);
1022+
ParserStatus parseDeclModifierList(DeclAttributes &Attributes,
1023+
SourceLoc &StaticLoc,
1024+
StaticSpellingKind &StaticSpelling,
1025+
bool isFromClangAttribute = false);
10251026

10261027
/// Parse an availability attribute of the form
10271028
/// @available(*, introduced: 1.0, deprecated: 3.1).
@@ -1133,9 +1134,9 @@ class Parser {
11331134
ParserResult<CustomAttr> parseCustomAttribute(
11341135
SourceLoc atLoc, PatternBindingInitializer *&initContext);
11351136

1136-
bool parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
1137-
DeclAttrKind DK,
1138-
bool isFromClangAttribute = false);
1137+
ParserStatus parseNewDeclAttribute(DeclAttributes &Attributes,
1138+
SourceLoc AtLoc, DeclAttrKind DK,
1139+
bool isFromClangAttribute = false);
11391140

11401141
/// Parse a version tuple of the form x[.y[.z]]. Returns true if there was
11411142
/// an error parsing.

lib/AST/Decl.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10113,6 +10113,14 @@ BuiltinTupleDecl::BuiltinTupleDecl(Identifier Name, DeclContext *Parent)
1011310113
: NominalTypeDecl(DeclKind::BuiltinTuple, Parent, Name, SourceLoc(),
1011410114
ArrayRef<InheritedEntry>(), nullptr) {}
1011510115

10116+
std::vector<MacroRole> swift::getAllMacroRoles() {
10117+
return {
10118+
MacroRole::Expression, MacroRole::Declaration, MacroRole::Accessor,
10119+
MacroRole::MemberAttribute, MacroRole::Member, MacroRole::Peer,
10120+
MacroRole::Conformance, MacroRole::CodeItem,
10121+
};
10122+
}
10123+
1011610124
StringRef swift::getMacroRoleString(MacroRole role) {
1011710125
switch (role) {
1011810126
case MacroRole::Expression:
@@ -10204,6 +10212,21 @@ MacroRoles swift::getAttachedMacroRoles() {
1020410212
return attachedMacroRoles;
1020510213
}
1020610214

10215+
bool swift::isMacroSupported(MacroRole role, ASTContext &ctx) {
10216+
switch (role) {
10217+
case MacroRole::Expression:
10218+
case MacroRole::Declaration:
10219+
case MacroRole::Accessor:
10220+
case MacroRole::MemberAttribute:
10221+
case MacroRole::Member:
10222+
case MacroRole::Peer:
10223+
case MacroRole::Conformance:
10224+
return true;
10225+
case MacroRole::CodeItem:
10226+
return ctx.LangOpts.hasFeature(Feature::CodeItemMacros);
10227+
}
10228+
}
10229+
1020710230
void MissingDecl::forEachMacroExpandedDecl(MacroExpandedDeclCallback callback) {
1020810231
auto macroRef = unexpandedMacro.macroRef;
1020910232
auto *baseDecl = unexpandedMacro.baseDecl;

lib/ClangImporter/ImportDecl.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7693,9 +7693,11 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
76937693
} else {
76947694
SourceLoc staticLoc;
76957695
StaticSpellingKind staticSpelling;
7696-
hadError = parser.parseDeclModifierList(
7697-
MappedDecl->getAttrs(), staticLoc, staticSpelling,
7698-
/*isFromClangAttribute=*/true);
7696+
hadError = parser
7697+
.parseDeclModifierList(MappedDecl->getAttrs(), staticLoc,
7698+
staticSpelling,
7699+
/*isFromClangAttribute=*/true)
7700+
.isError();
76997701
}
77007702

77017703
if (hadError) {

lib/IDE/CodeCompletion.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks,
113113
SourceLoc DotLoc;
114114
TypeLoc ParsedTypeLoc;
115115
DeclContext *CurDeclContext = nullptr;
116-
DeclAttrKind AttrKind;
116+
CustomSyntaxAttributeKind AttrKind;
117117

118118
/// When the code completion token occurs in a custom attribute, the attribute
119119
/// it occurs in. Used so we can complete inside the attribute even if it's
@@ -270,7 +270,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks,
270270
void completeCaseStmtKeyword() override;
271271
void completeCaseStmtBeginning(CodeCompletionExpr *E) override;
272272
void completeDeclAttrBeginning(bool Sil, bool isIndependent) override;
273-
void completeDeclAttrParam(DeclAttrKind DK, int Index) override;
273+
void completeDeclAttrParam(CustomSyntaxAttributeKind DK, int Index) override;
274274
void completeEffectsSpecifier(bool hasAsync, bool hasThrows) override;
275275
void completeInPrecedenceGroup(
276276
CodeCompletionCallbacks::PrecedenceGroupCompletionKind SK) override;
@@ -456,8 +456,8 @@ void CodeCompletionCallbacksImpl::completeTypeSimpleBeginning() {
456456
CurDeclContext = P.CurDeclContext;
457457
}
458458

459-
void CodeCompletionCallbacksImpl::completeDeclAttrParam(DeclAttrKind DK,
460-
int Index) {
459+
void CodeCompletionCallbacksImpl::completeDeclAttrParam(
460+
CustomSyntaxAttributeKind DK, int Index) {
461461
Kind = CompletionKind::AttributeDeclParen;
462462
AttrKind = DK;
463463
AttrParamIndex = Index;

lib/IDE/CompletionLookup.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3011,9 +3011,10 @@ void CompletionLookup::getAttributeDeclCompletions(bool IsInSil,
30113011
#include "swift/AST/Attr.def"
30123012
}
30133013

3014-
void CompletionLookup::getAttributeDeclParamCompletions(DeclAttrKind AttrKind,
3015-
int ParamIndex) {
3016-
if (AttrKind == DAK_Available) {
3014+
void CompletionLookup::getAttributeDeclParamCompletions(
3015+
CustomSyntaxAttributeKind AttrKind, int ParamIndex) {
3016+
switch (AttrKind) {
3017+
case CustomSyntaxAttributeKind::Available:
30173018
if (ParamIndex == 0) {
30183019
addDeclAttrParamKeyword("*", "Platform", false);
30193020

@@ -3029,6 +3030,28 @@ void CompletionLookup::getAttributeDeclParamCompletions(DeclAttrKind AttrKind,
30293030
addDeclAttrParamKeyword("introduced", "Specify version number", true);
30303031
addDeclAttrParamKeyword("deprecated", "Specify version number", true);
30313032
}
3033+
break;
3034+
case CustomSyntaxAttributeKind::FreestandingMacro:
3035+
case CustomSyntaxAttributeKind::AttachedMacro:
3036+
switch (ParamIndex) {
3037+
case 0:
3038+
for (auto role : getAllMacroRoles()) {
3039+
bool isRoleSupported = isMacroSupported(role, Ctx);
3040+
if (AttrKind == CustomSyntaxAttributeKind::FreestandingMacro) {
3041+
isRoleSupported &= isFreestandingMacro(role);
3042+
} else if (AttrKind == CustomSyntaxAttributeKind::AttachedMacro) {
3043+
isRoleSupported &= isAttachedMacro(role);
3044+
}
3045+
if (isRoleSupported) {
3046+
addDeclAttrParamKeyword(getMacroRoleString(role), "", false);
3047+
}
3048+
}
3049+
break;
3050+
case 1:
3051+
addDeclAttrParamKeyword("names", "Specify declared names", true);
3052+
break;
3053+
}
3054+
break;
30323055
}
30333056
}
30343057

@@ -3103,7 +3126,7 @@ void CompletionLookup::getPrecedenceGroupCompletions(
31033126
void CompletionLookup::getPoundAvailablePlatformCompletions() {
31043127

31053128
// The platform names should be identical to those in @available.
3106-
getAttributeDeclParamCompletions(DAK_Available, 0);
3129+
getAttributeDeclParamCompletions(CustomSyntaxAttributeKind::Available, 0);
31073130
}
31083131

31093132
void CompletionLookup::getSelfTypeCompletionInDeclContext(

0 commit comments

Comments
 (0)