Skip to content

Commit 5caa34b

Browse files
committed
feat(functions): Disallow arrow function return type hints
1 parent 8352f0d commit 5caa34b

5 files changed

Lines changed: 99 additions & 0 deletions

File tree

SlevomatCodingStandard/Sniffs/Functions/ArrowFunctionDeclarationSniff.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PHP_CodeSniffer\Files\File;
66
use PHP_CodeSniffer\Sniffs\Sniff;
77
use SlevomatCodingStandard\Helpers\FixerHelper;
8+
use SlevomatCodingStandard\Helpers\FunctionHelper;
89
use SlevomatCodingStandard\Helpers\SniffSettingsHelper;
910
use SlevomatCodingStandard\Helpers\TokenHelper;
1011
use function preg_match;
@@ -21,6 +22,7 @@ class ArrowFunctionDeclarationSniff implements Sniff
2122
public const CODE_INCORRECT_SPACES_AFTER_KEYWORD = 'IncorrectSpacesAfterKeyword';
2223
public const CODE_INCORRECT_SPACES_BEFORE_ARROW = 'IncorrectSpacesBeforeArrow';
2324
public const CODE_INCORRECT_SPACES_AFTER_ARROW = 'IncorrectSpacesAfterArrow';
25+
public const CODE_DISALLOWED_RETURN_TYPE_HINT = 'DisallowedReturnTypeHint';
2426

2527
public int $spacesCountAfterKeyword = 1;
2628

@@ -30,6 +32,8 @@ class ArrowFunctionDeclarationSniff implements Sniff
3032

3133
public bool $allowMultiLine = false;
3234

35+
public bool $disallowReturnTypeHint = false;
36+
3337
/**
3438
* @return array<int, (int|string)>
3539
*/
@@ -50,10 +54,46 @@ public function process(File $phpcsFile, int $arrowFunctionPointer): void
5054

5155
$arrowPointer = TokenHelper::findNext($phpcsFile, T_FN_ARROW, $arrowFunctionPointer);
5256

57+
$this->checkReturnTypeHint($phpcsFile, $arrowFunctionPointer, $arrowPointer);
58+
5359
$this->checkSpacesBeforeArrow($phpcsFile, $arrowPointer);
5460
$this->checkSpacesAfterArrow($phpcsFile, $arrowPointer);
5561
}
5662

63+
private function checkReturnTypeHint(File $phpcsFile, int $arrowFunctionPointer, int $arrowPointer): void
64+
{
65+
if (!$this->disallowReturnTypeHint) {
66+
return;
67+
}
68+
69+
$returnTypeHint = FunctionHelper::findReturnTypeHint($phpcsFile, $arrowFunctionPointer);
70+
if ($returnTypeHint === null) {
71+
return;
72+
}
73+
74+
$fix = $phpcsFile->addFixableError(
75+
'Arrow function must not have return type hint.',
76+
$returnTypeHint->getStartPointer(),
77+
self::CODE_DISALLOWED_RETURN_TYPE_HINT,
78+
);
79+
if (!$fix) {
80+
return;
81+
}
82+
83+
$colonPointer = TokenHelper::findPreviousEffective($phpcsFile, $returnTypeHint->getStartPointer() - 1);
84+
85+
$pointerBeforeColon = TokenHelper::findPreviousEffective($phpcsFile, $colonPointer - 1);
86+
87+
$phpcsFile->fixer->beginChangeset();
88+
FixerHelper::removeBetween($phpcsFile, $pointerBeforeColon, $arrowPointer);
89+
90+
if ($this->spacesCountBeforeArrow > 0) {
91+
FixerHelper::addBefore($phpcsFile, $arrowPointer, str_repeat(' ', $this->spacesCountBeforeArrow));
92+
}
93+
94+
$phpcsFile->fixer->endChangeset();
95+
}
96+
5797
private function checkSpacesAfterKeyword(File $phpcsFile, int $arrowFunctionPointer): void
5898
{
5999
$pointerAfter = TokenHelper::findNextNonWhitespace($phpcsFile, $arrowFunctionPointer + 1);

doc/functions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Sniff provides the following settings:
1010
* `spacesCountBeforeArrow`: the number of spaces before `=>`.
1111
* `spacesCountAfterArrow`: the number of spaces after `=>`.
1212
* `allowMultiLine`: allows multi-line declaration.
13+
* `disallowReturnTypeHint` (default: `false`): disallows return type hints in arrow functions.
1314

1415
#### SlevomatCodingStandard.Functions.DisallowArrowFunction
1516

tests/Sniffs/Functions/ArrowFunctionDeclarationSniffTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,40 @@ public function testModifiedSettingsErrors(): void
151151
self::assertAllFixedInFile($report);
152152
}
153153

154+
public function testDisallowReturnTypeHintErrors(): void
155+
{
156+
$report = self::checkFile(__DIR__ . '/data/arrowFunctionDeclarationDisallowReturnTypeHintErrors.php', [
157+
'disallowReturnTypeHint' => true,
158+
]);
159+
160+
self::assertSame(4, $report->getErrorCount());
161+
162+
self::assertSniffError(
163+
$report,
164+
3,
165+
ArrowFunctionDeclarationSniff::CODE_DISALLOWED_RETURN_TYPE_HINT,
166+
'Arrow function must not have return type hint.',
167+
);
168+
self::assertSniffError(
169+
$report,
170+
5,
171+
ArrowFunctionDeclarationSniff::CODE_DISALLOWED_RETURN_TYPE_HINT,
172+
'Arrow function must not have return type hint.',
173+
);
174+
self::assertSniffError(
175+
$report,
176+
7,
177+
ArrowFunctionDeclarationSniff::CODE_DISALLOWED_RETURN_TYPE_HINT,
178+
'Arrow function must not have return type hint.',
179+
);
180+
self::assertSniffError(
181+
$report,
182+
9,
183+
ArrowFunctionDeclarationSniff::CODE_DISALLOWED_RETURN_TYPE_HINT,
184+
'Arrow function must not have return type hint.',
185+
);
186+
187+
self::assertAllFixedInFile($report);
188+
}
189+
154190
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php // lint >= 8.1
2+
3+
fn ($a) => $a;
4+
5+
fn ($a) => $a;
6+
7+
fn ($a) => $a;
8+
9+
fn ($a) => $a;
10+
11+
fn ($a) => $a;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php // lint >= 8.1
2+
3+
fn ($a): int => $a;
4+
5+
fn ($a): ?string => $a;
6+
7+
fn ($a): int|string => $a;
8+
9+
fn ($a): A&B => $a;
10+
11+
fn ($a) => $a;

0 commit comments

Comments
 (0)