Skip to content

[5.9][CodeComplete] Offer code completion for attached macro attributes #65639

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
8 changes: 4 additions & 4 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -3258,17 +3258,17 @@ void simple_display(llvm::raw_ostream &out,
class ResolveMacroRequest
: public SimpleRequest<ResolveMacroRequest,
ConcreteDeclRef(UnresolvedMacroReference,
const Decl *),
DeclContext *),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

ConcreteDeclRef
evaluate(Evaluator &evaluator, UnresolvedMacroReference macroRef,
const Decl *decl) const;
ConcreteDeclRef evaluate(Evaluator &evaluator,
UnresolvedMacroReference macroRef,
DeclContext *decl) const;

public:
bool isCached() const { return true; }
Expand Down
3 changes: 1 addition & 2 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,7 @@ void Decl::forEachAttachedMacro(MacroRole role,
MacroDecl *Decl::getResolvedMacro(CustomAttr *customAttr) const {
auto declRef = evaluateOrDefault(
getASTContext().evaluator,
ResolveMacroRequest{customAttr, this},
ConcreteDeclRef());
ResolveMacroRequest{customAttr, getDeclContext()}, ConcreteDeclRef());

return dyn_cast_or_null<MacroDecl>(declRef.getDecl());
}
Expand Down
27 changes: 19 additions & 8 deletions lib/IDE/CodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1416,14 +1416,25 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
llvm::SaveAndRestore<TypeCheckCompletionCallback*>
CompletionCollector(Context.CompletionCallback, &Lookup);
if (AttrWithCompletion) {
/// The attribute might not be attached to the AST if there is no var decl
/// it could be attached to. Type check it standalone.
ASTNode Call = CallExpr::create(
CurDeclContext->getASTContext(), AttrWithCompletion->getTypeExpr(),
AttrWithCompletion->getArgs(), /*implicit=*/true);
typeCheckContextAt(
TypeCheckASTNodeAtLocContext::node(CurDeclContext, Call),
CompletionLoc);
/// The attribute might not be attached to the AST if there is no var
/// decl it could be attached to. Type check it standalone.

// First try to check it as an attached macro.
auto resolvedMacro = evaluateOrDefault(
CurDeclContext->getASTContext().evaluator,
ResolveMacroRequest{AttrWithCompletion, CurDeclContext},
ConcreteDeclRef());

// If that fails, type check as a call to the attribute's type. This is
// how, e.g., property wrappers are modelled.
if (!resolvedMacro) {
ASTNode Call = CallExpr::create(
CurDeclContext->getASTContext(), AttrWithCompletion->getTypeExpr(),
AttrWithCompletion->getArgs(), /*implicit=*/true);
typeCheckContextAt(
TypeCheckASTNodeAtLocContext::node(CurDeclContext, Call),
CompletionLoc);
}
} else {
typeCheckContextAt(
TypeCheckASTNodeAtLocContext::declContext(CurDeclContext),
Expand Down
5 changes: 2 additions & 3 deletions lib/Sema/TypeCheckDeclPrimary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3794,9 +3794,8 @@ ExpandMacroExpansionDeclRequest::evaluate(Evaluator &evaluator,
auto *dc = MED->getDeclContext();

// Resolve macro candidates.
auto macro = evaluateOrDefault(
ctx.evaluator, ResolveMacroRequest{MED, MED},
ConcreteDeclRef());
auto macro = evaluateOrDefault(ctx.evaluator, ResolveMacroRequest{MED, dc},
ConcreteDeclRef());
if (!macro)
return None;
MED->setMacroRef(macro);
Expand Down
9 changes: 3 additions & 6 deletions lib/Sema/TypeCheckMacros.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1496,12 +1496,9 @@ swift::expandConformances(CustomAttr *attr, MacroDecl *macro,
return macroSourceFile->getBufferID();
}

ConcreteDeclRef
ResolveMacroRequest::evaluate(Evaluator &evaluator,
UnresolvedMacroReference macroRef,
const Decl *decl) const {
auto dc = decl->getDeclContext();

ConcreteDeclRef ResolveMacroRequest::evaluate(Evaluator &evaluator,
UnresolvedMacroReference macroRef,
DeclContext *dc) const {
// Macro expressions and declarations have their own stored macro
// reference. Use it if it's there.
if (auto *expr = macroRef.getExpr()) {
Expand Down
23 changes: 23 additions & 0 deletions test/IDE/complete_macros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ public macro AttachedMemberMacro()
@attached(member)
public macro AttachedMemberMacroWithArgs(arg1: Int)

public enum Direction {
case up, down
}

@attached(member)
public macro AttachedMemberMacroWithEnumArgs(_ direction: Direction)

@attached(member)
public macro AttachedMemberMacroWithMultipleArgs(first: Int, second: Int)

@attached(memberAttribute)
public macro AttachedMemberAttributeMacro()

Expand Down Expand Up @@ -157,6 +167,19 @@ struct NestedFreestanding {
// ITEM_FREESTANDING-DAG: Decl[Macro]/{{.*}}: freestandingDeclMacro[#Void#]; name=freestandingDeclMacro
// ITEM_FREESTANDING-DAG: Decl[Macro]/{{.*}}: EverythingMacro[#Void#]; name=EverythingMacro


@AttachedMemberMacroWithEnumArgs(.#^ATTACHED_MACRO_ARG^#)
struct AttachedMacroArg {}

// ATTACHED_MACRO_ARG-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Convertible]: up[#Direction#]; name=up
// ATTACHED_MACRO_ARG-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Convertible]: down[#Direction#]; name=down

@AttachedMemberMacroWithMultipleArgs(first: 1, #^ATTACHED_MACRO_SECOND_ARG_LABEL^#)
struct AttachedMacroSecondArgLabel {}

// ATTACHED_MACRO_SECOND_ARG_LABEL: Pattern/Local/Flair[ArgLabels]: {#second: Int#}[#Int#]; name=second:


struct LastMember {
@#^LAST_MEMBER_ATTR?check=INDEPENDENT_ATTR^#
}
Expand Down