Skip to content

Commit

Permalink
Merge pull request #65427 from ahoppen/ahoppen/macro-attribute-comple…
Browse files Browse the repository at this point in the history
…tions

[CodeCompletion] Support completion for macro roles and the 'names:' argument label
  • Loading branch information
ahoppen committed Apr 29, 2023
2 parents 366213d + 6098a3c commit 053d215
Show file tree
Hide file tree
Showing 13 changed files with 246 additions and 109 deletions.
2 changes: 1 addition & 1 deletion include/swift/AST/DiagnosticsCommon.def
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ ERROR(unknown_attribute,none,
NOTE(in_macro_expansion,none,
"in expansion of macro %0 here", (DeclName))
ERROR(macro_experimental,none,
"%0 macros are an experimental feature that is not enabled (%1)",
"%0 macros are an experimental feature that is not enabled %select{|(%1)}1",
(StringRef, StringRef))
ERROR(ambiguous_macro_reference,none,
"ambiguous reference to macro %0", (DeclName))
Expand Down
8 changes: 8 additions & 0 deletions include/swift/AST/MacroDeclaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,13 @@ enum class MacroRole: uint32_t {
/// A freestanding macro that expands to expressions, statements and
/// declarations in a code block.
CodeItem = 0x80,

// NOTE: When adding a new macro role, also add it to `getAllMacroRoles`.
};

/// Returns an enumeratable list of all macro roles.
std::vector<MacroRole> getAllMacroRoles();

/// The contexts in which a particular macro declaration can be used.
using MacroRoles = OptionSet<MacroRole>;

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

MacroRoles getAttachedMacroRoles();

/// Checks if the macro is supported or guarded behind an experimental flag.
bool isMacroSupported(MacroRole role, ASTContext &ctx);

enum class MacroIntroducedDeclNameKind {
Named,
Overloaded,
Expand Down
3 changes: 2 additions & 1 deletion include/swift/IDE/CompletionLookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {

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

void getAttributeDeclParamCompletions(DeclAttrKind AttrKind, int ParamIndex);
void getAttributeDeclParamCompletions(CustomSyntaxAttributeKind AttrKind,
int ParamIndex);

void getTypeAttributeKeywordCompletions();

Expand Down
11 changes: 10 additions & 1 deletion include/swift/Parse/IDEInspectionCallbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ enum class ObjCSelectorContext {
SetterSelector
};

/// Attributes that have syntax which can't be modelled using a function call.
/// This can't be \c DeclAttrKind because '@freestandig' and '@attached' have
/// the same attribute kind but take different macro roles as arguemnts.
enum class CustomSyntaxAttributeKind {
Available,
FreestandingMacro,
AttachedMacro,
};

/// Parser's interface to code completion.
class CodeCompletionCallbacks {
protected:
Expand Down Expand Up @@ -185,7 +194,7 @@ class CodeCompletionCallbacks {

/// Complete the parameters in attribute, for instance, version specifier for
/// @available.
virtual void completeDeclAttrParam(DeclAttrKind DK, int Index) {};
virtual void completeDeclAttrParam(CustomSyntaxAttributeKind DK, int Index){};

/// Complete 'async' and 'throws' at effects specifier position.
virtual void completeEffectsSpecifier(bool hasAsync, bool hasThrows) {};
Expand Down
13 changes: 7 additions & 6 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1019,9 +1019,10 @@ class Parser {
PatternBindingInitializer *initContext);

/// Parse the optional modifiers before a declaration.
bool parseDeclModifierList(DeclAttributes &Attributes, SourceLoc &StaticLoc,
StaticSpellingKind &StaticSpelling,
bool isFromClangAttribute = false);
ParserStatus parseDeclModifierList(DeclAttributes &Attributes,
SourceLoc &StaticLoc,
StaticSpellingKind &StaticSpelling,
bool isFromClangAttribute = false);

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

bool parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
DeclAttrKind DK,
bool isFromClangAttribute = false);
ParserStatus parseNewDeclAttribute(DeclAttributes &Attributes,
SourceLoc AtLoc, DeclAttrKind DK,
bool isFromClangAttribute = false);

/// Parse a version tuple of the form x[.y[.z]]. Returns true if there was
/// an error parsing.
Expand Down
23 changes: 23 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10113,6 +10113,14 @@ BuiltinTupleDecl::BuiltinTupleDecl(Identifier Name, DeclContext *Parent)
: NominalTypeDecl(DeclKind::BuiltinTuple, Parent, Name, SourceLoc(),
ArrayRef<InheritedEntry>(), nullptr) {}

std::vector<MacroRole> swift::getAllMacroRoles() {
return {
MacroRole::Expression, MacroRole::Declaration, MacroRole::Accessor,
MacroRole::MemberAttribute, MacroRole::Member, MacroRole::Peer,
MacroRole::Conformance, MacroRole::CodeItem,
};
}

StringRef swift::getMacroRoleString(MacroRole role) {
switch (role) {
case MacroRole::Expression:
Expand Down Expand Up @@ -10204,6 +10212,21 @@ MacroRoles swift::getAttachedMacroRoles() {
return attachedMacroRoles;
}

bool swift::isMacroSupported(MacroRole role, ASTContext &ctx) {
switch (role) {
case MacroRole::Expression:
case MacroRole::Declaration:
case MacroRole::Accessor:
case MacroRole::MemberAttribute:
case MacroRole::Member:
case MacroRole::Peer:
case MacroRole::Conformance:
return true;
case MacroRole::CodeItem:
return ctx.LangOpts.hasFeature(Feature::CodeItemMacros);
}
}

void MissingDecl::forEachMacroExpandedDecl(MacroExpandedDeclCallback callback) {
auto macroRef = unexpandedMacro.macroRef;
auto *baseDecl = unexpandedMacro.baseDecl;
Expand Down
8 changes: 5 additions & 3 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7693,9 +7693,11 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
} else {
SourceLoc staticLoc;
StaticSpellingKind staticSpelling;
hadError = parser.parseDeclModifierList(
MappedDecl->getAttrs(), staticLoc, staticSpelling,
/*isFromClangAttribute=*/true);
hadError = parser
.parseDeclModifierList(MappedDecl->getAttrs(), staticLoc,
staticSpelling,
/*isFromClangAttribute=*/true)
.isError();
}

if (hadError) {
Expand Down
8 changes: 4 additions & 4 deletions lib/IDE/CodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks,
SourceLoc DotLoc;
TypeLoc ParsedTypeLoc;
DeclContext *CurDeclContext = nullptr;
DeclAttrKind AttrKind;
CustomSyntaxAttributeKind AttrKind;

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

void CodeCompletionCallbacksImpl::completeDeclAttrParam(DeclAttrKind DK,
int Index) {
void CodeCompletionCallbacksImpl::completeDeclAttrParam(
CustomSyntaxAttributeKind DK, int Index) {
Kind = CompletionKind::AttributeDeclParen;
AttrKind = DK;
AttrParamIndex = Index;
Expand Down
31 changes: 27 additions & 4 deletions lib/IDE/CompletionLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3011,9 +3011,10 @@ void CompletionLookup::getAttributeDeclCompletions(bool IsInSil,
#include "swift/AST/Attr.def"
}

void CompletionLookup::getAttributeDeclParamCompletions(DeclAttrKind AttrKind,
int ParamIndex) {
if (AttrKind == DAK_Available) {
void CompletionLookup::getAttributeDeclParamCompletions(
CustomSyntaxAttributeKind AttrKind, int ParamIndex) {
switch (AttrKind) {
case CustomSyntaxAttributeKind::Available:
if (ParamIndex == 0) {
addDeclAttrParamKeyword("*", "Platform", false);

Expand All @@ -3029,6 +3030,28 @@ void CompletionLookup::getAttributeDeclParamCompletions(DeclAttrKind AttrKind,
addDeclAttrParamKeyword("introduced", "Specify version number", true);
addDeclAttrParamKeyword("deprecated", "Specify version number", true);
}
break;
case CustomSyntaxAttributeKind::FreestandingMacro:
case CustomSyntaxAttributeKind::AttachedMacro:
switch (ParamIndex) {
case 0:
for (auto role : getAllMacroRoles()) {
bool isRoleSupported = isMacroSupported(role, Ctx);
if (AttrKind == CustomSyntaxAttributeKind::FreestandingMacro) {
isRoleSupported &= isFreestandingMacro(role);
} else if (AttrKind == CustomSyntaxAttributeKind::AttachedMacro) {
isRoleSupported &= isAttachedMacro(role);
}
if (isRoleSupported) {
addDeclAttrParamKeyword(getMacroRoleString(role), "", false);
}
}
break;
case 1:
addDeclAttrParamKeyword("names", "Specify declared names", true);
break;
}
break;
}
}

Expand Down Expand Up @@ -3103,7 +3126,7 @@ void CompletionLookup::getPrecedenceGroupCompletions(
void CompletionLookup::getPoundAvailablePlatformCompletions() {

// The platform names should be identical to those in @available.
getAttributeDeclParamCompletions(DAK_Available, 0);
getAttributeDeclParamCompletions(CustomSyntaxAttributeKind::Available, 0);
}

void CompletionLookup::getSelfTypeCompletionInDeclContext(
Expand Down
Loading

0 comments on commit 053d215

Please sign in to comment.