Skip to content

Commit 6bcecb0

Browse files
committed
Merge branch 'feature/tokenizer-goto-bugfix' of https://github.com/jrfnl/PHP_CodeSniffer
2 parents b0786e1 + 2351cc9 commit 6bcecb0

File tree

4 files changed

+231
-0
lines changed

4 files changed

+231
-0
lines changed

package.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
160160
<file baseinstalldir="" name="BackfillNumericSeparatorTest.php" role="test" />
161161
<file baseinstalldir="" name="BitwiseOrTest.inc" role="test" />
162162
<file baseinstalldir="" name="BitwiseOrTest.php" role="test" />
163+
<file baseinstalldir="" name="GotoLabelTest.inc" role="test" />
164+
<file baseinstalldir="" name="GotoLabelTest.php" role="test" />
163165
<file baseinstalldir="" name="NullsafeObjectOperatorTest.inc" role="test" />
164166
<file baseinstalldir="" name="NullsafeObjectOperatorTest.php" role="test" />
165167
<file baseinstalldir="" name="ScopeSettingWithNamespaceOperatorTest.inc" role="test" />
@@ -2048,6 +2050,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
20482050
<install as="CodeSniffer/Core/Tokenizer/BackfillNumericSeparatorTest.inc" name="tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc" />
20492051
<install as="CodeSniffer/Core/Tokenizer/BitwiseOrTest.php" name="tests/Core/Tokenizer/BitwiseOrTest.php" />
20502052
<install as="CodeSniffer/Core/Tokenizer/BitwiseOrTest.inc" name="tests/Core/Tokenizer/BitwiseOrTest.inc" />
2053+
<install as="CodeSniffer/Core/Tokenizer/GotoLabelTest.php" name="tests/Core/Tokenizer/GotoLabelTest.php" />
2054+
<install as="CodeSniffer/Core/Tokenizer/GotoLabelTest.inc" name="tests/Core/Tokenizer/GotoLabelTest.inc" />
20512055
<install as="CodeSniffer/Core/Tokenizer/NullsafeObjectOperatorTest.php" name="tests/Core/Tokenizer/NullsafeObjectOperatorTest.php" />
20522056
<install as="CodeSniffer/Core/Tokenizer/NullsafeObjectOperatorTest.inc" name="tests/Core/Tokenizer/NullsafeObjectOperatorTest.inc" />
20532057
<install as="CodeSniffer/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php" name="tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php" />
@@ -2120,6 +2124,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
21202124
<install as="CodeSniffer/Core/Tokenizer/BackfillNumericSeparatorTest.inc" name="tests/Core/Tokenizer/BackfillNumericSeparatorTest.inc" />
21212125
<install as="CodeSniffer/Core/Tokenizer/BitwiseOrTest.php" name="tests/Core/Tokenizer/BitwiseOrTest.php" />
21222126
<install as="CodeSniffer/Core/Tokenizer/BitwiseOrTest.inc" name="tests/Core/Tokenizer/BitwiseOrTest.inc" />
2127+
<install as="CodeSniffer/Core/Tokenizer/GotoLabelTest.php" name="tests/Core/Tokenizer/GotoLabelTest.php" />
2128+
<install as="CodeSniffer/Core/Tokenizer/GotoLabelTest.inc" name="tests/Core/Tokenizer/GotoLabelTest.inc" />
21232129
<install as="CodeSniffer/Core/Tokenizer/NullsafeObjectOperatorTest.php" name="tests/Core/Tokenizer/NullsafeObjectOperatorTest.php" />
21242130
<install as="CodeSniffer/Core/Tokenizer/NullsafeObjectOperatorTest.inc" name="tests/Core/Tokenizer/NullsafeObjectOperatorTest.inc" />
21252131
<install as="CodeSniffer/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php" name="tests/Core/Tokenizer/ScopeSettingWithNamespaceOperatorTest.php" />

src/Tokenizers/PHP.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,7 @@ function return types. We want to keep the parenthesis map clean,
15721572
$stopTokens = [
15731573
T_CASE => true,
15741574
T_SEMICOLON => true,
1575+
T_OPEN_TAG => true,
15751576
T_OPEN_CURLY_BRACKET => true,
15761577
T_INLINE_THEN => true,
15771578
];
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/* testGotoStatement */
4+
goto marker;
5+
echo 'Foo';
6+
7+
/* testGotoDeclaration */
8+
marker:
9+
echo 'Bar';
10+
11+
/* testGotoStatementInLoop */
12+
for($i=0,$j=50; $i<100; $i++) {
13+
while($j--) {
14+
if($j==17) GOTO end;
15+
}
16+
}
17+
echo "i = $i";
18+
?>
19+
<div><?php $cond ? TEST_A : TEST_B ?></div>
20+
21+
<?php
22+
/* testGotoDeclarationOutsideLoop */
23+
end:
24+
echo 'j hit 17';
25+
26+
switch ($x) {
27+
/* testNotGotoDeclarationGlobalConstant */
28+
case CONSTANT:
29+
// Do something.
30+
break;
31+
32+
/* testNotGotoDeclarationNamespacedConstant */
33+
case MyNS\CONSTANT:
34+
// Do something.
35+
break;
36+
37+
/* testNotGotoDeclarationClassConstant */
38+
case MyClass::CONSTANT:
39+
// Do something.
40+
break;
41+
42+
/* testNotGotoDeclarationClassProperty */
43+
case $obj->property:
44+
// Do something.
45+
break;
46+
}
47+
48+
switch (true) {
49+
/* testNotGotoDeclarationGlobalConstantInTernary */
50+
case $x === ($cond) ? CONST_A : CONST_B:
51+
// Do something.
52+
break;
53+
}
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<?php
2+
/**
3+
* Tests the tokenization of goto declarations and statements.
4+
*
5+
* @author Juliette Reinders Folmer <[email protected]>
6+
* @copyright 2020 Squiz Pty Ltd (ABN 77 084 670 600)
7+
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8+
*/
9+
10+
namespace PHP_CodeSniffer\Tests\Core\Tokenizer;
11+
12+
use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest;
13+
14+
class GotoLabelTest extends AbstractMethodUnitTest
15+
{
16+
17+
18+
/**
19+
* Verify that the label in a goto statement is tokenized as T_STRING.
20+
*
21+
* @param string $testMarker The comment prefacing the target token.
22+
* @param string $testContent The token content to expect.
23+
*
24+
* @dataProvider dataGotoStatement
25+
* @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize
26+
*
27+
* @return void
28+
*/
29+
public function testGotoStatement($testMarker, $testContent)
30+
{
31+
$tokens = self::$phpcsFile->getTokens();
32+
33+
$label = $this->getTargetToken($testMarker, T_STRING);
34+
35+
$this->assertInternalType('int', $label);
36+
$this->assertSame($testContent, $tokens[$label]['content']);
37+
38+
}//end testGotoStatement()
39+
40+
41+
/**
42+
* Data provider.
43+
*
44+
* @see testGotoStatement()
45+
*
46+
* @return array
47+
*/
48+
public function dataGotoStatement()
49+
{
50+
return [
51+
[
52+
'/* testGotoStatement */',
53+
'marker',
54+
],
55+
[
56+
'/* testGotoStatementInLoop */',
57+
'end',
58+
],
59+
];
60+
61+
}//end dataGotoStatement()
62+
63+
64+
/**
65+
* Verify that the label in a goto declaration is tokenized as T_GOTO_LABEL.
66+
*
67+
* @param string $testMarker The comment prefacing the target token.
68+
* @param string $testContent The token content to expect.
69+
*
70+
* @dataProvider dataGotoDeclaration
71+
* @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize
72+
*
73+
* @return void
74+
*/
75+
public function testGotoDeclaration($testMarker, $testContent)
76+
{
77+
$tokens = self::$phpcsFile->getTokens();
78+
79+
$label = $this->getTargetToken($testMarker, T_GOTO_LABEL);
80+
81+
$this->assertInternalType('int', $label);
82+
$this->assertSame($testContent, $tokens[$label]['content']);
83+
84+
}//end testGotoDeclaration()
85+
86+
87+
/**
88+
* Data provider.
89+
*
90+
* @see testGotoDeclaration()
91+
*
92+
* @return array
93+
*/
94+
public function dataGotoDeclaration()
95+
{
96+
return [
97+
[
98+
'/* testGotoDeclaration */',
99+
'marker:',
100+
],
101+
[
102+
'/* testGotoDeclarationOutsideLoop */',
103+
'end:',
104+
],
105+
];
106+
107+
}//end dataGotoDeclaration()
108+
109+
110+
/**
111+
* Verify that the constant used in a switch - case statement is not confused with a goto label.
112+
*
113+
* @param string $testMarker The comment prefacing the target token.
114+
* @param string $testContent The token content to expect.
115+
*
116+
* @dataProvider dataNotAGotoDeclaration
117+
* @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize
118+
*
119+
* @return void
120+
*/
121+
public function testNotAGotoDeclaration($testMarker, $testContent)
122+
{
123+
$tokens = self::$phpcsFile->getTokens();
124+
$target = $this->getTargetToken($testMarker, [T_GOTO_LABEL, T_STRING], $testContent);
125+
126+
$this->assertSame(T_STRING, $tokens[$target]['code']);
127+
$this->assertSame('T_STRING', $tokens[$target]['type']);
128+
129+
}//end testNotAGotoDeclaration()
130+
131+
132+
/**
133+
* Data provider.
134+
*
135+
* @see testNotAGotoDeclaration()
136+
*
137+
* @return array
138+
*/
139+
public function dataNotAGotoDeclaration()
140+
{
141+
return [
142+
[
143+
'/* testNotGotoDeclarationGlobalConstant */',
144+
'CONSTANT',
145+
],
146+
[
147+
'/* testNotGotoDeclarationNamespacedConstant */',
148+
'CONSTANT',
149+
],
150+
[
151+
'/* testNotGotoDeclarationClassConstant */',
152+
'CONSTANT',
153+
],
154+
[
155+
'/* testNotGotoDeclarationClassProperty */',
156+
'property',
157+
],
158+
[
159+
'/* testNotGotoDeclarationGlobalConstantInTernary */',
160+
'CONST_A',
161+
],
162+
[
163+
'/* testNotGotoDeclarationGlobalConstantInTernary */',
164+
'CONST_B',
165+
],
166+
];
167+
168+
}//end dataNotAGotoDeclaration()
169+
170+
171+
}//end class

0 commit comments

Comments
 (0)