Skip to content

Target-aware attribute completion filtering #320

Description

@Firehed

Summary

Filter attribute-name completion by the attribute's declared targets, so a #[
position only offers attributes valid there — e.g. don't offer a
TARGET_METHOD-only attribute on a class, or a TARGET_CLASS-only attribute in a
function-parameter position. This also covers suppressing completion entirely where
#[ is not a syntactically valid attribute position at all (see below).

Background

The initial attribute completion work added attribute-name completion (#[Ro
attribute classes only) via ClassCandidateFilter::Attribute +
CodeResolver::isAttribute. That filter is target-agnostic: every confirmed
attribute is offered at any #[ on the line, regardless of position. This is the
"less sophisticated version first" explicitly called out in the parent issue.

Because detection is text-only, it also offers attributes after a #[ that appears in
a syntactically invalid spot (e.g. an expression position like $x = #[Fo). Deciding
"is this even a valid attribute position, and if so what target?" is the same
position analysis — so both concerns are resolved here rather than by bolting a second
validity check onto the text classifier.

Work

  • Capture the attribute's target flags (the #[Attribute(Attribute::TARGET_*)]
    bitmask; #[Attribute] with no argument defaults to TARGET_ALL) on
    ClassInfo, populated from both the AST factory (attrGroups → the Attribute
    attribute's argument) and reflection.
  • Detect the current attribute target at the cursor (class / method / property /
    parameter / constant / function / enum-case), and detect the absence of a valid
    attribute target. This needs position context beyond the text classifier — an
    AST-first path with a text fallback, consistent with the member/call detection seam.
    The text classifier deliberately stays resilient (see docs/features/completion.md),
    so target detection should layer on rather than convert the classifier to AST.
  • Narrow the attribute filter (or a new CodeResolver predicate) by the detected
    target, and offer nothing when no attribute target applies.

Acceptance

  • A TARGET_METHOD attribute is offered on a method but not on a class.
  • TARGET_ALL / unflagged attributes are offered everywhere an attribute is valid.
  • No attributes are offered where #[ is not a valid attribute position (e.g. an
    expression/statement position inside a body).
  • When the position is valid but the target cannot be determined, fall back to offering
    all attributes (optimistic) rather than hiding valid completions.

Part of #252 (parent #311).


Issue body written by AI, from a design discussion with the maintainer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions