Skip to content

Commit 3466697

Browse files
authored
Merge pull request #493 from PHPCSStandards/feature/spacesfixer-extra-defensive-coding
SpacesFixer: prevent an unwarranted exception
2 parents 16b2935 + 977e71d commit 3466697

File tree

4 files changed

+148
-1
lines changed

4 files changed

+148
-1
lines changed

PHPCSUtils/Fixers/SpacesFixer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public static function checkAndFix(
133133
}
134134

135135
$nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($ptrA + 1), null, true);
136-
if ($nextNonEmpty < $ptrB) {
136+
if ($nextNonEmpty !== false && $nextNonEmpty < $ptrB) {
137137
throw new RuntimeException(
138138
'The $stackPtr and the $secondPtr token must be adjacent tokens separated only'
139139
. ' by whitespace and/or comments'
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
3+
/* testCommentAtEndOfFile */
4+
echo $foo; // Comment.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
3+
/* testCommentAtEndOfFile */
4+
echo $foo; // Comment.
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<?php
2+
/**
3+
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers.
4+
*
5+
* @package PHPCSUtils
6+
* @copyright 2019-2020 PHPCSUtils Contributors
7+
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3
8+
* @link https://github.com/PHPCSStandards/PHPCSUtils
9+
*/
10+
11+
namespace PHPCSUtils\Tests\Fixers\SpacesFixer;
12+
13+
use PHPCSUtils\Fixers\SpacesFixer;
14+
use PHPCSUtils\TestUtils\UtilityMethodTestCase;
15+
16+
/**
17+
* Tests for the \PHPCSUtils\Fixers\SpacesFixer::checkAndFix() method.
18+
*
19+
* @covers \PHPCSUtils\Fixers\SpacesFixer::checkAndFix
20+
*
21+
* @group fixers
22+
*
23+
* @since 1.0.8
24+
*/
25+
final class SpacesFixerAtEOFTest extends UtilityMethodTestCase
26+
{
27+
28+
/**
29+
* Expected number of spaces to use for these tests.
30+
*
31+
* @var int|string
32+
*/
33+
const SPACES = 1;
34+
35+
/**
36+
* Dummy error message phrase to use for the test.
37+
*
38+
* @var string
39+
*/
40+
const MSG = 'Expected: %s. Found: %s';
41+
42+
/**
43+
* Dummy error code to use for the test.
44+
*
45+
* Using the dummy full error code to force it to record.
46+
*
47+
* @var string
48+
*/
49+
const CODE = 'PHPCSUtils.SpacesFixer.Test.Found';
50+
51+
/**
52+
* Test marker.
53+
*
54+
* @var string
55+
*/
56+
const TESTMARKER = '/* testCommentAtEndOfFile */';
57+
58+
/**
59+
* Set the name of a sniff to pass to PHPCS to limit the run (and force it to record errors).
60+
*
61+
* @var array
62+
*/
63+
protected static $selectedSniff = ['PHPCSUtils.SpacesFixer.Test'];
64+
65+
/**
66+
* Test that violations are correctly reported when there is no non-empty token after the second stack pointer.
67+
*
68+
* @return void
69+
*/
70+
public function testCheckAndFix()
71+
{
72+
$stackPtr = $this->getTargetToken(self::TESTMARKER, \T_SEMICOLON);
73+
$secondPtr = $this->getTargetToken(self::TESTMARKER, \T_COMMENT);
74+
75+
SpacesFixer::checkAndFix(
76+
self::$phpcsFile,
77+
$stackPtr,
78+
$secondPtr,
79+
self::SPACES,
80+
self::MSG,
81+
self::CODE
82+
);
83+
84+
$result = self::$phpcsFile->getErrors();
85+
$tokens = self::$phpcsFile->getTokens();
86+
87+
if (isset($result[$tokens[$stackPtr]['line']][$tokens[$stackPtr]['column']]) === false) {
88+
$this->fail('Expected 1 violation. None found.');
89+
}
90+
91+
$messages = $result[$tokens[$stackPtr]['line']][$tokens[$stackPtr]['column']];
92+
93+
// Expect one violation.
94+
$this->assertCount(1, $messages, 'Expected 1 violation, found: ' . \count($messages));
95+
96+
/*
97+
* Test the violation details.
98+
*/
99+
$this->assertSame(self::CODE, $messages[0]['source'], 'Error code comparison failed');
100+
101+
$this->assertSame(true, $messages[0]['fixable'], 'Fixability comparison failed');
102+
}
103+
104+
/**
105+
* Test that the fixes are correctly made when there is no non-empty token after the second stack pointer.
106+
*
107+
* @return void
108+
*/
109+
public function testFixesMade()
110+
{
111+
self::$phpcsFile->fixer->startFile(self::$phpcsFile);
112+
self::$phpcsFile->fixer->enabled = true;
113+
114+
$stackPtr = $this->getTargetToken(self::TESTMARKER, \T_SEMICOLON);
115+
$secondPtr = $this->getTargetToken(self::TESTMARKER, \T_COMMENT);
116+
117+
SpacesFixer::checkAndFix(
118+
self::$phpcsFile,
119+
$stackPtr,
120+
$secondPtr,
121+
self::SPACES,
122+
self::MSG,
123+
self::CODE
124+
);
125+
126+
$fixedFile = self::$phpcsFile->getFilename() . '.fixed';
127+
$result = self::$phpcsFile->fixer->getContents();
128+
129+
$this->assertStringEqualsFile(
130+
$fixedFile,
131+
$result,
132+
\sprintf(
133+
'Fixed version of %s does not match expected version in %s',
134+
\basename(self::$caseFile),
135+
\basename($fixedFile)
136+
)
137+
);
138+
}
139+
}

0 commit comments

Comments
 (0)