Skip to content

Commit 14ac7eb

Browse files
committed
Tokenizer/PHP: add more tests for default keyword and double arrow
In particular, this adds tests where the `default` keyword is not used as the keyword and should be tokenized as `T_STRING`.
1 parent 2bd19c2 commit 14ac7eb

File tree

4 files changed

+356
-90
lines changed

4 files changed

+356
-90
lines changed

tests/Core/Tokenizer/DefaultKeywordTest.inc

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,105 @@ function switchWithDefaultInMatch() {
9191
}
9292
};
9393
}
94+
95+
function shortArrayWithConstantKey() {
96+
$arr = [
97+
/* testClassConstantAsShortArrayKey */
98+
SomeClass::DEFAULT => 1,
99+
/* testClassPropertyAsShortArrayKey */
100+
SomeClass->DEFAULT => 1,
101+
/* testNamespacedConstantAsShortArrayKey */
102+
// Intentional parse error PHP < 8.0. Reserved keyword used as namespaced constant.
103+
SomeNamespace\DEFAULT => 1,
104+
/* testFQNGlobalConstantAsShortArrayKey */
105+
// Intentional parse error in PHP < 8.0. Reserved keyword used as global constant.
106+
\DEFAULT => 1,
107+
];
108+
}
109+
110+
function longArrayWithConstantKey() {
111+
$arr = array(
112+
/* testClassConstantAsLongArrayKey */
113+
SomeClass::DEFAULT => 1,
114+
);
115+
}
116+
117+
function yieldWithConstantKey() {
118+
/* testClassConstantAsYieldKey */
119+
yield SomeClass::DEFAULT => 1;
120+
}
121+
122+
function longArrayWithConstantKeyNestedInMatch() {
123+
return match($x) {
124+
/* testMatchDefaultWithNestedLongArrayWithClassConstantKey */
125+
DEFAULT => array(
126+
/* testClassConstantAsLongArrayKeyNestedInMatch */
127+
SomeClass::DEFAULT => match($x) {
128+
/* testMatchDefaultWithNestedLongArrayWithClassConstantKeyLevelDown */
129+
DEFAULT => array(
130+
/* testClassConstantAsLongArrayKeyNestedInMatchLevelDown */
131+
SomeClass::DEFAULT => 1,
132+
),
133+
},
134+
),
135+
};
136+
}
137+
138+
function shortArrayWithConstantKeyNestedInMatch() {
139+
return match($x) {
140+
/* testMatchDefaultWithNestedShortArrayWithClassConstantKey */
141+
DEFAULT => [
142+
/* testClassConstantAsShortArrayKeyNestedInMatch */
143+
SomeClass::DEFAULT => match($x) {
144+
/* testMatchDefaultWithNestedShortArrayWithClassConstantKeyLevelDown */
145+
DEFAULT => [
146+
/* testClassConstantAsShortArrayKeyNestedInMatchLevelDown */
147+
SomeClass::DEFAULT => 1,
148+
],
149+
},
150+
],
151+
};
152+
}
153+
154+
155+
function longArrayWithConstantKeyWithNestedMatch() {
156+
return array(
157+
/* testClassConstantAsLongArrayKeyWithNestedMatch */
158+
SomeClass::DEFAULT => match($x) {
159+
/* testMatchDefaultNestedInLongArray */
160+
DEFAULT => 'foo'
161+
},
162+
);
163+
}
164+
165+
function shortArrayWithConstantKeyWithNestedMatch() {
166+
return [
167+
/* testClassConstantAsShortArrayKeyWithNestedMatch */
168+
SomeClass::DEFAULT => match($x) {
169+
/* testMatchDefaultNestedInShortArray */
170+
DEFAULT => 'foo'
171+
},
172+
];
173+
}
174+
175+
function switchWithConstantNonDefault($i) {
176+
switch ($i) {
177+
/* testClassConstantInSwitchCase */
178+
case SomeClass::DEFAULT:
179+
return 1;
180+
181+
/* testClassPropertyInSwitchCase */
182+
case SomeClass->DEFAULT:
183+
return 2;
184+
185+
/* testNamespacedConstantInSwitchCase */
186+
// Intentional parse error PHP < 8.0. Reserved keyword used as constant.
187+
case SomeNamespace\DEFAULT:
188+
return 2;
189+
190+
/* testNamespaceRelativeConstantInSwitchCase */
191+
// Intentional parse error PHP < 8.0. Reserved keyword used as global constant.
192+
case namespace\DEFAULT:
193+
return 2;
194+
}
195+
}

tests/Core/Tokenizer/DefaultKeywordTest.php

Lines changed: 100 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,20 @@ class DefaultKeywordTest extends AbstractMethodUnitTest
2222
* Note: Cases and default structures within a match structure do *NOT* get case/default scope
2323
* conditions, in contrast to case and default structures in switch control structures.
2424
*
25-
* @param string $testMarker The comment prefacing the target token.
25+
* @param string $testMarker The comment prefacing the target token.
26+
* @param string $testContent The token content to look for.
2627
*
2728
* @dataProvider dataMatchDefault
2829
* @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize
2930
* @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap
3031
*
3132
* @return void
3233
*/
33-
public function testMatchDefault($testMarker)
34+
public function testMatchDefault($testMarker, $testContent='default')
3435
{
3536
$tokens = self::$phpcsFile->getTokens();
3637

37-
$token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT]);
38+
$token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent);
3839
$tokenArray = $tokens[$token];
3940

4041
$this->assertSame(T_MATCH_DEFAULT, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_MATCH_DEFAULT (code)');
@@ -57,11 +58,36 @@ public function testMatchDefault($testMarker)
5758
public function dataMatchDefault()
5859
{
5960
return [
60-
'simple_match_default' => ['/* testSimpleMatchDefault */'],
61-
'match_default_in_switch_case_1' => ['/* testMatchDefaultNestedInSwitchCase1 */'],
62-
'match_default_in_switch_case_2' => ['/* testMatchDefaultNestedInSwitchCase2 */'],
63-
'match_default_in_switch_default' => ['/* testMatchDefaultNestedInSwitchDefault */'],
64-
'match_default_containing_switch' => ['/* testMatchDefault */'],
61+
'simple_match_default' => ['/* testSimpleMatchDefault */'],
62+
'match_default_in_switch_case_1' => ['/* testMatchDefaultNestedInSwitchCase1 */'],
63+
'match_default_in_switch_case_2' => ['/* testMatchDefaultNestedInSwitchCase2 */'],
64+
'match_default_in_switch_default' => ['/* testMatchDefaultNestedInSwitchDefault */'],
65+
'match_default_containing_switch' => ['/* testMatchDefault */'],
66+
67+
'match_default_with_nested_long_array_and_default_key' => [
68+
'/* testMatchDefaultWithNestedLongArrayWithClassConstantKey */',
69+
'DEFAULT',
70+
],
71+
'match_default_with_nested_long_array_and_default_key_2' => [
72+
'/* testMatchDefaultWithNestedLongArrayWithClassConstantKeyLevelDown */',
73+
'DEFAULT',
74+
],
75+
'match_default_with_nested_short_array_and_default_key' => [
76+
'/* testMatchDefaultWithNestedShortArrayWithClassConstantKey */',
77+
'DEFAULT',
78+
],
79+
'match_default_with_nested_short_array_and_default_key_2' => [
80+
'/* testMatchDefaultWithNestedShortArrayWithClassConstantKeyLevelDown */',
81+
'DEFAULT',
82+
],
83+
'match_default_in_long_array' => [
84+
'/* testMatchDefaultNestedInLongArray */',
85+
'DEFAULT',
86+
],
87+
'match_default_in_short_array' => [
88+
'/* testMatchDefaultNestedInShortArray */',
89+
'DEFAULT',
90+
],
6591
];
6692

6793
}//end dataMatchDefault()
@@ -78,17 +104,18 @@ public function dataMatchDefault()
78104
* @param int $openerOffset The expected offset of the scope opener in relation to the testMarker.
79105
* @param int $closerOffset The expected offset of the scope closer in relation to the testMarker.
80106
* @param int|null $conditionStop The expected offset at which tokens stop having T_DEFAULT as a scope condition.
107+
* @param string $testContent The token content to look for.
81108
*
82109
* @dataProvider dataSwitchDefault
83110
* @covers PHP_CodeSniffer\Tokenizers\Tokenizer::recurseScopeMap
84111
*
85112
* @return void
86113
*/
87-
public function testSwitchDefault($testMarker, $openerOffset, $closerOffset, $conditionStop=null)
114+
public function testSwitchDefault($testMarker, $openerOffset, $closerOffset, $conditionStop=null, $testContent='default')
88115
{
89116
$tokens = self::$phpcsFile->getTokens();
90117

91-
$token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT]);
118+
$token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent);
92119
$tokenArray = $tokens[$token];
93120
$expectedScopeOpener = ($token + $openerOffset);
94121
$expectedScopeCloser = ($token + $closerOffset);
@@ -182,4 +209,67 @@ public function dataSwitchDefault()
182209
}//end dataSwitchDefault()
183210

184211

212+
/**
213+
* Verify that the retokenization of `T_DEFAULT` tokens in match constructs, doesn't negatively
214+
* impact the tokenization of `T_STRING` tokens with the contents 'default' which aren't in
215+
* actual fact the default keyword.
216+
*
217+
* @param string $testMarker The comment prefacing the target token.
218+
* @param string $testContent The token content to look for.
219+
*
220+
* @dataProvider dataNotDefaultKeyword
221+
* @covers PHP_CodeSniffer\Tokenizers\PHP::processAdditional
222+
*
223+
* @return void
224+
*/
225+
public function testNotDefaultKeyword($testMarker, $testContent='DEFAULT')
226+
{
227+
$tokens = self::$phpcsFile->getTokens();
228+
229+
$token = $this->getTargetToken($testMarker, [T_MATCH_DEFAULT, T_DEFAULT, T_STRING], $testContent);
230+
$tokenArray = $tokens[$token];
231+
232+
$this->assertSame(T_STRING, $tokenArray['code'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (code)');
233+
$this->assertSame('T_STRING', $tokenArray['type'], 'Token tokenized as '.$tokenArray['type'].', not T_STRING (type)');
234+
235+
$this->assertArrayNotHasKey('scope_condition', $tokenArray, 'Scope condition is set');
236+
$this->assertArrayNotHasKey('scope_opener', $tokenArray, 'Scope opener is set');
237+
$this->assertArrayNotHasKey('scope_closer', $tokenArray, 'Scope closer is set');
238+
239+
}//end testNotDefaultKeyword()
240+
241+
242+
/**
243+
* Data provider.
244+
*
245+
* @see testNotDefaultKeyword()
246+
*
247+
* @return array
248+
*/
249+
public function dataNotDefaultKeyword()
250+
{
251+
return [
252+
'class-constant-as-short-array-key' => ['/* testClassConstantAsShortArrayKey */'],
253+
'class-property-as-short-array-key' => ['/* testClassPropertyAsShortArrayKey */'],
254+
'namespaced-constant-as-short-array-key' => ['/* testNamespacedConstantAsShortArrayKey */'],
255+
'fqn-global-constant-as-short-array-key' => ['/* testFQNGlobalConstantAsShortArrayKey */'],
256+
'class-constant-as-long-array-key' => ['/* testClassConstantAsLongArrayKey */'],
257+
'class-constant-as-yield-key' => ['/* testClassConstantAsYieldKey */'],
258+
259+
'class-constant-as-long-array-key-nested-in-match' => ['/* testClassConstantAsLongArrayKeyNestedInMatch */'],
260+
'class-constant-as-long-array-key-nested-in-match-2' => ['/* testClassConstantAsLongArrayKeyNestedInMatchLevelDown */'],
261+
'class-constant-as-short-array-key-nested-in-match' => ['/* testClassConstantAsShortArrayKeyNestedInMatch */'],
262+
'class-constant-as-short-array-key-nested-in-match-2' => ['/* testClassConstantAsShortArrayKeyNestedInMatchLevelDown */'],
263+
'class-constant-as-long-array-key-with-nested-match' => ['/* testClassConstantAsLongArrayKeyWithNestedMatch */'],
264+
'class-constant-as-short-array-key-with-nested-match' => ['/* testClassConstantAsShortArrayKeyWithNestedMatch */'],
265+
266+
'class-constant-in-switch-case' => ['/* testClassConstantInSwitchCase */'],
267+
'class-property-in-switch-case' => ['/* testClassPropertyInSwitchCase */'],
268+
'namespaced-constant-in-switch-case' => ['/* testNamespacedConstantInSwitchCase */'],
269+
'namespace-relative-constant-in-switch-case' => ['/* testNamespaceRelativeConstantInSwitchCase */'],
270+
];
271+
272+
}//end dataNotDefaultKeyword()
273+
274+
185275
}//end class

tests/Core/Tokenizer/DoubleArrowTest.inc

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,63 @@ function matchInShortList() {
219219
/* testMatchArrowInShortListKey */
220220
[match($x) {1 => 1, 2 => 2} /* testShortListArrowWithMatchInKey */ => $a] = $array;
221221
}
222+
223+
function longArrayWithConstantKey() {
224+
$arr = array(
225+
/* testLongArrayArrowWithClassConstantKey */
226+
SomeClass::DEFAULT => 1,
227+
);
228+
}
229+
230+
function shortArrayWithConstantKey() {
231+
$arr = [
232+
/* testShortArrayArrowWithClassConstantKey */
233+
SomeClass::DEFAULT => 1,
234+
];
235+
}
236+
237+
function yieldWithConstantKey() {
238+
/* testYieldArrowWithClassConstantKey */
239+
yield SomeClass::DEFAULT => 1;
240+
}
241+
242+
function longArrayWithConstantKeyNestedInMatch() {
243+
return match($x) {
244+
/* testMatchArrowWithNestedLongArrayWithClassConstantKey */
245+
default => array(
246+
/* testLongArrayArrowWithClassConstantKeyNestedInMatch */
247+
SomeClass::DEFAULT => 1,
248+
),
249+
};
250+
}
251+
252+
function shortArrayWithConstantKeyNestedInMatch() {
253+
return match($x) {
254+
/* testMatchArrowWithNestedShortArrayWithClassConstantKey */
255+
default => [
256+
/* testShortArrayArrowWithClassConstantKeyNestedInMatch */
257+
SomeClass::DEFAULT => 1,
258+
],
259+
};
260+
}
261+
262+
263+
function longArrayWithConstantKeyWithNestedMatch() {
264+
return array(
265+
/* testLongArrayArrowWithClassConstantKeyWithNestedMatch */
266+
SomeClass::DEFAULT => match($x) {
267+
/* testMatchArrowNestedInLongArrayWithClassConstantKey */
268+
default => 'foo'
269+
},
270+
);
271+
}
272+
273+
function shortArrayWithConstantKeyWithNestedMatch() {
274+
return [
275+
/* testShortArrayArrowWithClassConstantKeyWithNestedMatch */
276+
SomeClass::DEFAULT => match($x) {
277+
/* testMatchArrowNestedInShortArrayWithClassConstantKey */
278+
default => 'foo'
279+
},
280+
];
281+
}

0 commit comments

Comments
 (0)