Skip to content

[FR] Attributes: sniff to enforce single attribute per block if block is multi-line #392

@jrfnl

Description

@jrfnl

Setting the scene

PHP 8.0 introduced support for attributes via the #[...] syntax. At this moment, neither PHPCS itself, nor PHPCSExtra contain any sniffs to handle the formatting of attributes.

The PER Coding Standard from FIG, since PER 2.0, outlines a set of rules for attribute formatting to comply with, so using those rules as a starting point would allow for creating an initial set of sniffs to address attribute formatting.

Proposed new sniff: Universal.Attributes.OneAttributeInMultilineBlock

To address these rules from PER:

If the attribute list is split into multiple lines for any reason, then the attributes MUST be placed in separate attribute blocks. Those blocks may themselves contain multiple attributes provided this rule is respected.

If an attribute's argument list is split into multiple lines for any reason, then:

  • The attribute MUST be the only one in its attribute block.

Notes for the implementation

Suggested error codes:

  • MultipleFound

Should be straight forward to write using the upcoming PHPCSUtils AttributeBlock::getAttributes() and AttributeBlock::countAttributes() methods.

Describe the solution you'd like

A new sniff as outlined above.

The sniff should be able to flag and auto-fix the following:

// OK.
#[MultiLine(
    paramA: VALUE,
    paramB: 10 * 3,
)]

// Error.
#[MultiLine(
    paramA: VALUE,
    paramB: 10 * 3,
), SecondAttribute]

#[AttributeOne,
  AttributeTwo]

#[
    AttributeOne(VALUE),
    AttributeTwo(VALUE)
]

Also see the examples outlined in the PER documents (rules + migration guide).

Additional context (optional)

This ticket is part of a series of tickets related to PHP attributes and is the result of a detailed analysis of the rules as outlined in PER 2.0, as well as a critical look at what's still missing rule-wise.

  • I intend to create a pull request to implement this feature.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions