diff --git a/src/Psalm/ErrorBaseline.php b/src/Psalm/ErrorBaseline.php index 9ab0cbfc7d6..e56a65527e6 100644 --- a/src/Psalm/ErrorBaseline.php +++ b/src/Psalm/ErrorBaseline.php @@ -19,6 +19,7 @@ use function preg_replace_callback; use function str_replace; use function strpos; +use function trim; use function usort; use const LIBXML_NOBLANKS; @@ -115,7 +116,7 @@ public static function read(FileProvider $fileProvider, string $baselineFile): a $codeSamples = $issue->getElementsByTagName('code'); foreach ($codeSamples as $codeSample) { - $files[$fileName][$issueType]['s'][] = $codeSample->textContent; + $files[$fileName][$issueType]['s'][] = trim($codeSample->textContent); } } } @@ -273,6 +274,10 @@ function (string $extension) : string { foreach ($existingIssueType['s'] as $selection) { $codeNode = $baselineDoc->createElement('code'); + /** @todo in major version release (e.g. Psalm 5) replace $selection with trim($selection) + * This will be a minor BC break as baselines generated will then not be compatible with Psalm + * versions from before PR https://github.com/vimeo/psalm/pull/6000 + */ $codeNode->textContent = $selection; $issueNode->appendChild($codeNode); } diff --git a/src/Psalm/IssueBuffer.php b/src/Psalm/IssueBuffer.php index bc5492b2780..f9954a9cf6e 100644 --- a/src/Psalm/IssueBuffer.php +++ b/src/Psalm/IssueBuffer.php @@ -48,6 +48,7 @@ use function sprintf; use function str_repeat; use function str_replace; +use function trim; use function usort; use const DEBUG_BACKTRACE_IGNORE_ARGS; @@ -518,7 +519,7 @@ function (IssueData $d1, IssueData $d2) : int { if (isset($issue_baseline[$file][$type]) && $issue_baseline[$file][$type]['o'] > 0) { if ($issue_baseline[$file][$type]['o'] === count($issue_baseline[$file][$type]['s'])) { $position = array_search( - $issue_data->selected_text, + trim($issue_data->selected_text), $issue_baseline[$file][$type]['s'], true ); diff --git a/tests/ErrorBaselineTest.php b/tests/ErrorBaselineTest.php index 92e846f2a1f..56be18758f3 100644 --- a/tests/ErrorBaselineTest.php +++ b/tests/ErrorBaselineTest.php @@ -67,6 +67,34 @@ public function testLoadShouldParseXmlBaselineToPhpArray() ); } + public function testLoadShouldIgnoreLineEndingsInIssueSnippet(): void + { + $baselineFilePath = 'baseline.xml'; + + $this->fileProvider->fileExists($baselineFilePath)->willReturn(true); + $this->fileProvider->getContents($baselineFilePath)->willReturn( + " + + + + foo\r + + + " + ); + + $expectedParsedBaseline = [ + 'sample/sample-file.php' => [ + 'MixedAssignment' => ['o' => 1, 's' => ['foo']], + ], + ]; + + $this->assertSame( + $expectedParsedBaseline, + ErrorBaseline::read($this->fileProvider->reveal(), $baselineFilePath) + ); + } + /** * @return void */ diff --git a/tests/IssueBufferTest.php b/tests/IssueBufferTest.php index d350906e295..d12ef833484 100644 --- a/tests/IssueBufferTest.php +++ b/tests/IssueBufferTest.php @@ -54,11 +54,31 @@ public function testFinishDoesNotCorruptInternalState(): void 0, 0 ) - ] + ], + '/path/three.php' => [ + new \Psalm\Internal\Analyzer\IssueData( + "error", + 0, + 0, + "MissingPropertyType", + 'Message', + "three.php", + "/path/three.php", + "snippet-3-has-carriage-return\r", + "snippet-3-has-carriage-return\r", + 0, + 0, + 0, + 0, + 0, + 0 + ) + ], ]); $baseline = [ 'one.php' => ['MissingPropertyType' => ['o' => 1, 's' => ['snippet-1']] ], 'two.php' => ['MissingPropertyType' => ['o' => 1, 's' => ['snippet-2']] ], + 'three.php' => ['MissingPropertyType' => ['o' => 1, 's' => ['snippet-3-has-carriage-return']] ], ]; $analyzer = $this->createMock(Analyzer::class);