Skip to content

Commit e3b113f

Browse files
committed
File::getMethodParameters(): bug fix for attributes leaking into type hint
This commit adds handling of parameter attributes to the `File::getMethodParameters()` method as per option [2] discussed in issue 3298. In practice this means that: * [New] A new `attributes` index is introduced into the returned array which will hold a boolean value indicating whether attributes are attached to the parameter. * [Unchanged] The `content` index in the returned array includes the textual representation of any attributes attached to a parameter. * [Fixed] The `type_hint` and `type_hint_token` indexes will no longer be polluted (set incorrectly) with information belonging to the attribute(s) instead of to the type declaration. Includes minor efficiency fix for handling of parenthesis and brackets in default values. Includes dedicated unit test. Fixes 3298
1 parent e4af9dc commit e3b113f

File tree

3 files changed

+135
-3
lines changed

3 files changed

+135
-3
lines changed

src/Files/File.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,7 @@ public function getDeclarationName($stackPtr)
12831283
* 'name' => '$var', // The variable name.
12841284
* 'token' => integer, // The stack pointer to the variable name.
12851285
* 'content' => string, // The full content of the variable definition.
1286+
* 'attributes' => boolean, // Does the parameter have one or more attributes attached ?
12861287
* 'pass_by_reference' => boolean, // Is the variable passed by reference?
12871288
* 'reference_token' => integer, // The stack pointer to the reference operator
12881289
* // or FALSE if the param is not passed by reference.
@@ -1355,6 +1356,7 @@ public function getMethodParameters($stackPtr)
13551356
$defaultStart = null;
13561357
$equalToken = null;
13571358
$paramCount = 0;
1359+
$attributes = false;
13581360
$passByReference = false;
13591361
$referenceToken = false;
13601362
$variableLength = false;
@@ -1373,18 +1375,25 @@ public function getMethodParameters($stackPtr)
13731375
if (isset($this->tokens[$i]['parenthesis_opener']) === true) {
13741376
// Don't do this if it's the close parenthesis for the method.
13751377
if ($i !== $this->tokens[$i]['parenthesis_closer']) {
1376-
$i = ($this->tokens[$i]['parenthesis_closer'] + 1);
1378+
$i = $this->tokens[$i]['parenthesis_closer'];
1379+
continue;
13771380
}
13781381
}
13791382

13801383
if (isset($this->tokens[$i]['bracket_opener']) === true) {
1381-
// Don't do this if it's the close parenthesis for the method.
13821384
if ($i !== $this->tokens[$i]['bracket_closer']) {
1383-
$i = ($this->tokens[$i]['bracket_closer'] + 1);
1385+
$i = $this->tokens[$i]['bracket_closer'];
1386+
continue;
13841387
}
13851388
}
13861389

13871390
switch ($this->tokens[$i]['code']) {
1391+
case T_ATTRIBUTE:
1392+
$attributes = true;
1393+
1394+
// Skip to the end of the attribute.
1395+
$i = $this->tokens[$i]['attribute_closer'];
1396+
break;
13881397
case T_BITWISE_AND:
13891398
if ($defaultStart === null) {
13901399
$passByReference = true;
@@ -1501,6 +1510,7 @@ public function getMethodParameters($stackPtr)
15011510
$vars[$paramCount]['default_equal_token'] = $equalToken;
15021511
}
15031512

1513+
$vars[$paramCount]['attributes'] = $attributes;
15041514
$vars[$paramCount]['pass_by_reference'] = $passByReference;
15051515
$vars[$paramCount]['reference_token'] = $referenceToken;
15061516
$vars[$paramCount]['variable_length'] = $variableLength;
@@ -1526,6 +1536,7 @@ public function getMethodParameters($stackPtr)
15261536
$paramStart = ($i + 1);
15271537
$defaultStart = null;
15281538
$equalToken = null;
1539+
$attributes = false;
15291540
$passByReference = false;
15301541
$referenceToken = false;
15311542
$variableLength = false;

tests/Core/File/GetMethodParametersTest.inc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,17 @@ function commentsInParams(
126126
// Leading comment.
127127
?MyClass /*-*/ & /*-*/.../*-*/ $param /*-*/ = /*-*/ 'default value' . /*-*/ 'second part' // Trailing comment.
128128
) {}
129+
130+
/* testParameterAttributesInFunctionDeclaration */
131+
class ParametersWithAttributes(
132+
public function __construct(
133+
#[\MyExample\MyAttribute] private string $constructorPropPromTypedParamSingleAttribute,
134+
#[MyAttr([1, 2])]
135+
Type|false
136+
$typedParamSingleAttribute,
137+
#[MyAttribute(1234), MyAttribute(5678)] ?int $nullableTypedParamMultiAttribute,
138+
#[WithoutArgument] #[SingleArgument(0)] $nonTypedParamTwoAttributes,
139+
#[MyAttribute(array("key" => "value"))]
140+
&...$otherParam,
141+
) {}
142+
}

0 commit comments

Comments
 (0)