Skip to content

Commit 4d22790

Browse files
authored
Merge pull request #180 from PHPCSStandards/feature/support-namespace-operator-in-types
Support namespace operator in type declarations
2 parents 8b23ad7 + 0941b32 commit 4d22790

14 files changed

+107
-0
lines changed

PHPCSUtils/Tokens/Collections.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,7 @@ public static function parameterTypeTokens()
723723
\T_FALSE => \T_FALSE, // Union types only.
724724
\T_NULL => \T_NULL, // Union types only.
725725
\T_STRING => \T_STRING,
726+
\T_NAMESPACE => \T_NAMESPACE,
726727
\T_NS_SEPARATOR => \T_NS_SEPARATOR,
727728
\T_BITWISE_OR => \T_BITWISE_OR, // Union types.
728729
];
@@ -792,6 +793,7 @@ public static function propertyTypeTokens()
792793
\T_FALSE => \T_FALSE, // Union types only.
793794
\T_NULL => \T_NULL, // Union types only.
794795
\T_STRING => \T_STRING,
796+
\T_NAMESPACE => \T_NAMESPACE,
795797
\T_NS_SEPARATOR => \T_NS_SEPARATOR,
796798
\T_BITWISE_OR => \T_BITWISE_OR, // Union types.
797799
];
@@ -863,6 +865,7 @@ public static function returnTypeTokens()
863865
\T_FALSE => \T_FALSE, // Union types only.
864866
\T_NULL => \T_NULL, // Union types only.
865867
\T_ARRAY => \T_ARRAY, // Arrow functions PHPCS < 3.5.4 + union types.
868+
\T_NAMESPACE => \T_NAMESPACE,
866869
\T_NS_SEPARATOR => \T_NS_SEPARATOR,
867870
\T_BITWISE_OR => \T_BITWISE_OR, // Union types.
868871
];

PHPCSUtils/Utils/FunctionDeclarations.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ public static function getName(File $phpcsFile, $stackPtr)
171171
* - To allow for backward compatible handling of arrow functions, this method will also accept
172172
* `T_STRING` tokens and examine them to check if these are arrow functions.
173173
* - Support for PHP 8.0 union types.
174+
* - Support for namespace operator in type declarations.
174175
*
175176
* @see \PHP_CodeSniffer\Files\File::getMethodProperties() Original source.
176177
* @see \PHPCSUtils\BackCompat\BCFile::getMethodProperties() Cross-version compatible version of the original.
@@ -300,6 +301,16 @@ public static function getProperties(File $phpcsFile, $stackPtr)
300301
break;
301302
}
302303

304+
/*
305+
* Work-around for a scope map tokenizer bug in PHPCS.
306+
* {@link https://github.com/squizlabs/PHP_CodeSniffer/pull/3066}
307+
*/
308+
if ($scopeOpener === null && $tokens[$i]['code'] === \T_OPEN_CURLY_BRACKET) {
309+
// End of function definition for which the scope opener is incorrectly not set.
310+
$hasBody = true;
311+
break;
312+
}
313+
303314
if ($tokens[$i]['type'] === 'T_NULLABLE'
304315
// Handle nullable tokens in PHPCS < 2.8.0.
305316
|| (\defined('T_NULLABLE') === false && $tokens[$i]['code'] === \T_INLINE_THEN)
@@ -391,6 +402,7 @@ public static function getProperties(File $phpcsFile, $stackPtr)
391402
* `T_STRING` tokens and examine them to check if these are arrow functions.
392403
* - Support for PHP 8.0 union types.
393404
* - Support for PHP 8.0 constructor property promotion.
405+
* - Support for namespace operator in type declarations.
394406
*
395407
* @see \PHP_CodeSniffer\Files\File::getMethodParameters() Original source.
396408
* @see \PHPCSUtils\BackCompat\BCFile::getMethodParameters() Cross-version compatible version of the original.
@@ -494,6 +506,7 @@ public static function getParameters(File $phpcsFile, $stackPtr)
494506
case 'T_FALSE': // Union types.
495507
case 'T_NULL': // Union types.
496508
case 'T_STRING':
509+
case 'T_NAMESPACE':
497510
case 'T_NS_SEPARATOR':
498511
case 'T_BITWISE_OR': // Union type separator.
499512
if ($typeHintToken === false) {

PHPCSUtils/Utils/Variables.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class Variables
8181
* other non-property variables passed to the method.
8282
* - Defensive coding against incorrect calls to this method.
8383
* - Support for PHP 8.0 union types.
84+
* - Support for namespace operator in type declarations.
8485
*
8586
* @see \PHP_CodeSniffer\Files\File::getMemberProperties() Original source.
8687
* @see \PHPCSUtils\BackCompat\BCFile::getMemberProperties() Cross-version compatible version of the original.

Tests/Tokens/Collections/ParameterTypeTokensTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public function testParameterTypeTokens()
3939
\T_FALSE => \T_FALSE,
4040
\T_NULL => \T_NULL,
4141
\T_STRING => \T_STRING,
42+
\T_NAMESPACE => \T_NAMESPACE,
4243
\T_NS_SEPARATOR => \T_NS_SEPARATOR,
4344
\T_BITWISE_OR => \T_BITWISE_OR,
4445
];

Tests/Tokens/Collections/PropertyTypeTokensTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public function testPropertyTypeTokens()
3939
\T_FALSE => \T_FALSE,
4040
\T_NULL => \T_NULL,
4141
\T_STRING => \T_STRING,
42+
\T_NAMESPACE => \T_NAMESPACE,
4243
\T_NS_SEPARATOR => \T_NS_SEPARATOR,
4344
\T_BITWISE_OR => \T_BITWISE_OR,
4445
];

Tests/Tokens/Collections/ReturnTypeTokensTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public function testReturnTypeTokens()
4141
\T_FALSE => \T_FALSE,
4242
\T_NULL => \T_NULL,
4343
\T_ARRAY => \T_ARRAY,
44+
\T_NAMESPACE => \T_NAMESPACE,
4445
\T_NS_SEPARATOR => \T_NS_SEPARATOR,
4546
\T_BITWISE_OR => \T_BITWISE_OR,
4647
];

Tests/Utils/FunctionDeclarations/GetParametersDiffTest.inc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,6 @@ abstract class ConstructorPropertyPromotionAbstractMethod {
7575
// 3. The callable type is not supported for properties, but that's not the concern of this method.
7676
abstract public function __construct(public callable $y, private ...$x);
7777
}
78+
79+
/* testNamespaceOperatorTypeHint */
80+
function namespaceOperatorTypeHint(?namespace\Name $var1) {}

Tests/Utils/FunctionDeclarations/GetParametersDiffTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,32 @@ public function testPHP8ConstructorPropertyPromotionAbstractMethod()
629629
$this->getParametersTestHelper('/* ' . __FUNCTION__ . ' */', $expected);
630630
}
631631

632+
/**
633+
* Verify recognition of type declarations using the namespace operator.
634+
*
635+
* @return void
636+
*/
637+
public function testNamespaceOperatorTypeHint()
638+
{
639+
$expected = [];
640+
$expected[0] = [
641+
'token' => 9, // Offset from the T_FUNCTION token.
642+
'name' => '$var1',
643+
'content' => '?namespace\Name $var1',
644+
'pass_by_reference' => false,
645+
'reference_token' => false,
646+
'variable_length' => false,
647+
'variadic_token' => false,
648+
'type_hint' => '?namespace\Name',
649+
'type_hint_token' => 5, // Offset from the T_FUNCTION token.
650+
'type_hint_end_token' => 7, // Offset from the T_FUNCTION token.
651+
'nullable_type' => true,
652+
'comma_token' => false,
653+
];
654+
655+
$this->getParametersTestHelper('/* ' . __FUNCTION__ . ' */', $expected);
656+
}
657+
632658
/**
633659
* Test helper.
634660
*

Tests/Utils/FunctionDeclarations/GetPropertiesDiffTest.inc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,6 @@ interface FooBar {
6565
/* testPHP8DuplicateTypeInUnionWhitespaceAndComment */
6666
// Intentional fatal error - duplicate types are not allowed in union types, but that's not the concern of the method.
6767
function duplicateTypeInUnion(): int | /*comment*/ string | INT {}
68+
69+
/* testNamespaceOperatorTypeHint */
70+
function namespaceOperatorTypeHint() : ?namespace\Name {}

Tests/Utils/FunctionDeclarations/GetPropertiesDiffTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,29 @@ public function testPHP8DuplicateTypeInUnionWhitespaceAndComment()
367367
$this->getPropertiesTestHelper('/* ' . __FUNCTION__ . ' */', $expected);
368368
}
369369

370+
/**
371+
* Test a function with return type using the namespace operator.
372+
*
373+
* @return void
374+
*/
375+
public function testNamespaceOperatorTypeHint()
376+
{
377+
$expected = [
378+
'scope' => 'public',
379+
'scope_specified' => false,
380+
'return_type' => '?namespace\Name',
381+
'return_type_token' => 9, // Offset from the T_FUNCTION token.
382+
'return_type_end_token' => 11, // Offset from the T_FUNCTION token.
383+
'nullable_return_type' => true,
384+
'is_abstract' => false,
385+
'is_final' => false,
386+
'is_static' => false,
387+
'has_body' => true,
388+
];
389+
390+
$this->getPropertiesTestHelper('/* ' . __FUNCTION__ . ' */', $expected);
391+
}
392+
370393
/**
371394
* Test helper.
372395
*

Tests/Utils/FunctionDeclarations/IsArrowFunctionTest.inc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ $fn = fn($x) : ?\My\NS\ClassName => $x;
6464
/* testReturnTypeNullableFQNClass */
6565
$a = fn(?\DateTime $x) : ?\DateTime => $x;
6666

67+
/* testNamespaceOperatorInTypes */
68+
$fn = fn(namespace\Foo $a) : ?namespace\Foo => $a;
69+
6770
/* testReturnTypeSelf */
6871
$fn = fn(self $a) : ?self => $a;
6972

Tests/Utils/FunctionDeclarations/IsArrowFunctionTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,18 @@ public function dataArrowFunction()
348348
],
349349
],
350350
],
351+
'arrow-function-with-namespace-operator-in-types' => [
352+
'/* testNamespaceOperatorInTypes */',
353+
[
354+
'is' => true,
355+
'get' => [
356+
'parenthesis_opener' => 1,
357+
'parenthesis_closer' => 7,
358+
'scope_opener' => 16,
359+
'scope_closer' => 19,
360+
],
361+
],
362+
],
351363
'arrow-function-with-return-type-nullable-self' => [
352364
'/* testReturnTypeSelf */',
353365
[

Tests/Utils/Variables/GetMemberPropertiesDiffTest.inc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,8 @@ $anon = class() {
5252
// Intentional fatal error - duplicate types are not allowed in union types, but that's not the concern of the method.
5353
public int |string| /*comment*/ INT $duplicateTypeInUnion;
5454
};
55+
56+
class NSOperatorInType {
57+
/* testNamespaceOperatorTypeHint */
58+
public ?namespace\Name $prop;
59+
}

Tests/Utils/Variables/GetMemberPropertiesDiffTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,18 @@ public function dataGetMemberProperties()
232232
'nullable_type' => false,
233233
],
234234
],
235+
'namespace-operator-type-declaration' => [
236+
'/* testNamespaceOperatorTypeHint */',
237+
[
238+
'scope' => 'public',
239+
'scope_specified' => true,
240+
'is_static' => false,
241+
'type' => '?namespace\Name',
242+
'type_token' => -4, // Offset from the T_VARIABLE token.
243+
'type_end_token' => -2, // Offset from the T_VARIABLE token.
244+
'nullable_type' => true,
245+
],
246+
],
235247
];
236248
}
237249
}

0 commit comments

Comments
 (0)