Skip to content

Commit 749fdd5

Browse files
committed
Indent the line after a `=>' left at the end of a line
An arrow function whose body starts on the next line fell back to column zero: $f = fn($x) => $x + 1; `=>' is deliberately excluded from php-indent--indent-operator-re --- in PHP it is overwhelmingly the array key operator, and treating every `'key' => 'value'' as a continuation would be wrong --- so nothing at all picked up a trailing one, and the body was indented as if it began a fresh statement. Property hooks showed the same gap, and worse, an inconsistent one: the first line after `get =>' stayed put while a following `.' line was indented by php-indent--statement-continuation-indentation, which does fire after an identifier: get => $this->a . ' '; Treat a trailing `=>' as leaving the statement open, alongside the identifier / `)' / `):' cases already there. The three shapes now agree: $f = fn($x) => $x + 1; $config = [ 'key' => 'a value long enough to wrap', ]; get => $this->a . ' '; Only `=>' is matched, so `>=', `->' and `<=>' keep the handling they had. The shape had no fixture at all, which is why the gap went unnoticed; tests/indent/trailing-arrow.php now covers arrow functions, array values, the bracket-on-the-same-line case, property hooks, match arms, and a `>=' left at the end of a line.
1 parent c8c5b04 commit 749fdd5

3 files changed

Lines changed: 75 additions & 4 deletions

File tree

lisp/php-indent.el

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -464,9 +464,10 @@ until a statement terminator (`;', `{', `}', an opening `(' or `[', a
464464
A continuation line is one whose previous code token leaves the
465465
statement unterminated: an identifier or keyword (as in stacked member
466466
modifiers, `extends' on its own line or a broken `return'), a closing
467-
parenthesis, or a return-type `):'. Such lines are indented one
468-
`php-indent-offset' beyond the first line of the statement. Return nil
469-
when the current line does not continue a statement this way."
467+
parenthesis, a return-type `):', or a trailing `=>'. Such lines are
468+
indented one `php-indent-offset' beyond the first line of the
469+
statement. Return nil when the current line does not continue a
470+
statement this way."
470471
(save-excursion
471472
(back-to-indentation)
472473
(unless (or (memq (char-after) '(?\{ ?\} ?\) ?\]))
@@ -480,7 +481,15 @@ when the current line does not continue a statement this way."
480481
;; A `):' return-type (or alternative-syntax `):')
481482
;; also leaves the statement open.
482483
(and (eq (char-before) ?:)
483-
(eq (char-before (1- (point))) ?\)))))
484+
(eq (char-before (1- (point))) ?\)))
485+
;; So does a `=>' left dangling at the end of a
486+
;; line: an arrow function's body, an array value
487+
;; or a property hook's expression follows it.
488+
;; `=>' is excluded from
489+
;; `php-indent--indent-operator-re', so nothing
490+
;; else picks these up.
491+
(and (eq (char-before) ?>)
492+
(eq (char-before (1- (point))) ?=))))
484493
(goto-char pos)
485494
(php-indent--goto-statement-start)
486495
(unless (php-indent--same-line pos)

tests/indent/trailing-arrow.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
/**
4+
* A `=>' left dangling at the end of a line.
5+
*
6+
* `=>' is excluded from `php-indent--indent-operator-re' because it is
7+
* PHP's array key operator, so nothing treated the line after it as a
8+
* continuation: an arrow function's body fell all the way back to
9+
* column zero.
10+
*/
11+
12+
// An arrow function's body on the next line.
13+
$f = fn($x) =>
14+
$x + 1; // ###php-mode-test### ((indent 4))
15+
16+
$g = static fn(int $n): bool =>
17+
$n > 0; // ###php-mode-test### ((indent 4))
18+
19+
// An array value on the next line.
20+
$config = [
21+
'key' => // ###php-mode-test### ((indent 4))
22+
'a value long enough to wrap', // ###php-mode-test### ((indent 8))
23+
'other' => 1, // ###php-mode-test### ((indent 4))
24+
]; // ###php-mode-test### ((indent 0))
25+
26+
// The opening bracket on the same line as the arrow: the value anchors
27+
// to the line holding the bracket, not to the key's column.
28+
$inline = ['key' =>
29+
'value']; // ###php-mode-test### ((indent 4))
30+
31+
// A property hook's expression on the next line.
32+
class Person
33+
{
34+
public string $label { // ###php-mode-test### ((indent 4))
35+
get => // ###php-mode-test### ((indent 8))
36+
$this->firstName // ###php-mode-test### ((indent 12))
37+
. ' ' // ###php-mode-test### ((indent 12))
38+
. $this->lastName; // ###php-mode-test### ((indent 12))
39+
} // ###php-mode-test### ((indent 4))
40+
}
41+
42+
// A match arm's result on the next line.
43+
$label = match ($n) {
44+
1 => // ###php-mode-test### ((indent 4))
45+
'one', // ###php-mode-test### ((indent 8))
46+
default => 'many', // ###php-mode-test### ((indent 4))
47+
}; // ###php-mode-test### ((indent 0))
48+
49+
// Tokens that end in `>' but are not `=>' keep their own handling.
50+
if ($a >=
51+
$b // ###php-mode-test### ((indent 4))
52+
) {
53+
echo 1; // ###php-mode-test### ((indent 4))
54+
}

tests/php-mode-test.el

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,14 @@ Meant for `php-mode-test-issue-503'."
660660
;; Proper alignment arglist that contains empty lines.
661661
(with-php-mode-test ("indent/issue-793.php" :indent t :magic t)))
662662

663+
(ert-deftest php-mode-test-indentation-trailing-arrow ()
664+
"Indentation of a line following a `=>' left at the end of a line.
665+
666+
`=>' is excluded from `php-indent--indent-operator-re' because it is
667+
PHP's array key operator, so nothing treated the next line as a
668+
continuation: an arrow function's body fell back to column zero."
669+
(with-php-mode-test ("indent/trailing-arrow.php" :indent t :magic t)))
670+
663671
(ert-deftest php-mode-test-indentation-object-accessor ()
664672
"Alignment of chained object accessors split across lines."
665673
(with-php-mode-test ("indent/issue-623.php" :indent t :magic t)))

0 commit comments

Comments
 (0)