Skip to content

Commit c249614

Browse files
SpacePossumsebastianbergmann
authored andcommitted
Show diff lines if line endings differ.
1 parent 3c40ca4 commit c249614

File tree

4 files changed

+127
-22
lines changed

4 files changed

+127
-22
lines changed

src/Differ.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public function diffToArray($from, $to, LongestCommonSubsequenceCalculator $lcs
110110

111111
if ($this->detectUnmatchedLineEndings($fromMatches, $toMatches)) {
112112
$diff[] = [
113-
'#Warning: Strings contain different line endings!',
113+
"#Warning: Strings contain different line endings!\n",
114114
3
115115
];
116116
}
@@ -175,7 +175,7 @@ private function getNewLineMatches(string $string): array
175175
*/
176176
private function splitStringByLines(string $input): array
177177
{
178-
return \preg_split('(\r\n|\r|\n)', $input);
178+
return \preg_split('/(.*\R)/', $input, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
179179
}
180180

181181
/**

src/Output/DiffOnlyOutputBuilder.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,21 @@ public function getDiff(array $diff): string
3838

3939
foreach ($diff as $diffEntry) {
4040
if ($diffEntry[1] === 1 /* ADDED */) {
41-
\fwrite($buffer, '+' . $diffEntry[0] . "\n");
41+
\fwrite($buffer, '+' . $diffEntry[0]);
4242
} elseif ($diffEntry[1] === 2 /* REMOVED */) {
43-
\fwrite($buffer, '-' . $diffEntry[0] . "\n");
43+
\fwrite($buffer, '-' . $diffEntry[0]);
4444
} elseif ($diffEntry[1] === 3 /* WARNING */) {
45-
\fwrite($buffer, ' ' . $diffEntry[0] . "\n");
46-
} // else { /* Not changed (old) 0 */
45+
\fwrite($buffer, ' ' . $diffEntry[0]);
46+
47+
continue; // Warnings should not be tested for line break, it will always be there
48+
} else { /* Not changed (old) 0 */
49+
continue; // we didn't write the non changs line, so do not add a line break either
50+
}
51+
52+
$lc = \substr($diffEntry[0], -1);
53+
if ($lc !== "\n" && $lc !== "\r") {
54+
\fwrite($buffer, "\n"); // \No newline at end of file
55+
}
4756
}
4857

4958
$diff = \stream_get_contents($buffer, -1, 0);

src/Output/UnifiedDiffOutputBuilder.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,20 @@ private function writeDiffBufferElementNew(array $diff, $buffer, int $diffIndex)
100100
private function writeDiffBufferElement(array $diff, $buffer, int $diffIndex)
101101
{
102102
if ($diff[$diffIndex][1] === 1 /* ADDED */) {
103-
\fwrite($buffer, '+' . $diff[$diffIndex][0] . "\n");
103+
\fwrite($buffer, '+' . $diff[$diffIndex][0]);
104104
} elseif ($diff[$diffIndex][1] === 2 /* REMOVED */) {
105-
\fwrite($buffer, '-' . $diff[$diffIndex][0] . "\n");
106-
} else { /* Not changed (OLD) 0 or Warning 3 */
107-
\fwrite($buffer, ' ' . $diff[$diffIndex][0] . "\n");
105+
\fwrite($buffer, '-' . $diff[$diffIndex][0]);
106+
} elseif ($diff[$diffIndex][1] === 3 /* WARNING */) {
107+
\fwrite($buffer, ' ' . $diff[$diffIndex][0]);
108+
109+
return; // Warnings should not be tested for line break, it will always be there
110+
} else { /* OLD Not changed (0) */
111+
\fwrite($buffer, ' ' . $diff[$diffIndex][0]);
112+
}
113+
114+
$lc = \substr($diff[$diffIndex][0], -1);
115+
if ($lc !== "\n" && $lc !== "\r") {
116+
\fwrite($buffer, "\n"); // \No newline at end of file
108117
}
109118
}
110119
}

tests/DifferTest.php

Lines changed: 99 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -282,20 +282,20 @@ public function arrayProvider(): array
282282
'test line diff detection' => [
283283
[
284284
[
285-
'#Warning: Strings contain different line endings!',
285+
"#Warning: Strings contain different line endings!\n",
286286
self::WARNING,
287287
],
288288
[
289-
'<?php',
290-
self::OLD,
289+
"<?php\r\n",
290+
self::REMOVED,
291291
],
292292
[
293-
'',
294-
self::OLD,
293+
"<?php\n",
294+
self::ADDED,
295295
],
296296
],
297297
"<?php\r\n",
298-
"<?php\n"
298+
"<?php\n",
299299
]
300300
];
301301
}
@@ -380,6 +380,11 @@ public function textProvider(): array
380380
"A\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1",
381381
"B\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1",
382382
],
383+
[
384+
"--- Original\n+++ New\n@@ @@\n #Warning: Strings contain different line endings!\n-<?php\r\n+<?php\n A\n",
385+
"<?php\r\nA\n",
386+
"<?php\nA\n",
387+
],
383388
];
384389
}
385390

@@ -415,13 +420,15 @@ public function textForNoNonDiffLinesProvider(): array
415420
{
416421
return [
417422
[
418-
' #Warning: Strings contain different line endings!
419-
-A
420-
+B
421-
',
423+
" #Warning: Strings contain different line endings!\n-A\r\n+B\n",
422424
"A\r\n",
423425
"B\n",
424426
],
427+
[
428+
"-A\n+B\n",
429+
"\nA",
430+
"\nB"
431+
],
425432
[
426433
'',
427434
'a',
@@ -545,12 +552,12 @@ public function provideGetCommonChunks(): array
545552
"B\n\n\n\n\n\n\nX\nA\nZ\n\n",
546553
],
547554
'same trailing' => [
548-
[2 => 15],
555+
[2 => 14],
549556
"A\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
550557
"B\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
551558
],
552559
'same part in between, same trailing' => [
553-
[2 => 7, 10 => 16],
560+
[2 => 7, 10 => 15],
554561
"A\n\n\n\n\n\n\nA\n\n\n\n\n\n\n",
555562
"B\n\n\n\n\n\n\nB\n\n\n\n\n\n\n",
556563
],
@@ -589,4 +596,84 @@ public function provideGetCommonChunks(): array
589596
],
590597
];
591598
}
599+
600+
/**
601+
* @param array $expected
602+
* @param string $input
603+
* @dataProvider provideSplitStringByLinesCases
604+
*/
605+
public function testSplitStringByLines(array $expected, string $input)
606+
{
607+
$reflection = new \ReflectionObject($this->differ);
608+
$method = $reflection->getMethod('splitStringByLines');
609+
$method->setAccessible(true);
610+
611+
$this->assertSame($expected, $method->invoke($this->differ, $input));
612+
}
613+
614+
public function provideSplitStringByLinesCases()
615+
{
616+
return [
617+
[
618+
[],
619+
''
620+
],
621+
[
622+
['a'],
623+
'a'
624+
],
625+
[
626+
["a\n"],
627+
"a\n"
628+
],
629+
[
630+
["a\r"],
631+
"a\r"
632+
],
633+
[
634+
["a\r\n"],
635+
"a\r\n"
636+
],
637+
[
638+
["\n"],
639+
"\n"
640+
],
641+
[
642+
["\r"],
643+
"\r"
644+
],
645+
[
646+
["\r\n"],
647+
"\r\n"
648+
],
649+
[
650+
[
651+
"A\n",
652+
"B\n",
653+
"\n",
654+
"C\n"
655+
],
656+
"A\nB\n\nC\n",
657+
],
658+
[
659+
[
660+
"A\r\n",
661+
"B\n",
662+
"\n",
663+
"C\r"
664+
],
665+
"A\r\nB\n\nC\r",
666+
],
667+
[
668+
[
669+
"\n",
670+
"A\r\n",
671+
"B\n",
672+
"\n",
673+
'C'
674+
],
675+
"\nA\r\nB\n\nC",
676+
],
677+
];
678+
}
592679
}

0 commit comments

Comments
 (0)