Skip to content

Commit 4db6a74

Browse files
committed
Merge branch 'feature/bugfixes-namespace-operator-in-typedeclarations' of https://github.com/jrfnl/PHP_CodeSniffer
2 parents 6525028 + 16d2cd1 commit 4db6a74

14 files changed

+233
-0
lines changed

package.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
122122
<file baseinstalldir="" name="BackfillNumericSeparatorTest.php" role="test" />
123123
<file baseinstalldir="" name="NullsafeObjectOperatorTest.inc" role="test" />
124124
<file baseinstalldir="" name="NullsafeObjectOperatorTest.php" role="test" />
125+
<file baseinstalldir="" name="ScopeSettingWithNamespaceOperatorTest.inc" role="test" />
126+
<file baseinstalldir="" name="ScopeSettingWithNamespaceOperatorTest.php" role="test" />
125127
<file baseinstalldir="" name="ShortArrayTest.inc" role="test" />
126128
<file baseinstalldir="" name="ShortArrayTest.php" role="test" />
127129
<file baseinstalldir="" name="StableCommentWhitespaceTest.inc" role="test" />
@@ -2000,6 +2002,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
20002002
<install as="CodeSniffer/Core/Tokenizer/BackfillNumericSeparatorTest.inc" name="tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc" />
20012003
<install as="CodeSniffer/Core/Tokenizer/NullsafeObjectOperatorTest.php" name="tests/Core/Tokenizer/NullsafeObjectOperatorTest.php" />
20022004
<install as="CodeSniffer/Core/Tokenizer/NullsafeObjectOperatorTest.inc" name="tests/Core/Tokenizer/NullsafeObjectOperatorTest.inc" />
2005+
<install as="CodeSniffer/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php" name="tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php" />
2006+
<install as="CodeSniffer/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc" name="tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc" />
20032007
<install as="CodeSniffer/Core/Tokenizer/ShortArrayTest.php" name="tests/Core/Tokenizer/ShortArrayTest.php" />
20042008
<install as="CodeSniffer/Core/Tokenizer/ShortArrayTest.inc" name="tests/Core/Tokenizer/ShortArrayTest.inc" />
20052009
<install as="CodeSniffer/Core/Tokenizer/StableCommentWhitespaceTest.php" name="tests/Core/Tokenizer/StableCommentWhitespaceTest.php" />
@@ -2063,6 +2067,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
20632067
<install as="CodeSniffer/Core/Tokenizer/BackfillNumericSeparatorTest.inc" name="tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc" />
20642068
<install as="CodeSniffer/Core/Tokenizer/NullsafeObjectOperatorTest.php" name="tests/Core/Tokenizer/NullsafeObjectOperatorTest.php" />
20652069
<install as="CodeSniffer/Core/Tokenizer/NullsafeObjectOperatorTest.inc" name="tests/Core/Tokenizer/NullsafeObjectOperatorTest.inc" />
2070+
<install as="CodeSniffer/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php" name="tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php" />
2071+
<install as="CodeSniffer/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc" name="tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.inc" />
20662072
<install as="CodeSniffer/Core/Tokenizer/ShortArrayTest.php" name="tests/Core/Tokenizer/ShortArrayTest.php" />
20672073
<install as="CodeSniffer/Core/Tokenizer/ShortArrayTest.inc" name="tests/Core/Tokenizer/ShortArrayTest.inc" />
20682074
<install as="CodeSniffer/Core/Tokenizer/StableCommentWhitespaceTest.php" name="tests/Core/Tokenizer/StableCommentWhitespaceTest.php" />

src/Files/File.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,6 +1441,7 @@ public function getMethodParameters($stackPtr)
14411441
$typeHintEndToken = $i;
14421442
}
14431443
break;
1444+
case T_NAMESPACE:
14441445
case T_NS_SEPARATOR:
14451446
// Part of a type hint or default value.
14461447
if ($defaultStart === null) {
@@ -1630,6 +1631,7 @@ public function getMethodProperties($stackPtr)
16301631
T_SELF => T_SELF,
16311632
T_PARENT => T_PARENT,
16321633
T_STATIC => T_STATIC,
1634+
T_NAMESPACE => T_NAMESPACE,
16331635
T_NS_SEPARATOR => T_NS_SEPARATOR,
16341636
];
16351637

@@ -1813,6 +1815,7 @@ public function getMemberProperties($stackPtr)
18131815
T_CALLABLE => T_CALLABLE,
18141816
T_SELF => T_SELF,
18151817
T_PARENT => T_PARENT,
1818+
T_NAMESPACE => T_NAMESPACE,
18161819
T_NS_SEPARATOR => T_NS_SEPARATOR,
18171820
];
18181821

src/Tokenizers/PHP.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,7 @@ protected function tokenize($string)
12271227
|| $tokenType === T_NAME_RELATIVE
12281228
|| $tokenType === T_NAME_QUALIFIED
12291229
|| $tokenType === T_ARRAY
1230+
|| $tokenType === T_NAMESPACE
12301231
|| $tokenType === T_NS_SEPARATOR
12311232
) {
12321233
$lastRelevantNonEmpty = $tokenType;
@@ -1473,6 +1474,7 @@ function return types. We want to keep the parenthesis map clean,
14731474
T_CALLABLE => T_CALLABLE,
14741475
T_SELF => T_SELF,
14751476
T_PARENT => T_PARENT,
1477+
T_NAMESPACE => T_NAMESPACE,
14761478
T_NS_SEPARATOR => T_NS_SEPARATOR,
14771479
];
14781480

@@ -1987,6 +1989,7 @@ protected function processAdditional()
19871989
T_STRING => T_STRING,
19881990
T_ARRAY => T_ARRAY,
19891991
T_COLON => T_COLON,
1992+
T_NAMESPACE => T_NAMESPACE,
19901993
T_NS_SEPARATOR => T_NS_SEPARATOR,
19911994
T_NULLABLE => T_NULLABLE,
19921995
T_CALLABLE => T_CALLABLE,

src/Tokenizers/Tokenizer.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,13 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0)
11111111
continue;
11121112
}
11131113

1114+
if ($tokenType === T_NAMESPACE) {
1115+
// PHP namespace keywords are special because they can be
1116+
// used as blocks but also inline as operators.
1117+
// So if we find them nested inside another opener, just skip them.
1118+
continue;
1119+
}
1120+
11141121
if ($tokenType === T_FUNCTION
11151122
&& $this->tokens[$stackPtr]['code'] !== T_FUNCTION
11161123
) {

tests/Core/File/GetMemberPropertiesTest.inc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,8 @@ class PHP8Mixed {
188188
// Intentional fatal error - nullability is not allowed with mixed, but that's not the concern of the method.
189189
private ?mixed $nullableMixed;
190190
}
191+
192+
class NSOperatorInType {
193+
/* testNamespaceOperatorTypeHint */
194+
public ?namespace\Name $prop;
195+
}

tests/Core/File/GetMemberPropertiesTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,16 @@ public function dataGetMemberProperties()
479479
'nullable_type' => true,
480480
],
481481
],
482+
[
483+
'/* testNamespaceOperatorTypeHint */',
484+
[
485+
'scope' => 'public',
486+
'scope_specified' => true,
487+
'is_static' => false,
488+
'type' => '?namespace\Name',
489+
'nullable_type' => true,
490+
],
491+
],
482492
];
483493

484494
}//end dataGetMemberProperties()

tests/Core/File/GetMethodParametersTest.inc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,6 @@ function mixedTypeHint(mixed &...$var1) {}
3838
/* testPHP8MixedTypeHintNullable */
3939
// Intentional fatal error - nullability is not allowed with mixed, but that's not the concern of the method.
4040
function mixedTypeHintNullable(?Mixed $var1) {}
41+
42+
/* testNamespaceOperatorTypeHint */
43+
function namespaceOperatorTypeHint(?namespace\Name $var1) {}

tests/Core/File/GetMethodParametersTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,28 @@ public function testPHP8MixedTypeHintNullable()
318318
}//end testPHP8MixedTypeHintNullable()
319319

320320

321+
/**
322+
* Verify recognition of type declarations using the namespace operator.
323+
*
324+
* @return void
325+
*/
326+
public function testNamespaceOperatorTypeHint()
327+
{
328+
$expected = [];
329+
$expected[0] = [
330+
'name' => '$var1',
331+
'content' => '?namespace\Name $var1',
332+
'pass_by_reference' => false,
333+
'variable_length' => false,
334+
'type_hint' => '?namespace\Name',
335+
'nullable_type' => true,
336+
];
337+
338+
$this->getMethodParametersTestHelper('/* '.__FUNCTION__.' */', $expected);
339+
340+
}//end testNamespaceOperatorTypeHint()
341+
342+
321343
/**
322344
* Test helper.
323345
*

tests/Core/File/GetMethodPropertiesTest.inc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,6 @@ function mixedTypeHint() :mixed {}
8080
/* testPHP8MixedTypeHintNullable */
8181
// Intentional fatal error - nullability is not allowed with mixed, but that's not the concern of the method.
8282
function mixedTypeHintNullable(): ?mixed {}
83+
84+
/* testNamespaceOperatorTypeHint */
85+
function namespaceOperatorTypeHint() : ?namespace\Name {}

tests/Core/File/GetMethodPropertiesTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,29 @@ public function testPHP8MixedTypeHintNullable()
452452
}//end testPHP8MixedTypeHintNullable()
453453

454454

455+
/**
456+
* Test a function with return type using the namespace operator.
457+
*
458+
* @return void
459+
*/
460+
public function testNamespaceOperatorTypeHint()
461+
{
462+
$expected = [
463+
'scope' => 'public',
464+
'scope_specified' => false,
465+
'return_type' => '?namespace\Name',
466+
'nullable_return_type' => true,
467+
'is_abstract' => false,
468+
'is_final' => false,
469+
'is_static' => false,
470+
'has_body' => true,
471+
];
472+
473+
$this->getMethodPropertiesTestHelper('/* '.__FUNCTION__.' */', $expected);
474+
475+
}//end testNamespaceOperatorTypeHint()
476+
477+
455478
/**
456479
* Test helper.
457480
*

0 commit comments

Comments
 (0)