Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php declare(strict_types=1);
2
/*
3
 * This file is part of sebastian/diff.
4
 *
5
 * (c) Sebastian Bergmann <sebastian@phpunit.de>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace SebastianBergmann\Diff;
11
 
12
use function array_pop;
13
use function count;
14
use function max;
15
use function preg_match;
16
use function preg_split;
17
 
18
/**
19
 * Unified diff parser.
20
 */
21
final class Parser
22
{
23
    /**
24
     * @return Diff[]
25
     */
26
    public function parse(string $string): array
27
    {
28
        $lines = preg_split('(\r\n|\r|\n)', $string);
29
 
30
        if (!empty($lines) && $lines[count($lines) - 1] === '') {
31
            array_pop($lines);
32
        }
33
 
34
        $lineCount = count($lines);
35
        $diffs     = [];
36
        $diff      = null;
37
        $collected = [];
38
 
39
        for ($i = 0; $i < $lineCount; ++$i) {
40
            if (preg_match('#^---\h+"?(?P<file>[^\\v\\t"]+)#', $lines[$i], $fromMatch) &&
41
                preg_match('#^\\+\\+\\+\\h+"?(?P<file>[^\\v\\t"]+)#', $lines[$i + 1], $toMatch)) {
42
                if ($diff !== null) {
43
                    $this->parseFileDiff($diff, $collected);
44
 
45
                    $diffs[]   = $diff;
46
                    $collected = [];
47
                }
48
 
49
                $diff = new Diff($fromMatch['file'], $toMatch['file']);
50
 
51
                ++$i;
52
            } else {
53
                if (preg_match('/^(?:diff --git |index [\da-f\.]+|[+-]{3} [ab])/', $lines[$i])) {
54
                    continue;
55
                }
56
 
57
                $collected[] = $lines[$i];
58
            }
59
        }
60
 
61
        if ($diff !== null && count($collected)) {
62
            $this->parseFileDiff($diff, $collected);
63
 
64
            $diffs[] = $diff;
65
        }
66
 
67
        return $diffs;
68
    }
69
 
70
    private function parseFileDiff(Diff $diff, array $lines): void
71
    {
72
        $chunks    = [];
73
        $chunk     = null;
74
        $diffLines = [];
75
 
76
        foreach ($lines as $line) {
77
            if (preg_match('/^@@\s+-(?P<start>\d+)(?:,\s*(?P<startrange>\d+))?\s+\+(?P<end>\d+)(?:,\s*(?P<endrange>\d+))?\s+@@/', $line, $match)) {
78
                $chunk = new Chunk(
79
                    (int) $match['start'],
80
                    isset($match['startrange']) ? max(1, (int) $match['startrange']) : 1,
81
                    (int) $match['end'],
82
                    isset($match['endrange']) ? max(1, (int) $match['endrange']) : 1
83
                );
84
 
85
                $chunks[]  = $chunk;
86
                $diffLines = [];
87
 
88
                continue;
89
            }
90
 
91
            if (preg_match('/^(?P<type>[+ -])?(?P<line>.*)/', $line, $match)) {
92
                $type = Line::UNCHANGED;
93
 
94
                if ($match['type'] === '+') {
95
                    $type = Line::ADDED;
96
                } elseif ($match['type'] === '-') {
97
                    $type = Line::REMOVED;
98
                }
99
 
100
                $diffLines[] = new Line($type, $match['line']);
101
 
102
                if (null !== $chunk) {
103
                    $chunk->setLines($diffLines);
104
                }
105
            }
106
        }
107
 
108
        $diff->setChunks($chunks);
109
    }
110
}