Skip to content

Commit 0fa0724

Browse files
authored
Merge pull request #132 from PHPCSStandards/feature/namespace-get-type-improve-operator-detection
Namespaces::getType(): improve detection of namespace keyword as operator
2 parents 442f5d3 + 49324bb commit 0fa0724

File tree

3 files changed

+68
-5
lines changed

3 files changed

+68
-5
lines changed

PHPCSUtils/Utils/Namespaces.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHP_CodeSniffer\Files\File;
1515
use PHP_CodeSniffer\Util\Tokens;
1616
use PHPCSUtils\BackCompat\BCFile;
17+
use PHPCSUtils\BackCompat\BCTokens;
1718
use PHPCSUtils\Tokens\Collections;
1819
use PHPCSUtils\Utils\Conditions;
1920
use PHPCSUtils\Utils\GetTokensAsString;
@@ -46,6 +47,26 @@ class Namespaces
4647
*/
4748
public static function getType(File $phpcsFile, $stackPtr)
4849
{
50+
static $findAfter;
51+
52+
if (isset($findAfter) === false) {
53+
/*
54+
* Set up array of tokens which can only be used in combination with the keyword as operator
55+
* and which cannot be confused with other keywords.
56+
*/
57+
$findAfter = BCTokens::assignmentTokens()
58+
+ BCTokens::comparisonTokens()
59+
+ BCTokens::operators()
60+
+ Tokens::$castTokens
61+
+ Tokens::$blockOpeners
62+
+ Collections::$incrementDecrementOperators
63+
+ Collections::$objectOperators;
64+
65+
$findAfter[\T_OPEN_CURLY_BRACKET] = \T_OPEN_CURLY_BRACKET;
66+
$findAfter[\T_OPEN_SQUARE_BRACKET] = \T_OPEN_SQUARE_BRACKET;
67+
$findAfter[\T_OPEN_SHORT_ARRAY] = \T_OPEN_SHORT_ARRAY;
68+
}
69+
4970
$tokens = $phpcsFile->getTokens();
5071

5172
if (isset($tokens[$stackPtr]) === false || $tokens[$stackPtr]['code'] !== \T_NAMESPACE) {
@@ -80,8 +101,9 @@ public static function getType(File $phpcsFile, $stackPtr)
80101
return 'declaration';
81102
}
82103

83-
if ($start !== $stackPtr
84-
&& $tokens[$next]['code'] === \T_NS_SEPARATOR
104+
if ($tokens[$next]['code'] === \T_NS_SEPARATOR
105+
&& ($start !== $stackPtr
106+
|| $phpcsFile->findNext($findAfter, ($stackPtr + 1), null, false, null, true) !== false)
85107
) {
86108
return 'operator';
87109
}

Tests/Utils/Namespaces/NamespaceTypeTest.inc

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,24 @@ function closedScope() {
2828
echo namespace\ClassName::method();
2929

3030
while( true ) {
31-
/* testNamespaceOperatorInParentheses */
32-
function_call( namespace\ClassName::$property );
33-
}
31+
/* testNamespaceOperatorInParentheses */
32+
function_call( namespace\ClassName::$property );
33+
}
3434
}
3535

36+
/* testNamespaceOperatorGlobalNamespaceStartOfStatementFunctionCall */
37+
namespace\functionCall();
38+
39+
/* testNamespaceOperatorGlobalNamespaceStartOfStatementCombiWithNonConfusingToken1 */
40+
namespace\CONSTANT === 'test' or die();
41+
42+
/* testNamespaceOperatorGlobalNamespaceStartOfStatementCombiWithNonConfusingToken2 */
43+
namespace\ClassName::$property++;
44+
45+
/* testNamespaceOperatorGlobalNamespaceStartOfStatementCombiWithNonConfusingToken3 */
46+
namespace\CONSTANT['key'];
47+
48+
3649
/* testParseErrorScopedNamespaceDeclaration */
3750
function testScope() {
3851
namespace My\Namespace;

Tests/Utils/Namespaces/NamespaceTypeTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,34 @@ public function dataNamespaceType()
156156
'operator' => true,
157157
],
158158
],
159+
'namespace-operator-global-namespace-start-of-statement-function-call' => [
160+
'/* testNamespaceOperatorGlobalNamespaceStartOfStatementFunctionCall */',
161+
[
162+
'declaration' => false,
163+
'operator' => true,
164+
],
165+
],
166+
'namespace-operator-global-namespace-start-of-statement-with-non-confusing-token-1' => [
167+
'/* testNamespaceOperatorGlobalNamespaceStartOfStatementCombiWithNonConfusingToken1 */',
168+
[
169+
'declaration' => false,
170+
'operator' => true,
171+
],
172+
],
173+
'namespace-operator-global-namespace-start-of-statement-with-non-confusing-token-2' => [
174+
'/* testNamespaceOperatorGlobalNamespaceStartOfStatementCombiWithNonConfusingToken2 */',
175+
[
176+
'declaration' => false,
177+
'operator' => true,
178+
],
179+
],
180+
'namespace-operator-global-namespace-start-of-statement-with-non-confusing-token-3' => [
181+
'/* testNamespaceOperatorGlobalNamespaceStartOfStatementCombiWithNonConfusingToken3 */',
182+
[
183+
'declaration' => false,
184+
'operator' => true,
185+
],
186+
],
159187
'parse-error-scoped-namespace-declaration' => [
160188
'/* testParseErrorScopedNamespaceDeclaration */',
161189
[

0 commit comments

Comments
 (0)