Skip to content

Commit f036e26

Browse files
authored
Merge pull request #471 from PHPCSStandards/php-8.2/file-getmethodparameters-support-dnf
PHP 8.2 | File::getMethodParameters(): add support for DNF types
2 parents 7aceb91 + 36aa8aa commit f036e26

File tree

3 files changed

+178
-2
lines changed

3 files changed

+178
-2
lines changed

src/Files/File.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1419,7 +1419,9 @@ public function getMethodParameters($stackPtr)
14191419
// it's likely to be an array which might have arguments in it. This
14201420
// could cause problems in our parsing below, so lets just skip to the
14211421
// end of it.
1422-
if (isset($this->tokens[$i]['parenthesis_opener']) === true) {
1422+
if ($this->tokens[$i]['code'] !== T_TYPE_OPEN_PARENTHESIS
1423+
&& isset($this->tokens[$i]['parenthesis_opener']) === true
1424+
) {
14231425
// Don't do this if it's the close parenthesis for the method.
14241426
if ($i !== $this->tokens[$i]['parenthesis_closer']) {
14251427
$i = $this->tokens[$i]['parenthesis_closer'];
@@ -1513,6 +1515,8 @@ public function getMethodParameters($stackPtr)
15131515
case T_NS_SEPARATOR:
15141516
case T_TYPE_UNION:
15151517
case T_TYPE_INTERSECTION:
1518+
case T_TYPE_OPEN_PARENTHESIS:
1519+
case T_TYPE_CLOSE_PARENTHESIS:
15161520
case T_FALSE:
15171521
case T_TRUE:
15181522
case T_NULL:

tests/Core/File/GetMethodParametersTest.inc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,23 @@ function newInInitializers(
280280
\Package\TypeB $newToo = new \Package\TypeB(10, 'string'),
281281
) {}
282282

283+
/* testPHP82DNFTypes */
284+
function dnfTypes(
285+
#[MyAttribute]
286+
false|(Foo&Bar)|true $obj1,
287+
(\Boo&\Pck\Bar)|(Boo&Baz) $obj2 = new Boo()
288+
) {}
289+
290+
/* testPHP82DNFTypesWithSpreadOperatorAndReference */
291+
function dnfInGlobalFunctionWithSpreadAndReference((Countable&MeMe)|iterable &$paramA, true|(Foo&Bar) ...$paramB) {}
292+
293+
/* testPHP82DNFTypesIllegalNullable */
294+
// Intentional fatal error - nullable operator cannot be combined with DNF.
295+
$dnf_closure = function (? ( MyClassA & /*comment*/ \Package\MyClassB & \Package\MyClassC ) $var): void {};
296+
297+
/* testPHP82DNFTypesInArrow */
298+
$dnf_arrow = fn((Hi&Ho)|FALSE &...$range): string => $a;
299+
283300
/* testFunctionCallFnPHPCS353-354 */
284301
$value = $obj->fn(true);
285302

tests/Core/File/GetMethodParametersTest.php

Lines changed: 156 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2450,7 +2450,7 @@ public function testPHP8IntersectionTypes()
24502450

24512451

24522452
/**
2453-
* Verify recognition of PHP8 intersection type declaration when the variable
2453+
* Verify recognition of PHP8.1 intersection type declaration when the variable
24542454
* has either a spread operator or a reference.
24552455
*
24562456
* @return void
@@ -2702,6 +2702,161 @@ public function testPHP81NewInInitializers()
27022702
}//end testPHP81NewInInitializers()
27032703

27042704

2705+
/**
2706+
* Verify recognition of 8.2 DNF parameter type declarations.
2707+
*
2708+
* @return void
2709+
*/
2710+
public function testPHP82DNFTypes()
2711+
{
2712+
// Offsets are relative to the T_FUNCTION token.
2713+
$expected = [];
2714+
$expected[0] = [
2715+
'token' => 21,
2716+
'name' => '$obj1',
2717+
'content' => '#[MyAttribute]
2718+
false|(Foo&Bar)|true $obj1',
2719+
'has_attributes' => true,
2720+
'pass_by_reference' => false,
2721+
'reference_token' => false,
2722+
'variable_length' => false,
2723+
'variadic_token' => false,
2724+
'type_hint' => 'false|(Foo&Bar)|true',
2725+
'type_hint_token' => 11,
2726+
'type_hint_end_token' => 19,
2727+
'nullable_type' => false,
2728+
'comma_token' => 22,
2729+
];
2730+
$expected[1] = [
2731+
'token' => 41,
2732+
'name' => '$obj2',
2733+
'content' => '(\Boo&\Pck\Bar)|(Boo&Baz) $obj2 = new Boo()',
2734+
'default' => 'new Boo()',
2735+
'default_token' => 45,
2736+
'default_equal_token' => 43,
2737+
'has_attributes' => false,
2738+
'pass_by_reference' => false,
2739+
'reference_token' => false,
2740+
'variable_length' => false,
2741+
'variadic_token' => false,
2742+
'type_hint' => '(\Boo&\Pck\Bar)|(Boo&Baz)',
2743+
'type_hint_token' => 25,
2744+
'type_hint_end_token' => 39,
2745+
'nullable_type' => false,
2746+
'comma_token' => false,
2747+
];
2748+
2749+
$this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected);
2750+
2751+
}//end testPHP82DNFTypes()
2752+
2753+
2754+
/**
2755+
* Verify recognition of PHP 8.2 DNF parameter type declarations when the variable
2756+
* has either a spread operator or a reference.
2757+
*
2758+
* @return void
2759+
*/
2760+
public function testPHP82DNFTypesWithSpreadOperatorAndReference()
2761+
{
2762+
// Offsets are relative to the T_FUNCTION token.
2763+
$expected = [];
2764+
$expected[0] = [
2765+
'token' => 13,
2766+
'name' => '$paramA',
2767+
'content' => '(Countable&MeMe)|iterable &$paramA',
2768+
'has_attributes' => false,
2769+
'pass_by_reference' => true,
2770+
'reference_token' => 12,
2771+
'variable_length' => false,
2772+
'variadic_token' => false,
2773+
'type_hint' => '(Countable&MeMe)|iterable',
2774+
'type_hint_token' => 4,
2775+
'type_hint_end_token' => 10,
2776+
'nullable_type' => false,
2777+
'comma_token' => 14,
2778+
];
2779+
$expected[1] = [
2780+
'token' => 25,
2781+
'name' => '$paramB',
2782+
'content' => 'true|(Foo&Bar) ...$paramB',
2783+
'has_attributes' => false,
2784+
'pass_by_reference' => false,
2785+
'reference_token' => false,
2786+
'variable_length' => true,
2787+
'variadic_token' => 24,
2788+
'type_hint' => 'true|(Foo&Bar)',
2789+
'type_hint_token' => 16,
2790+
'type_hint_end_token' => 22,
2791+
'nullable_type' => false,
2792+
'comma_token' => false,
2793+
];
2794+
2795+
$this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected);
2796+
2797+
}//end testPHP82DNFTypesWithSpreadOperatorAndReference()
2798+
2799+
2800+
/**
2801+
* Verify recognition of PHP 8.2 DNF parameter type declarations using the nullability operator (not allowed).
2802+
*
2803+
* @return void
2804+
*/
2805+
public function testPHP82DNFTypesIllegalNullable()
2806+
{
2807+
// Offsets are relative to the T_FUNCTION token.
2808+
$expected = [];
2809+
$expected[0] = [
2810+
'token' => 27,
2811+
'name' => '$var',
2812+
'content' => '? ( MyClassA & /*comment*/ \Package\MyClassB & \Package\MyClassC ) $var',
2813+
'has_attributes' => false,
2814+
'pass_by_reference' => false,
2815+
'reference_token' => false,
2816+
'variable_length' => false,
2817+
'variadic_token' => false,
2818+
'type_hint' => '?(MyClassA&\Package\MyClassB&\Package\MyClassC)',
2819+
'type_hint_token' => 5,
2820+
'type_hint_end_token' => 25,
2821+
'nullable_type' => true,
2822+
'comma_token' => false,
2823+
];
2824+
2825+
$this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected);
2826+
2827+
}//end testPHP82DNFTypesIllegalNullable()
2828+
2829+
2830+
/**
2831+
* Verify recognition of PHP 8.2 DNF parameter type declarations in an arrow function.
2832+
*
2833+
* @return void
2834+
*/
2835+
public function testPHP82DNFTypesInArrow()
2836+
{
2837+
// Offsets are relative to the T_FUNCTION token.
2838+
$expected = [];
2839+
$expected[0] = [
2840+
'token' => 12,
2841+
'name' => '$range',
2842+
'content' => '(Hi&Ho)|FALSE &...$range',
2843+
'has_attributes' => false,
2844+
'pass_by_reference' => true,
2845+
'reference_token' => 10,
2846+
'variable_length' => true,
2847+
'variadic_token' => 11,
2848+
'type_hint' => '(Hi&Ho)|FALSE',
2849+
'type_hint_token' => 2,
2850+
'type_hint_end_token' => 8,
2851+
'nullable_type' => false,
2852+
'comma_token' => false,
2853+
];
2854+
2855+
$this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected);
2856+
2857+
}//end testPHP82DNFTypesInArrow()
2858+
2859+
27052860
/**
27062861
* Verify handling of a closure.
27072862
*

0 commit comments

Comments
 (0)