Skip to content

Commit 295f567

Browse files
committed
Uses a unique file name for DummyFile to avoid issues with PHPCSUtils caching
1 parent 671176f commit 295f567

File tree

10 files changed

+141
-24
lines changed

10 files changed

+141
-24
lines changed

Scripts/DocCodeExamples/CodeBlock.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,24 @@ final class CodeBlock
3131
*/
3232
public $content;
3333

34+
/**
35+
* The position of the code block in the XML documentation file.
36+
*
37+
* @var int
38+
*/
39+
public $position;
40+
3441
/**
3542
* Constructor.
3643
*
37-
* @param string $title The title of the code block.
38-
* @param string $content The content of the code block.
44+
* @param string $title The title of the code block.
45+
* @param string $content The content of the code block.
46+
* @param int $position The position of the code block in the XML documentation file.
3947
*/
40-
public function __construct(string $title, string $content)
48+
public function __construct(string $title, string $content, int $position)
4149
{
42-
$this->title = $title;
43-
$this->content = $content;
50+
$this->title = $title;
51+
$this->content = $content;
52+
$this->position = $position;
4453
}
4554
}

Scripts/DocCodeExamples/CodeBlocksExtractor.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
final class CodeBlocksExtractor
1717
{
1818

19+
/**
20+
* Counter for the code blocks for a given XML file.
21+
*
22+
* @var int
23+
*/
24+
private $codeBlocksCounter = 0;
25+
1926
/**
2027
* Extract the valid and invalid code blocks from the XML documentation file.
2128
* Note that each returned code block might contain more than one code example.
@@ -28,7 +35,8 @@ final class CodeBlocksExtractor
2835
*/
2936
public function extract(string $xmlDocFilePath): array
3037
{
31-
$xmlDoc = $this->loadXmlFile($xmlDocFilePath);
38+
$this->codeBlocksCounter = 0;
39+
$xmlDoc = $this->loadXmlFile($xmlDocFilePath);
3240

3341
$codeBlocks = [];
3442

@@ -110,7 +118,7 @@ private function extractCodeBlocksOfGivenType(\DOMXPath $xpath, string $type): a
110118
$title = $codeBlockElement->getAttribute('title');
111119
$content = \trim($codeBlockElement->nodeValue);
112120
$content = \preg_replace('`</?em>`', '', $content);
113-
$codeBlocks[] = new CodeBlock($title, $content);
121+
$codeBlocks[] = new CodeBlock($title, $content, $this->codeBlocksCounter++);
114122
}
115123

116124
return $codeBlocks;

Scripts/DocCodeExamples/XmlDocValidator.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,13 @@ private function verifyCodeBlock(CodeBlock $codeBlock, bool $isExpectedToBeValid
222222
new Tokens(); // @phpstan-ignore new.resultUnused
223223
$ruleset = new Ruleset($this->phpcsConfig);
224224

225-
$file = new DummyFile($codeBlockContent, $ruleset, $this->phpcsConfig);
225+
// Set a unique file name for the DummyFile instance to avoid cache conflicts for
226+
// sniffs that rely on PHPCSUtils functionality.
227+
$dummyFileName = md5($this->sniff . $codeBlock->position);
228+
$fileContents = 'phpcs_input_file: ' . $dummyFileName . PHP_EOL;
229+
$fileContents .= $codeBlockContent;
230+
231+
$file = new DummyFile($fileContents, $ruleset, $this->phpcsConfig);
226232
$file->process();
227233

228234
if ($isExpectedToBeValid === true && ($file->getErrorCount() !== 0 || $file->getWarningCount() !== 0)) {

Tests/DocCodeExamples/CheckTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ public static function dataConstructorTargets(): array
134134
'/CheckCodeExamplesStandard/Docs/Examples/CorrectExamplesStandard.xml',
135135
'/CheckCodeExamplesStandard/Docs/Examples/IncorrectInvalidExampleStandard.xml',
136136
'/CheckCodeExamplesStandard/Docs/Examples/IncorrectValidExampleStandard.xml',
137+
'/CheckCodeExamplesStandard/Docs/Examples/PhpcsUtilsCacheStandard.xml',
137138
'/CheckCodeExamplesStandard/Docs/Examples/SyntaxErrorExampleStandard.xml',
138139
'/CheckDocPathStandard/Docs/MissingCategoryDirStandard.xml',
139140
'/UninstalledStandard/Docs/Category/TestErrorWhenStandardIsNotInstalledStandard.xml',

Tests/DocCodeExamples/CodeBlocksExtractorTest.php

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,20 @@ final class CodeBlocksExtractorTest extends XTestCase
3232
*
3333
* @var CodeBlocksExtractor
3434
*/
35-
private $codeBlocksExtractor;
35+
private static $codeBlocksExtractor;
3636

3737
/**
38-
* Set up.
38+
* Creates a single instance of the CodeBlocksExtractor class for all the tests to simulate how
39+
* this class is used by the script (where a single instance is used to extract code blocks from
40+
* multiple XML files).
3941
*
40-
* @before
42+
* @beforeClass
4143
*
4244
* @return void
4345
*/
44-
protected function setUpPrerequisites()
46+
public static function setUpPrerequisitesBeforeClass()
4547
{
46-
$this->codeBlocksExtractor = new CodeBlocksExtractor();
48+
self::$codeBlocksExtractor = new CodeBlocksExtractor();
4749
}
4850

4951
/**
@@ -61,7 +63,7 @@ public function testExtractCodeBlocksWithInvalidFiles(string $filePath, string $
6163
$this->expectException(\RuntimeException::class);
6264
$this->expectExceptionMessage($expectedMessage);
6365

64-
$this->codeBlocksExtractor->extract($filePath);
66+
self::$codeBlocksExtractor->extract($filePath);
6567
}
6668

6769
/**
@@ -95,7 +97,7 @@ public static function dataExtractCodeBlocksWithInvalidFiles(): array
9597
*/
9698
public function testExtractCodeBlocks(string $xmlFilePath, array $expectedResult)
9799
{
98-
$codeBlocks = $this->codeBlocksExtractor->extract($xmlFilePath);
100+
$codeBlocks = self::$codeBlocksExtractor->extract($xmlFilePath);
99101

100102
$this->assertEquals($expectedResult, $codeBlocks);
101103
}
@@ -115,6 +117,19 @@ public static function dataExtractCodeBlocks(): array
115117
'invalid' => [],
116118
],
117119
],
120+
'One valid block' => [
121+
'xmlFilePath' => self::FIXTURE_DIR . 'OneValidBlock.xml',
122+
'expectedResult' => [
123+
'valid' => [
124+
new CodeBlock(
125+
'Valid: Example of a valid code block.',
126+
'// Some PHP code.',
127+
0
128+
)
129+
],
130+
'invalid' => [],
131+
],
132+
],
118133
'Valid and invalid code blocks' => [
119134
'xmlFilePath' => self::FIXTURE_DIR . 'ValidAndInvalidBlocks.xml',
120135
'expectedResult' => [
@@ -127,15 +142,17 @@ public static function dataExtractCodeBlocks(): array
127142
1,
128143
2,
129144
];
130-
}'
145+
}',
146+
0
131147
),
132148
new CodeBlock(
133149
'Valid: Elements of an array indented four spaces beyond the indentation level of the opening square bracket/parenthesis.',
134150
'$a = array(
135151
1,
136152
2,
137153
3,
138-
);'
154+
);',
155+
1
139156
),
140157
],
141158
'invalid' => [
@@ -147,15 +164,17 @@ public static function dataExtractCodeBlocks(): array
147164
1,
148165
2,
149166
];
150-
}'
167+
}',
168+
2
151169
),
152170
new CodeBlock(
153171
'Invalid: Elements of an array not indented four spaces beyond the indentation level of the opening square bracket/parenthesis.',
154172
'$a = array(
155173
1,
156174
2,
157175
3,
158-
);'
176+
);',
177+
3
159178
),
160179
],
161180
],

Tests/DocCodeExamples/XmlDocValidatorTest.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,28 +160,28 @@ public function testValidate($xmlPath, $expectedErrorMessage, $expectedReturnVal
160160
public static function dataValidate()
161161
{
162162
return [
163-
'All code examples match the expectation' => [
163+
'All code examples match the expectation' => [
164164
'xmlPath' => 'Tests/Fixtures/DocCodeExamples/CheckCodeExamplesStandard/Docs/Examples/CorrectExamplesStandard.xml',
165165
'expectedErrorMessage' => '',
166166
'expectedReturnValue' => true,
167167
],
168-
'One valid code example which is actually invalid' => [
168+
'One valid code example which is actually invalid' => [
169169
'xmlPath' => 'Tests/Fixtures/DocCodeExamples/CheckCodeExamplesStandard/Docs/Examples/IncorrectValidExampleStandard.xml',
170170
'expectedErrorMessage' => 'Errors found while processing Tests/Fixtures/DocCodeExamples/CheckCodeExamplesStandard/Docs/Examples/IncorrectValidExampleStandard.xml' . PHP_EOL . PHP_EOL .
171171
'ERROR: Code block is valid and PHPCS should have returned nothing, but instead it returned an error.' . PHP_EOL .
172172
'Code block title: "Valid: invalid valid code example."' . PHP_EOL .
173173
'Code block content: "function sniffValidationWillFail() {}"' . PHP_EOL . PHP_EOL,
174174
'expectedReturnValue' => false,
175175
],
176-
'One invalid code example which is actually valid' => [
176+
'One invalid code example which is actually valid' => [
177177
'xmlPath' => 'Tests/Fixtures/DocCodeExamples/CheckCodeExamplesStandard/Docs/Examples/IncorrectInvalidExampleStandard.xml',
178178
'expectedErrorMessage' => 'Errors found while processing Tests/Fixtures/DocCodeExamples/CheckCodeExamplesStandard/Docs/Examples/IncorrectInvalidExampleStandard.xml' . PHP_EOL . PHP_EOL .
179179
'ERROR: Code block is invalid and PHPCS should have returned an error message, but instead it returned nothing.' . PHP_EOL .
180180
'Code block title: "Invalid: invalid code examples."' . PHP_EOL .
181181
'Code block content: "function sniffValidationWillPass() {}"' . PHP_EOL . PHP_EOL,
182182
'expectedReturnValue' => false,
183183
],
184-
'Code example with syntax error' => [
184+
'Code example with syntax error' => [
185185
'xmlPath' => 'Tests/Fixtures/DocCodeExamples/CheckCodeExamplesStandard/Docs/Examples/SyntaxErrorExampleStandard.xml',
186186
'expectedErrorMessage' => 'Errors found while processing Tests/Fixtures/DocCodeExamples/CheckCodeExamplesStandard/Docs/Examples/SyntaxErrorExampleStandard.xml' . PHP_EOL . PHP_EOL .
187187
'ERROR: There is a syntax error in the code block.' . PHP_EOL .
@@ -194,6 +194,11 @@ public static function dataValidate()
194194
'Code block content: "sniffValidationWillFail() // Syntax error: missing semicolon."' . PHP_EOL . PHP_EOL,
195195
'expectedReturnValue' => false,
196196
],
197+
'Code example from a sniff that uses PHPCSUtils caching' => [
198+
'xmlPath' => 'Tests/Fixtures/DocCodeExamples/CheckCodeExamplesStandard/Docs/Examples/PhpcsUtilsCacheStandard.xml',
199+
'expectedErrorMessage' => '',
200+
'expectedReturnValue' => true,
201+
],
197202
];
198203
}
199204
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<documentation title="PHPCSUtils Cache Sniff">
2+
<standard>
3+
<![CDATA[
4+
Documentation containing valid and invalid code examples that are correct. Uses a sniff that
5+
relies on PHPCSUtils caching. Ensures that the script correctly calls PHPCS programatically by
6+
using different filenames for each instance of DummyFile, so that the cache is not shared
7+
between different code examples causing incorrect results.
8+
9+
If DummyFile is not called with different filenames, PHPCSUtils cache will be shared for the two
10+
code examples below, causing the second code example to be incorrectly marked as valid and
11+
causing the test to fail.
12+
]]>
13+
</standard>
14+
<code_comparison>
15+
<code title="Valid: valid code example.">
16+
<![CDATA[
17+
function sniffValidationWill($pass) {}
18+
]]>
19+
</code>
20+
<code title="Invalid: invalid code example.">
21+
<![CDATA[
22+
function sniffValidationWill($fail) {}
23+
]]>
24+
</code>
25+
</code_comparison>
26+
</documentation>

Tests/Fixtures/DocCodeExamples/CheckCodeExamplesStandard/Sniffs/Examples/BaseExamplesSniff.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public function register()
2222
public function process(File $phpcsFile, $stackPtr)
2323
{
2424
if ($phpcsFile->getTokens()[$stackPtr]['content'] === 'sniffValidationWillFail') {
25-
$phpcsFile->addError('This is a test error', $stackPtr, 'TestError');
25+
$phpcsFile->addError('This is a error', $stackPtr, 'Error');
2626
}
2727
}
2828
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
/**
4+
* Test fixture.
5+
*
6+
* @see \PHPCSDevTools\Tests\DocCodeExamples\XmlDocValidatorTest
7+
*/
8+
9+
namespace Fixtures\DocCodeExamples\CheckCodeExamplesStandard\Sniffs\Examples;
10+
11+
use PHP_CodeSniffer\Files\File;
12+
use PHP_CodeSniffer\Sniffs\Sniff;
13+
use PHPCSUtils\Utils\PassedParameters;
14+
15+
class PhpcsUtilsCacheSniff implements Sniff {
16+
public function register()
17+
{
18+
return [T_STRING];
19+
}
20+
21+
public function process(File $phpcsFile, $stackPtr)
22+
{
23+
$parameter = PassedParameters::getParameter($phpcsFile, $stackPtr, 1);
24+
if ($parameter['clean'] === '$fail') {
25+
$phpcsFile->addError('This is a error', $stackPtr, 'TestError');
26+
}
27+
}
28+
29+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<documentation title="Array Indent">
2+
<standard>
3+
<![CDATA[
4+
The opening square bracket/parenthesis of a multi-line array must be indented at least to the same level of the start of the statement.
5+
]]>
6+
</standard>
7+
<code_comparison>
8+
<code title="Valid: Example of a valid code block.">
9+
<![CDATA[
10+
// Some PHP code.
11+
]]>
12+
</code>
13+
</code_comparison>
14+
</documentation>

0 commit comments

Comments
 (0)