Skip to content

[FR] Arrow functions: sniff to enforce spacing and placement of the => symbol #458

Description

@rodrigoprimo

Setting the scene

PHP 7.4 introduced arrow functions (short closures) via the fn() => expression syntax. PER-CS 2.0 states in section 7.1 that the => symbol must be surrounded by a single space, and gives a placement rule for when the expression is split across multiple lines. Neither PHPCS itself nor PHPCSExtra contains a sniff for this.

Proposed new sniff: Universal.WhiteSpace.FnArrowFormatting

To address these rules from PER:

The => symbol MUST be preceded and succeeded by a space.
The expression portion MAY be split to a subsequent line. If so, the => MUST be included on the second line, and MUST be indented once.

Notes for the implementation

[T_FN_ARROW] can be the entry point for this sniff. The SpacesFixer from PHPCSUtils handles the two spacing checks.

The space-before-=> check must be skipped when the expression is validly split across multiple lines, so the two rules do not conflict. For the indentation part of the placement rule, the expected indent is the indentation of the line the fn keyword starts on plus one level, where one level is the configurable $indent property.

Suggested error codes:

  • SpacingBefore: incorrect spacing before the =>.
  • SpacingAfter: incorrect spacing after the =>.
  • ArrowNotOnSecondLine: wrapped expression with the => left on the first line.
  • ArrowIndent: wrapped => not indented one level.

The sniff should be configurable and use PER-CS values as default values:

  • public $spacingBefore = 1;
  • public $spacingAfter = 1;
  • public $indent = 4;

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.
$fn = fn($x) => $x + 1;

// OK: expression wrapped, => on the second line, indented once.
$fn = fn($x)
    => $x + 1;

// Error (SpacingBefore): no space before the =>.
$fn = fn($x)=> $x + 1;

// Error (SpacingAfter): no space after the =>.
$fn = fn($x) =>$x + 1;

// Error (SpacingBefore / SpacingAfter): more than one space around the =>.
$fn = fn($x)   =>   $x + 1;

// Error (ArrowNotOnSecondLine): expression wrapped, but => left dangling on the first line.
$fn = fn($x) =>
    $x + 1;

// Error (ArrowIndent): expression wrapped, => on the second line, but not indented once.
$fn = fn($x)
=> $x + 1;

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

Additional context (optional)

This ticket is the result of a detailed analysis of the rules as outlined in PER-CS 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

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions