Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 78 additions & 50 deletions src/PHPCodeCoverageVerifier/UnifiedDiffParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,72 +7,89 @@ class UnifiedDiffParser
private $log = false;

private $token_to_method = array(
'Index' => 'parse_index',
'index' => 'parse_index',
'diff' => 'parse_diff',
'deleted' => 'parse_deleted',
'old' => 'parse_old',
'new' => 'parse_new',
'===' => 'parse_separator',
'---' => 'parse_source',
'+++' => 'parse_destination',
'@@' => 'parse_range',
' ' => 'parse_unchanged',
'+' => 'parse_added',
'-' => 'parse_removed',
'\\' => 'parse_comment',
'Binary' => 'parse_binary',
'Index' => 'parse_index',
'index' => 'parse_index',
'diff' => 'parse_diff',
'deleted' => 'parse_deleted',
'new' => 'parse_new',
'===' => 'parse_separator',
'---' => 'parse_source',
'+++' => 'parse_destination',
'@@' => 'parse_range',
' ' => 'parse_unchanged',
'+' => 'parse_added',
'-' => 'parse_removed',
'\\' => 'parse_comment',
'Binary' => 'parse_binary',
'similarity index 100%' => 'parse_similarity',
'rename' => 'parse_rename',
);

private $contextual_line_count = 0;
private $added_line_count = 0;
private $removed_line_count = 0;
private $new_file = false;
private $added_line_count = 0;
private $removed_line_count = 0;
private $new_file = false;

private $current_file = null;
private $current_file = null;
private $extracted_data = array();

public function parse($string)
{
$lines = explode("\n", $string);
foreach ($lines as $line_number => $line) {
foreach($lines as $line_number => $line)
{
$line = trim($line, "\r");

// Generally only for EOF
if ($line === '') {
if($line === '')
{
continue;
}

$found = false;
foreach ($this->token_to_method as $token => $method) {
if ($this->startsWith($line, $token)) {
foreach($this->token_to_method as $token => $method)
{
if($this->startsWith($line, $token))
{
$this->$method($line);
$found = true;
break;
}
}

if (!$found) {
throw new \Exception('Could not find parser for line #'.($line_number+1).', text "'.$line.'"');
if(!$found)
{
throw new \Exception('Could not find parser for line #' . ($line_number + 1) . ', text "' . $line . '"');
}
}
}

private function parse_index($line)
{
$this->log('contextual: '.$this->contextual_line_count.', added: '.$this->added_line_count.', removed: '.$this->removed_line_count);
$this->log('contextual: ' . $this->contextual_line_count . ', added: ' . $this->added_line_count . ', removed: ' .
$this->removed_line_count);
$this->contextual_line_count = 0;
$this->added_line_count = 0;
$this->removed_line_count = 0;
$this->new_file = false;
$this->log('index '.$line);
$this->log('index ' . $line);
}

private function parse_similarity($line)
{
// do nothing because the files match
}

private function parse_deleted($line)
{
$this->log('deleted', $line);
}

private function parse_rename($line)
{
$this->log('rename', $line);
}

private function parse_new($line)
{
$this->log('new', $line);
Expand All @@ -90,107 +107,116 @@ private function parse_diff($line)

private function parse_separator($line)
{
$this->log('separator '.$line);
$this->log('separator ' . $line);
}

private function parse_source($line)
{
if ($line === '--- /dev/null')
if($line === '--- /dev/null')
{
$this->new_file = true;
return;
}

preg_match('/\-\-\- (\S+)/', $line, $matches);

if (count($matches) === 0) return;

if(count($matches) === 0)
{
return;
}

array_shift($matches);

//git has a prefix of a/ in this line
if ($this->startsWith($matches[0], 'a/'))
if($this->startsWith($matches[0], 'a/'))
{
$matches[0] = substr($matches[0], strlen('a/'));
}

$this->extracted_data[$matches[0]] = array();
$this->current_file = &$this->extracted_data[$matches[0]];

$this->log('source('.$matches[0].') '.$line);
$this->log('source(' . $matches[0] . ') ' . $line);
}

private function parse_destination($line)
{
preg_match('/\+\+\+ (\S+)/', $line, $matches);

if (count($matches) === 0) return;
if(count($matches) === 0)
{
return;
}
array_shift($matches);

//git has a prefix of b/ in this line
if ($this->startsWith($matches[0], 'b/'))
if($this->startsWith($matches[0], 'b/'))
{
$matches[0] = substr($matches[0], strlen('b/'));
}

if ($this->new_file)
if($this->new_file)
{
$this->extracted_data[$matches[0]] = array();
$this->current_file = &$this->extracted_data[$matches[0]];
}

$this->log('destination('.$matches[0].') '.$line);
$this->log('destination(' . $matches[0] . ') ' . $line);
}

private function parse_range($line)
{
preg_match('/@@ \-(\d+),(\d+) \+(\d+),(\d+) @@/', $line, $matches);

if (count($matches) === 0) return;
if(count($matches) === 0)
{
return;
}

array_shift($matches);

$this->current_file['line'][] = array(
'range' => array(
'source' => array(
'source' => array(
'line_start' => $matches[0],
'line_count' => $matches[1]
),
'destination' => array(
'destination' => array(
'line_start' => $matches[2],
'line_count' => $matches[3]
),
),
);

$this->log('range('.$matches[0].', '.$matches[1].', '.$matches[2].', '.$matches[3].') '.$line);
$this->log('range(' . $matches[0] . ', ' . $matches[1] . ', ' . $matches[2] . ', ' . $matches[3] . ') ' . $line);
}

private function parse_unchanged($line)
{
++$this->contextual_line_count;
$this->log('unchanged '.$line);
$this->log('unchanged ' . $line);
}

private function parse_added($line)
{
++$this->added_line_count;
$this->log('added '.$line);
$this->log('added ' . $line);
}

private function parse_removed($line)
{
++$this->removed_line_count;
$this->log('removed '.$line);
$this->log('removed ' . $line);
}

private function parse_comment($line)
{
$this->log('comment '.$line);
$this->log('comment ' . $line);
}

private function parse_binary($line)
{
$this->log('binary '.$line);
$this->log('binary ' . $line);
}

public function get_extracted_data()
Expand All @@ -208,9 +234,11 @@ public function setLogging($value)
$this->log = $value;
}

private function log($text, $eol = true) {
if ($this->log) {
echo $text.($eol ? PHP_EOL : '');
private function log($text, $eol = true)
{
if($this->log)
{
echo $text . ($eol ? PHP_EOL : '');
}
}
}
7 changes: 6 additions & 1 deletion tests/fixtures/diff.diff
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@ Index: application/classes/controller/a_nice_file.php
-
/**
* Something else
*
*

diff --git a/htdocs/js/Zeus/qa/DEV.png b/htdocs/js/Zeus/qa/dev.png
similarity index 100%
rename from htdocs/js/Zeus/qa/DEV.png
rename to htdocs/js/Zeus/qa/dev.png