Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace SebastianBergmann\Diff; Chris@0: Chris@0: /** Chris@0: * Unified diff parser. Chris@0: */ Chris@0: class Parser Chris@0: { Chris@0: /** Chris@0: * @param string $string Chris@0: * Chris@0: * @return Diff[] Chris@0: */ Chris@0: public function parse($string) Chris@0: { Chris@0: $lines = preg_split('(\r\n|\r|\n)', $string); Chris@0: $lineCount = count($lines); Chris@0: $diffs = array(); Chris@0: $diff = null; Chris@0: $collected = array(); Chris@0: Chris@0: for ($i = 0; $i < $lineCount; ++$i) { Chris@0: if (preg_match('(^---\\s+(?P\\S+))', $lines[$i], $fromMatch) && Chris@0: preg_match('(^\\+\\+\\+\\s+(?P\\S+))', $lines[$i + 1], $toMatch)) { Chris@0: if ($diff !== null) { Chris@0: $this->parseFileDiff($diff, $collected); Chris@0: $diffs[] = $diff; Chris@0: $collected = array(); Chris@0: } Chris@0: Chris@0: $diff = new Diff($fromMatch['file'], $toMatch['file']); Chris@0: ++$i; Chris@0: } else { Chris@0: if (preg_match('/^(?:diff --git |index [\da-f\.]+|[+-]{3} [ab])/', $lines[$i])) { Chris@0: continue; Chris@0: } Chris@0: $collected[] = $lines[$i]; Chris@0: } Chris@0: } Chris@0: Chris@0: if (count($collected) && ($diff !== null)) { Chris@0: $this->parseFileDiff($diff, $collected); Chris@0: $diffs[] = $diff; Chris@0: } Chris@0: Chris@0: return $diffs; Chris@0: } Chris@0: Chris@0: /** Chris@0: * @param Diff $diff Chris@0: * @param array $lines Chris@0: */ Chris@0: private function parseFileDiff(Diff $diff, array $lines) Chris@0: { Chris@0: $chunks = array(); Chris@0: Chris@0: foreach ($lines as $line) { Chris@0: if (preg_match('/^@@\s+-(?P\d+)(?:,\s*(?P\d+))?\s+\+(?P\d+)(?:,\s*(?P\d+))?\s+@@/', $line, $match)) { Chris@0: $chunk = new Chunk( Chris@0: $match['start'], Chris@0: isset($match['startrange']) ? max(1, $match['startrange']) : 1, Chris@0: $match['end'], Chris@0: isset($match['endrange']) ? max(1, $match['endrange']) : 1 Chris@0: ); Chris@0: Chris@0: $chunks[] = $chunk; Chris@0: $diffLines = array(); Chris@0: continue; Chris@0: } Chris@0: Chris@0: if (preg_match('/^(?P[+ -])?(?P.*)/', $line, $match)) { Chris@0: $type = Line::UNCHANGED; Chris@0: Chris@0: if ($match['type'] == '+') { Chris@0: $type = Line::ADDED; Chris@0: } elseif ($match['type'] == '-') { Chris@0: $type = Line::REMOVED; Chris@0: } Chris@0: Chris@0: $diffLines[] = new Line($type, $match['line']); Chris@0: Chris@0: if (isset($chunk)) { Chris@0: $chunk->setLines($diffLines); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: $diff->setChunks($chunks); Chris@0: } Chris@0: }