diff --git a/src/Core/LCS.php b/src/Core/LCS.php index 684a1fe..408bd78 100644 --- a/src/Core/LCS.php +++ b/src/Core/LCS.php @@ -313,7 +313,7 @@ private function findMostProgress(int $M, int $N, int $limit, array $V): array $backwardEndDiag = \min($M, $limit); - $maxProgress = array_fill( + $maxProgress = \array_fill( 0, (int) (\max($forwardEndDiag - $forwardStartDiag, $backwardEndDiag - $backwardStartDiag) / 2 + 1), [0, 0, 0]); diff --git a/src/DifferencesIterator.php b/src/DifferencesIterator.php index 3f809ef..584be71 100644 --- a/src/DifferencesIterator.php +++ b/src/DifferencesIterator.php @@ -17,7 +17,7 @@ */ class DifferencesIterator { - /** @var RangeDifference[]|null[] */ + /** @var RangeDifference[] */ private $fRange = []; /** @var int */ @@ -58,7 +58,7 @@ public function getCount(): int /** * @return RangeDifference[] */ - public function getRange(): iterable + public function getRange(): array { return $this->fRange; } diff --git a/src/RangeDifferencer.php b/src/RangeDifferencer.php index 1e14d99..8a4bfa5 100644 --- a/src/RangeDifferencer.php +++ b/src/RangeDifferencer.php @@ -28,6 +28,8 @@ final class RangeDifferencer { /** * Prevent class instantiation. + * + * @codeCoverageIgnore */ private function __construct() { @@ -56,96 +58,96 @@ public static function findDifferences(RangeComparatorInterface $left, RangeComp * @param RangeComparatorInterface $right * @return RangeDifference[] */ - public static function findDifferences3( - RangeComparatorInterface $ancestor, - RangeComparatorInterface $left, - RangeComparatorInterface $right - ): array { - $leftAncestorScript = []; - $rightAncestorScript = static::findDifferences($ancestor, $right); - - if (!empty($rightAncestorScript)) { - $leftAncestorScript = static::findDifferences($ancestor, $left); - } - - if (empty($rightAncestorScript) || empty($leftAncestorScript)) { - return []; - } - - $myIter = new DifferencesIterator($rightAncestorScript); - $yourIter = new DifferencesIterator($leftAncestorScript); - - // Add a sentinel. - $diff3 = []; - $diff3[] = new RangeDifference(RangeDifference::ERROR); - - // Combine the two two-way edit scripts into one. - while (null !== $myIter->getDifference() || null !== $yourIter->getDifference()) { - $myIter->removeAll(); - $yourIter->removeAll(); - - if (null === $myIter->getDifference()) { - $startThread = $yourIter; - } elseif (null === $yourIter->getDifference()) { - $startThread = $myIter; - } else { - // Not at end of both scripts take the lowest range. - if ($myIter->getDifference()->getLeftStart() < $yourIter->getDifference()->getLeftStart()) { - // 2 -> common (Ancestor) - $startThread = $myIter; - } elseif ($myIter->getDifference()->getLeftStart() > $yourIter->getDifference()->getLeftStart()) { - $startThread = $yourIter; - } else { - if ($myIter->getDifference()->getLeftLength() === 0 && - $yourIter->getDifference()->getLeftLength() === 0) { - // Insertion into the same position is conflict. - $changeRangeStart = $myIter->getDifference()->getLeftStart(); - $changeRangeEnd = $myIter->getDifference()->getLeftEnd(); - - $myIter->next(); - $yourIter->next(); - - $diff3[] = static::createRangeDifference3( - $myIter, $yourIter, $diff3, $right, $left, $changeRangeStart, $changeRangeEnd); - continue; - } elseif (0 === $myIter->getDifference()->getLeftLength()) { - // Insertion into a position, and modification to the next line, is not conflict. - $startThread = $myIter; - } elseif (0 === $yourIter->getDifference()->getLeftLength()) { - $startThread = $yourIter; - } else { - // Modifications to overlapping lines is conflict. - $startThread = $myIter; - } - } - } - - $changeRangeStart = $startThread->getDifference()->getLeftStart(); - $changeRangeEnd = $startThread->getDifference()->getLeftEnd(); - $startThread->next(); - - // Check for overlapping changes with other thread. Merge overlapping changes with this range. - $other = $startThread->other($myIter, $yourIter); - - while (null !== $other->getDifference() && $other->getDifference()->getLeftStart() < $changeRangeEnd) { - $newMax = $other->getDifference()->getLeftEnd(); - $other->next(); - - if ($newMax > $changeRangeEnd) { - $changeRangeEnd = $newMax; - $other = $other->other($myIter, $yourIter); - } - } - - $diff3[] = static::createRangeDifference3( - $myIter, $yourIter, $diff3, $right, $left, $changeRangeStart, $changeRangeEnd); - } - - // Remove sentinel. - array_shift($diff3); - - return $diff3; - } +// public static function findDifferences3( +// RangeComparatorInterface $ancestor, +// RangeComparatorInterface $left, +// RangeComparatorInterface $right +// ): array { +// $leftAncestorScript = []; +// $rightAncestorScript = static::findDifferences($ancestor, $right); +// +// if (!empty($rightAncestorScript)) { +// $leftAncestorScript = static::findDifferences($ancestor, $left); +// } +// +// if (empty($rightAncestorScript) || empty($leftAncestorScript)) { +// return []; +// } +// +// $myIter = new DifferencesIterator($rightAncestorScript); +// $yourIter = new DifferencesIterator($leftAncestorScript); +// +// // Add a sentinel. +// $diff3 = []; +// $diff3[] = new RangeDifference(RangeDifference::ERROR); +// +// // Combine the two two-way edit scripts into one. +// while (null !== $myIter->getDifference() || null !== $yourIter->getDifference()) { +// $myIter->removeAll(); +// $yourIter->removeAll(); +// +// if (null === $myIter->getDifference()) { +// $startThread = $yourIter; +// } elseif (null === $yourIter->getDifference()) { +// $startThread = $myIter; +// } else { +// // Not at end of both scripts take the lowest range. +// if ($myIter->getDifference()->getLeftStart() < $yourIter->getDifference()->getLeftStart()) { +// // 2 -> common (Ancestor) +// $startThread = $myIter; +// } elseif ($myIter->getDifference()->getLeftStart() > $yourIter->getDifference()->getLeftStart()) { +// $startThread = $yourIter; +// } else { +// if ($myIter->getDifference()->getLeftLength() === 0 && +// $yourIter->getDifference()->getLeftLength() === 0) { +// // Insertion into the same position is conflict. +// $changeRangeStart = $myIter->getDifference()->getLeftStart(); +// $changeRangeEnd = $myIter->getDifference()->getLeftEnd(); +// +// $myIter->next(); +// $yourIter->next(); +// +// $diff3[] = static::createRangeDifference3( +// $myIter, $yourIter, $diff3, $right, $left, $changeRangeStart, $changeRangeEnd); +// continue; +// } elseif (0 === $myIter->getDifference()->getLeftLength()) { +// // Insertion into a position, and modification to the next line, is not conflict. +// $startThread = $myIter; +// } elseif (0 === $yourIter->getDifference()->getLeftLength()) { +// $startThread = $yourIter; +// } else { +// // Modifications to overlapping lines is conflict. +// $startThread = $myIter; +// } +// } +// } +// +// $changeRangeStart = $startThread->getDifference()->getLeftStart(); +// $changeRangeEnd = $startThread->getDifference()->getLeftEnd(); +// $startThread->next(); +// +// // Check for overlapping changes with other thread. Merge overlapping changes with this range. +// $other = $startThread->other($myIter, $yourIter); +// +// while (null !== $other->getDifference() && $other->getDifference()->getLeftStart() < $changeRangeEnd) { +// $newMax = $other->getDifference()->getLeftEnd(); +// $other->next(); +// +// if ($newMax > $changeRangeEnd) { +// $changeRangeEnd = $newMax; +// $other = $other->other($myIter, $yourIter); +// } +// } +// +// $diff3[] = static::createRangeDifference3( +// $myIter, $yourIter, $diff3, $right, $left, $changeRangeStart, $changeRangeEnd); +// } +// +// // Remove sentinel. +// \array_shift($diff3); +// +// return $diff3; +// } /** * Finds the differences among two RangeComparatorInterfaces. In contrast to findDifferences, the result contains @@ -155,41 +157,41 @@ public static function findDifferences3( * @param RangeComparatorInterface $right * @return RangeDifference[] */ - public static function findRanges(RangeComparatorInterface $left, RangeComparatorInterface $right): array - { - $in = static::findDifferences($left, $right); - $out = []; - - $mStart = 0; - $yStart = 0; - - for ($i = 0, $iMax = \count($in); $i < $iMax; $i++) { - $es = $in[$i]; - $rd = new RangeDifference( - RangeDifference::NOCHANGE, - $mStart, $es->getRightStart() - $mStart, - $yStart, $es->getLeftStart() - $yStart); - - if (0 !== $rd->getMaxLength()) { - $out[] = $rd; - } - - $out[] = $es; - - $mStart = $es->getRightEnd(); - $yStart = $es->getLeftEnd(); - } - - $rd = new RangeDifference(RangeDifference::NOCHANGE, - $mStart, $right->getRangeCount() - $mStart, - $yStart, $left->getRangeCount() - $yStart); - - if ($rd->getMaxLength() > 0) { - $out[] = $rd; - } - - return $out; - } +// public static function findRanges(RangeComparatorInterface $left, RangeComparatorInterface $right): array +// { +// $in = static::findDifferences($left, $right); +// $out = []; +// +// $mStart = 0; +// $yStart = 0; +// +// for ($i = 0, $iMax = \count($in); $i < $iMax; $i++) { +// $es = $in[$i]; +// $rd = new RangeDifference( +// RangeDifference::NOCHANGE, +// $mStart, $es->getRightStart() - $mStart, +// $yStart, $es->getLeftStart() - $yStart); +// +// if (0 !== $rd->getMaxLength()) { +// $out[] = $rd; +// } +// +// $out[] = $es; +// +// $mStart = $es->getRightEnd(); +// $yStart = $es->getLeftEnd(); +// } +// +// $rd = new RangeDifference(RangeDifference::NOCHANGE, +// $mStart, $right->getRangeCount() - $mStart, +// $yStart, $left->getRangeCount() - $yStart); +// +// if ($rd->getMaxLength() > 0) { +// $out[] = $rd; +// } +// +// return $out; +// } /** * Finds the differences among three RangeComparatorInterfaces. In contrast to findDifferences, the result contains @@ -201,47 +203,47 @@ public static function findRanges(RangeComparatorInterface $left, RangeComparato * @param RangeComparatorInterface $right * @return RangeDifference[] */ - public static function findRanges3( - RangeComparatorInterface $ancestor, - RangeComparatorInterface $left, - RangeComparatorInterface $right): array - { - $in = static::findDifferences3($ancestor, $left, $right); - $out = []; - - $mStart = 0; - $yStart = 0; - $aStart = 0; - - for ($i = 0, $iMax = \count($in); $i < $iMax; $i++) { - $es = $in[$i]; - $rd = new RangeDifference(RangeDifference::NOCHANGE, - $mStart, $es->getRightStart() - $mStart, - $yStart, $es->getLeftStart() - $yStart, - $aStart, $es->getAncestorStart() - $aStart); - - if ($rd->getMaxLength() > 0) { - $out[] = $rd; - } - - $out[] = $es; - - $mStart = $es->getRightEnd(); - $yStart = $es->getLeftEnd(); - $aStart = $es->getAncestorEnd(); - } - - $rd = new RangeDifference(RangeDifference::NOCHANGE, - $mStart, $right->getRangeCount() - $mStart, - $yStart, $left->getRangeCount() - $yStart, - $aStart, $ancestor->getRangeCount() - $aStart); - - if ($rd->getMaxLength() > 0) { - $out[] = $rd; - } - - return $out; - } +// public static function findRanges3( +// RangeComparatorInterface $ancestor, +// RangeComparatorInterface $left, +// RangeComparatorInterface $right): array +// { +// $in = static::findDifferences3($ancestor, $left, $right); +// $out = []; +// +// $mStart = 0; +// $yStart = 0; +// $aStart = 0; +// +// for ($i = 0, $iMax = \count($in); $i < $iMax; $i++) { +// $es = $in[$i]; +// $rd = new RangeDifference(RangeDifference::NOCHANGE, +// $mStart, $es->getRightStart() - $mStart, +// $yStart, $es->getLeftStart() - $yStart, +// $aStart, $es->getAncestorStart() - $aStart); +// +// if ($rd->getMaxLength() > 0) { +// $out[] = $rd; +// } +// +// $out[] = $es; +// +// $mStart = $es->getRightEnd(); +// $yStart = $es->getLeftEnd(); +// $aStart = $es->getAncestorEnd(); +// } +// +// $rd = new RangeDifference(RangeDifference::NOCHANGE, +// $mStart, $right->getRangeCount() - $mStart, +// $yStart, $left->getRangeCount() - $yStart, +// $aStart, $ancestor->getRangeCount() - $aStart); +// +// if ($rd->getMaxLength() > 0) { +// $out[] = $rd; +// } +// +// return $out; +// } /** * @param DifferencesIterator $myIter @@ -253,66 +255,66 @@ public static function findRanges3( * @param int $changeRangeEnd * @return RangeDifference */ - private static function createRangeDifference3( - DifferencesIterator $myIter, - DifferencesIterator $yourIter, - array &$diff3, - RangeComparatorInterface $right, - RangeComparatorInterface $left, - int $changeRangeStart, - int $changeRangeEnd - ): RangeDifference { - $kind = RangeDifference::ERROR; - /** @var RangeDifference $last */ - $last = $diff3[\count($diff3) - 1]; - - // At least one range array must be non-empty. - assert(true === ($myIter->getCount() !== 0 || $yourIter->getCount() !== 0)); - - // Find corresponding lines to changeRangeStart/End in right and left. - if ($myIter->getCount() === 0) { - // Only left changed. - $rightStart = $changeRangeStart - $last->getAncestorEnd() + $last->getRightEnd(); - $rightEnd = $changeRangeEnd - $last->getAncestorEnd() + $last->getRightEnd(); - $kind = RangeDifference::LEFT; - } else { - $myRange = $myIter->getRange(); - $f = $myRange[0]; - $l = $myRange[\count($myRange) - 1]; - $rightStart = $changeRangeStart - $f->getLeftStart() + $f->getRightStart(); - $rightEnd = $changeRangeEnd - $l->getLeftEnd() + $l->getRightEnd(); - } - - if ($yourIter->getCount() === 0) { - // Only right changed. - $leftStart = $changeRangeStart - $last->getAncestorEnd() + $last->getLeftEnd(); - $leftEnd = $changeRangeEnd - $last->getAncestorEnd() + $last->getLeftEnd(); - $kind = RangeDifference::RIGHT; - } else { - $yourRange = $yourIter->getRange(); - $f = $yourRange[0]; - $l = $yourRange[\count($yourRange) - 1]; - $leftStart = $changeRangeStart - $f->getLeftStart() + $f->getRightStart(); - $leftEnd = $changeRangeEnd - $l->getLeftEnd() + $l->getRightEnd(); - } - - if ($kind === RangeDifference::ERROR) { - // Overlapping change (conflict) -> compare the changed ranges. - if (static::rangeSpansEqual( - $right, $rightStart, $rightEnd - $rightStart, - $left, $leftStart, $leftEnd - $leftStart)) { - $kind = RangeDifference::ANCESTOR; - } else { - $kind = RangeDifference::CONFLICT; - } - } - - return new RangeDifference( - $kind, - $rightStart, $rightEnd - $rightStart, - $leftStart, $leftEnd - $leftStart, - $changeRangeStart, $changeRangeEnd - $changeRangeStart); - } +// private static function createRangeDifference3( +// DifferencesIterator $myIter, +// DifferencesIterator $yourIter, +// array &$diff3, +// RangeComparatorInterface $right, +// RangeComparatorInterface $left, +// int $changeRangeStart, +// int $changeRangeEnd +// ): RangeDifference { +// $kind = RangeDifference::ERROR; +// /** @var RangeDifference $last */ +// $last = $diff3[\count($diff3) - 1]; +// +// // At least one range array must be non-empty. +// assert(true === ($myIter->getCount() !== 0 || $yourIter->getCount() !== 0)); +// +// // Find corresponding lines to changeRangeStart/End in right and left. +// if ($myIter->getCount() === 0) { +// // Only left changed. +// $rightStart = $changeRangeStart - $last->getAncestorEnd() + $last->getRightEnd(); +// $rightEnd = $changeRangeEnd - $last->getAncestorEnd() + $last->getRightEnd(); +// $kind = RangeDifference::LEFT; +// } else { +// $myRange = $myIter->getRange(); +// $f = $myRange[0]; +// $l = $myRange[\count($myRange) - 1]; +// $rightStart = $changeRangeStart - $f->getLeftStart() + $f->getRightStart(); +// $rightEnd = $changeRangeEnd - $l->getLeftEnd() + $l->getRightEnd(); +// } +// +// if ($yourIter->getCount() === 0) { +// // Only right changed. +// $leftStart = $changeRangeStart - $last->getAncestorEnd() + $last->getLeftEnd(); +// $leftEnd = $changeRangeEnd - $last->getAncestorEnd() + $last->getLeftEnd(); +// $kind = RangeDifference::RIGHT; +// } else { +// $yourRange = $yourIter->getRange(); +// $f = $yourRange[0]; +// $l = $yourRange[\count($yourRange) - 1]; +// $leftStart = $changeRangeStart - $f->getLeftStart() + $f->getRightStart(); +// $leftEnd = $changeRangeEnd - $l->getLeftEnd() + $l->getRightEnd(); +// } +// +// if ($kind === RangeDifference::ERROR) { +// // Overlapping change (conflict) -> compare the changed ranges. +// if (static::rangeSpansEqual( +// $right, $rightStart, $rightEnd - $rightStart, +// $left, $leftStart, $leftEnd - $leftStart)) { +// $kind = RangeDifference::ANCESTOR; +// } else { +// $kind = RangeDifference::CONFLICT; +// } +// } +// +// return new RangeDifference( +// $kind, +// $rightStart, $rightEnd - $rightStart, +// $leftStart, $leftEnd - $leftStart, +// $changeRangeStart, $changeRangeEnd - $changeRangeStart); +// } /** * Tests whether right and left changed in the same way. @@ -325,28 +327,28 @@ private static function createRangeDifference3( * @param int $leftLength * @return bool */ - private static function rangeSpansEqual( - RangeComparatorInterface $right, - int $rightStart, - int $rightLength, - RangeComparatorInterface $left, - int $leftStart, - int $leftLength - ): bool { - if ($rightLength === $leftLength) { - for ($i = 0; $i < $rightLength; $i++) { - if (!static::rangesEqual($right, $rightStart + $i, $left, $leftStart + $i)) { - break; - } - } - - if ($i === $rightLength) { - return true; - } - } - - return false; - } +// private static function rangeSpansEqual( +// RangeComparatorInterface $right, +// int $rightStart, +// int $rightLength, +// RangeComparatorInterface $left, +// int $leftStart, +// int $leftLength +// ): bool { +// if ($rightLength === $leftLength) { +// for ($i = 0; $i < $rightLength; $i++) { +// if (!static::rangesEqual($right, $rightStart + $i, $left, $leftStart + $i)) { +// break; +// } +// } +// +// if ($i === $rightLength) { +// return true; +// } +// } +// +// return false; +// } /** * Tests if two ranges are equal. @@ -357,12 +359,12 @@ private static function rangeSpansEqual( * @param int $bi * @return bool */ - private static function rangesEqual( - RangeComparatorInterface $a, - int $ai, - RangeComparatorInterface $b, - int $bi - ): bool { - return $a->rangesEqual($ai, $b, $bi); - } +// private static function rangesEqual( +// RangeComparatorInterface $a, +// int $ai, +// RangeComparatorInterface $b, +// int $bi +// ): bool { +// return $a->rangesEqual($ai, $b, $bi); +// } } diff --git a/tests/Core/DocLineComparator.php b/tests/Core/DocLineComparator.php deleted file mode 100644 index af80400..0000000 --- a/tests/Core/DocLineComparator.php +++ /dev/null @@ -1,179 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -declare(strict_types=1); - -namespace SN\RangeDifferencer\Core; - -use SN\RangeDifferencer\RangeComparatorInterface; - -class DocLineComparator implements TokenComparatorInterface -{ - /** @var string[] */ - private $document; - - /** @var string */ - private $documentStr = ''; - - /** @var int */ - private $lineOffset = 0; - - /** @var int */ - private $lineCount = 0; - - /** @var int */ - private $length = 0; - - /** @var bool */ - private $ignoreWhiteSpace = false; - - /** @var array */ - private $compareFilters = []; - - /** @var string */ - private $contributor = ''; - - public function __construct(string $document, bool $ignoreWhiteSpace, string $contributor = '?') - { - $this->document = \explode(PHP_EOL, $document); - $this->documentStr = $document; - $this->ignoreWhiteSpace = $ignoreWhiteSpace; - $this->contributor = $contributor; - - $this->length = \mb_strlen($document); - $this->lineCount = \count($this->document); - - for ($i = 0, $iMax = $this->lineCount - 1; $i < $iMax; $i++) { -// $this->document[$i] .= PHP_EOL; - } - } - - public function getRangeCount(): int - { - return $this->lineCount; - } - - public function getTokenStart(int $line): int - { - $line += $this->lineOffset; - - if (isset($this->document[$line])) { - $offset = 0; - - for ($i = 0; $i < $line; $i++) { - $offset += \mb_strlen($this->document[$i]); - } - - return $offset; - } - - return $this->length; - } - - public function getTokenLength(int $index): int - { - return $this->getTokenStart($index + 1) - $this->getTokenStart($index); - } - - public function rangesEqual(int $thisIndex, RangeComparatorInterface $other, int $otherIndex): bool - { - if (null !== $other && \get_class($this) === \get_class($other)) { - if ($this->ignoreWhiteSpace) { - $linesToCompare = $this->extract($thisIndex, $otherIndex, $other, false); - - return $this->compare($linesToCompare[0], $linesToCompare[1]); - } - - $tLen = $this->getTokenLength($thisIndex); - $oLen = $other->getTokenLength($otherIndex); - - if ($tLen === $oLen) { - $linesToCompare = $this->extract($thisIndex, $otherIndex, $other, false); - - return $linesToCompare[0] === $linesToCompare[1]; - } - } - - return false; - } - - public function skipRangeComparison(int $length, int $maxLength, RangeComparatorInterface $other): bool - { - return false; - } - - /** - * @param int $thisIndex - * @param int $otherIndex - * @param DocLineComparator $other - * @param bool $includeSeparator - * @return string[] - */ - private function extract(int $thisIndex, int $otherIndex, DocLineComparator $other, bool $includeSeparator): array - { - $extracts = [ - $this->extract2($thisIndex, $includeSeparator), - $other->extract2($otherIndex, $includeSeparator), - ]; - - return $extracts; - } - - public function extract2(int $line, bool $includeSeparator): string - { - if ($line < $this->lineCount) { - if ($includeSeparator) { - return $this->document[$line]; - } - - return $this->document[$line]; - } - - return ''; - } - - private function compare(string $s1, string $s2): bool - { - $l1 = \mb_strlen($s1); - $l2 = \mb_strlen($s2); - $c1 = 0; - $c2 = 0; - $i1 = 0; - $i2 = 0; - - while (-1 !== $c1) { - $c1 = -1; - - while ($i1 < $l1) { - $c = \mb_substr($s1, $i1++, 1); - - if (!in_array($c, [' ', "\n", "\r", "\t"], true)) { - $c1 = $c; - break; - } - } - - $c2 = -1; - - while ($i2 < $l2) { - $c = \mb_substr($s2, $i2++, 1); - - if (!in_array($c, [' ', "\n", "\r", "\t"], true)) { - $c2 = $c; - break; - } - } - - if ($c1 !== $c2) { - return false; - } - } - - return true; - } -} diff --git a/tests/RangeComparatorLCSTest.php b/tests/RangeComparatorLCSTest.php index f45df77..b01d8b4 100644 --- a/tests/RangeComparatorLCSTest.php +++ b/tests/RangeComparatorLCSTest.php @@ -21,242 +21,242 @@ class RangeComparatorLCSTest extends TestCase { public function testDifferencesIterator(): void { - $oldText = '
This is a blue book
'; - $newText = 'This is a big blue book
'; + $oldText = ' This is a blue book'; + $newText = ' This is a big blue book'; - $left = new TagComparator($oldText); - $right = new TagComparator($newText); + $left = new StringComparator($oldText); + $right = new StringComparator($newText); $rangeDifferences = RangeComparatorLCS::findDifferences($left, $right); $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (8, 0) Right: (8, 4)}', $rangeDifferences[0]->__toString()); } - public function testLength(): void - { - $oldText = 'This is a blue book
'; - $newText = 'This is a big blue book
'; - $left = new TagComparator($oldText); - $right = new TagComparator($newText); - - $comp = new RangeComparatorLCS($left, $right); - $this->assertSame(0, $comp->getLength()); - - $refMethod = new \ReflectionMethod($comp, 'getLength1'); - $refMethod->setAccessible(true); - $this->assertSame(12, $refMethod->invoke($comp)); - - $refMethod = new \ReflectionMethod($comp, 'getLength2'); - $refMethod->setAccessible(true); - $this->assertSame(16, $refMethod->invoke($comp)); - } - - public function testLengthEmpty1(): void - { - $oldText = ''; - $newText = 'This is a big blue book
'; - $left = new TagComparator($oldText); - $right = new TagComparator($newText); - - $comp = new RangeComparatorLCS($left, $right); - $this->assertSame(0, $comp->getLength()); - - $refMethod = new \ReflectionMethod($comp, 'getLength1'); - $refMethod->setAccessible(true); - $this->assertSame(0, $refMethod->invoke($comp)); - - $refMethod = new \ReflectionMethod($comp, 'getLength2'); - $refMethod->setAccessible(true); - $this->assertSame(16, $refMethod->invoke($comp)); - } - - public function testLengthEmpty2(): void - { - $oldText = 'This is a blue book
'; - $newText = ''; - $left = new TagComparator($oldText); - $right = new TagComparator($newText); - - $comp = new RangeComparatorLCS($left, $right); - $this->assertSame(0, $comp->getLength()); - - $refMethod = new \ReflectionMethod($comp, 'getLength1'); - $refMethod->setAccessible(true); - $this->assertSame(12, $refMethod->invoke($comp)); - - $refMethod = new \ReflectionMethod($comp, 'getLength2'); - $refMethod->setAccessible(true); - $this->assertSame(0, $refMethod->invoke($comp)); - } - - public function testLengthEmpty3(): void - { - $oldText = ''; - $newText = ''; - $left = new TagComparator($oldText); - $right = new TagComparator($newText); - - $comp = new RangeComparatorLCS($left, $right); - $this->assertSame(0, $comp->getLength()); - - $refMethod = new \ReflectionMethod($comp, 'getLength1'); - $refMethod->setAccessible(true); - $this->assertSame(0, $refMethod->invoke($comp)); - - $refMethod = new \ReflectionMethod($comp, 'getLength2'); - $refMethod->setAccessible(true); - $this->assertSame(0, $refMethod->invoke($comp)); - } - - public function testInitializeLCS(): void - { - $oldText = 'This is a blue book
'; - $newText = 'This is a big blue book
'; - $left = new TagComparator($oldText); - $right = new TagComparator($newText); - $comp = new RangeComparatorLCS($left, $right); - - $refMethod = new \ReflectionMethod($comp, 'initializeLcs'); - $refMethod->setAccessible(true); - $refMethod->invoke($comp, 20); - - $refProp = new \ReflectionProperty($comp, 'lcs'); - $refProp->setAccessible(true); - $lcs = $refProp->getValue($comp); - - $this->assertSame(2, \count($lcs)); - $this->assertSame(20, \count($lcs[0])); - $this->assertSame(20, \count($lcs[1])); - } - - public function testInitializeLCSZero(): void - { - $oldText = 'This is a blue book
'; - $newText = 'This is a big blue book
'; - $left = new TagComparator($oldText); - $right = new TagComparator($newText); - $comp = new RangeComparatorLCS($left, $right); - - $refMethod = new \ReflectionMethod($comp, 'initializeLcs'); - $refMethod->setAccessible(true); - $refMethod->invoke($comp, 0); - - $refProp = new \ReflectionProperty($comp, 'lcs'); - $refProp->setAccessible(true); - $lcs = $refProp->getValue($comp); - - $this->assertSame(2, \count($lcs)); - $this->assertSame(0, \count($lcs[0])); - $this->assertSame(0, \count($lcs[1])); - } - - public function testIsRangeEqual(): void - { - $oldText = 'This is a blue book
'; - $newText = 'This is a big blue book
'; - $left = new TagComparator($oldText); - $right = new TagComparator($newText); - $comp = new RangeComparatorLCS($left, $right); - - $refMethod = new \ReflectionMethod($comp, 'isRangeEqual'); - $refMethod->setAccessible(true); - - $this->assertTrue($refMethod->invoke($comp, 0, 0)); - $this->assertFalse($refMethod->invoke($comp, 0, 3)); - } - - public function testGetDifferences1(): void - { - $oldText = "This is a blue book
\nThis is a big blue book
'; - $left = new TagComparator($oldText); - $right = new TagComparator($newText); - $comp = new RangeComparatorLCS($left, $right); - - $diffs = $comp->getDifferences(); - $this->assertSame(1, \count($diffs)); - $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (0, 26) Right: (0, 16)}', $diffs[0]->__toString()); - } - - public function testGetDifferences2(): void - { - $oldText = "This is a big blue book
'; - $left = new TagComparator($oldText); - $right = new TagComparator($newText); - $comp = new RangeComparatorLCS($left, $right); - - $diffs = $comp->getDifferences(); - $this->assertSame(1, \count($diffs)); - $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (0, 11) Right: (0, 16)}', $diffs[0]->__toString()); - } - - public function testGetDifferences3(): void - { - $newText = "This is a big blue book
"; - $right = new TagComparator($newText); - $comp = new RangeComparatorLCS($right, $right); - - $diffs = $comp->getDifferences(); - $this->assertSame(1, \count($diffs)); - $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (0, 16) Right: (0, 16)}', $diffs[0]->__toString()); - } - - public function testGetDifferences4(): void - { - $newText = ''; - $right = new TagComparator($newText); - $comp = new RangeComparatorLCS($right, $right); - - $diffs = $comp->getDifferences(); - $this->assertSame(1, \count($diffs)); - $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (0, 0) Right: (0, 0)}', $diffs[0]->__toString()); - } - - public function testGetDifferences5(): void - { - $oldText = "This is a blue book
'; +// $newText = 'This is a big blue book
'; +// $left = new TagComparator($oldText); +// $right = new TagComparator($newText); +// +// $comp = new RangeComparatorLCS($left, $right); +// $this->assertSame(0, $comp->getLength()); +// +// $refMethod = new \ReflectionMethod($comp, 'getLength1'); +// $refMethod->setAccessible(true); +// $this->assertSame(12, $refMethod->invoke($comp)); +// +// $refMethod = new \ReflectionMethod($comp, 'getLength2'); +// $refMethod->setAccessible(true); +// $this->assertSame(16, $refMethod->invoke($comp)); +// } +// +// public function testLengthEmpty1(): void +// { +// $oldText = ''; +// $newText = 'This is a big blue book
'; +// $left = new TagComparator($oldText); +// $right = new TagComparator($newText); +// +// $comp = new RangeComparatorLCS($left, $right); +// $this->assertSame(0, $comp->getLength()); +// +// $refMethod = new \ReflectionMethod($comp, 'getLength1'); +// $refMethod->setAccessible(true); +// $this->assertSame(0, $refMethod->invoke($comp)); +// +// $refMethod = new \ReflectionMethod($comp, 'getLength2'); +// $refMethod->setAccessible(true); +// $this->assertSame(16, $refMethod->invoke($comp)); +// } +// +// public function testLengthEmpty2(): void +// { +// $oldText = 'This is a blue book
'; +// $newText = ''; +// $left = new TagComparator($oldText); +// $right = new TagComparator($newText); +// +// $comp = new RangeComparatorLCS($left, $right); +// $this->assertSame(0, $comp->getLength()); +// +// $refMethod = new \ReflectionMethod($comp, 'getLength1'); +// $refMethod->setAccessible(true); +// $this->assertSame(12, $refMethod->invoke($comp)); +// +// $refMethod = new \ReflectionMethod($comp, 'getLength2'); +// $refMethod->setAccessible(true); +// $this->assertSame(0, $refMethod->invoke($comp)); +// } +// +// public function testLengthEmpty3(): void +// { +// $oldText = ''; +// $newText = ''; +// $left = new TagComparator($oldText); +// $right = new TagComparator($newText); +// +// $comp = new RangeComparatorLCS($left, $right); +// $this->assertSame(0, $comp->getLength()); +// +// $refMethod = new \ReflectionMethod($comp, 'getLength1'); +// $refMethod->setAccessible(true); +// $this->assertSame(0, $refMethod->invoke($comp)); +// +// $refMethod = new \ReflectionMethod($comp, 'getLength2'); +// $refMethod->setAccessible(true); +// $this->assertSame(0, $refMethod->invoke($comp)); +// } +// +// public function testInitializeLCS(): void +// { +// $oldText = 'This is a blue book
'; +// $newText = 'This is a big blue book
'; +// $left = new TagComparator($oldText); +// $right = new TagComparator($newText); +// $comp = new RangeComparatorLCS($left, $right); +// +// $refMethod = new \ReflectionMethod($comp, 'initializeLcs'); +// $refMethod->setAccessible(true); +// $refMethod->invoke($comp, 20); +// +// $refProp = new \ReflectionProperty($comp, 'lcs'); +// $refProp->setAccessible(true); +// $lcs = $refProp->getValue($comp); +// +// $this->assertSame(2, \count($lcs)); +// $this->assertSame(20, \count($lcs[0])); +// $this->assertSame(20, \count($lcs[1])); +// } +// +// public function testInitializeLCSZero(): void +// { +// $oldText = 'This is a blue book
'; +// $newText = 'This is a big blue book
'; +// $left = new TagComparator($oldText); +// $right = new TagComparator($newText); +// $comp = new RangeComparatorLCS($left, $right); +// +// $refMethod = new \ReflectionMethod($comp, 'initializeLcs'); +// $refMethod->setAccessible(true); +// $refMethod->invoke($comp, 0); +// +// $refProp = new \ReflectionProperty($comp, 'lcs'); +// $refProp->setAccessible(true); +// $lcs = $refProp->getValue($comp); +// +// $this->assertSame(2, \count($lcs)); +// $this->assertSame(0, \count($lcs[0])); +// $this->assertSame(0, \count($lcs[1])); +// } +// +// public function testIsRangeEqual(): void +// { +// $oldText = 'This is a blue book
'; +// $newText = 'This is a big blue book
'; +// $left = new TagComparator($oldText); +// $right = new TagComparator($newText); +// $comp = new RangeComparatorLCS($left, $right); +// +// $refMethod = new \ReflectionMethod($comp, 'isRangeEqual'); +// $refMethod->setAccessible(true); +// +// $this->assertTrue($refMethod->invoke($comp, 0, 0)); +// $this->assertFalse($refMethod->invoke($comp, 0, 3)); +// } +// +// public function testGetDifferences1(): void +// { +// $oldText = "This is a blue book
\nThis is a big blue book
'; +// $left = new TagComparator($oldText); +// $right = new TagComparator($newText); +// $comp = new RangeComparatorLCS($left, $right); +// +// $diffs = $comp->getDifferences(); +// $this->assertSame(1, \count($diffs)); +// $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (0, 26) Right: (0, 16)}', $diffs[0]->__toString()); +// } +// +// public function testGetDifferences2(): void +// { +// $oldText = "This is a big blue book
'; +// $left = new TagComparator($oldText); +// $right = new TagComparator($newText); +// $comp = new RangeComparatorLCS($left, $right); +// +// $diffs = $comp->getDifferences(); +// $this->assertSame(1, \count($diffs)); +// $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (0, 11) Right: (0, 16)}', $diffs[0]->__toString()); +// } +// +// public function testGetDifferences3(): void +// { +// $newText = "This is a big blue book
"; +// $right = new TagComparator($newText); +// $comp = new RangeComparatorLCS($right, $right); +// +// $diffs = $comp->getDifferences(); +// $this->assertSame(1, \count($diffs)); +// $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (0, 16) Right: (0, 16)}', $diffs[0]->__toString()); +// } +// +// public function testGetDifferences4(): void +// { +// $newText = ''; +// $right = new TagComparator($newText); +// $comp = new RangeComparatorLCS($right, $right); +// +// $diffs = $comp->getDifferences(); +// $this->assertSame(1, \count($diffs)); +// $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (0, 0) Right: (0, 0)}', $diffs[0]->__toString()); +// } +// +// public function testGetDifferences5(): void +// { +// $oldText = "This is a green book about food
'; - $newText = 'This is a big blue book
'; - $left = new TagComparator($oldText); - $right = new TagComparator($newText); - - $diffs = RangeDifferencer::findRanges($left, $right); - - $this->assertSame(5, \count($diffs)); - $this->assertSame('RangeDifference {NOCHANGE, Left: (0, 8) Right: (0, 8)}', $diffs[0]->__toString()); - $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (8, 1) Right: (8, 5)}', $diffs[1]->__toString()); - $this->assertSame('RangeDifference {NOCHANGE, Left: (9, 2) Right: (13, 2)}', $diffs[2]->__toString()); - $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (11, 4) Right: (15, 0)}', $diffs[3]->__toString()); - $this->assertSame('RangeDifference {NOCHANGE, Left: (15, 1) Right: (15, 1)}', $diffs[4]->__toString()); - } - - public function testFindRanges3(): void - { - $ancestorText = 'This is a book
'; - $oldText = 'This is a green book about food
'; - $newText = 'This is a big blue book
'; - $ancestor = new TagComparator($ancestorText); - $left = new TagComparator($oldText); - $right = new TagComparator($newText); - - $diffs = RangeDifferencer::findDifferences3($ancestor, $left, $right); - - $this->assertSame(3, \count($diffs)); - $this->assertSame('RangeDifference {CONFLICT, Left: (8, 2) Right: (8, 6) Ancestor: (8, 0)}', $diffs[0]->__toString()); - $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (11, 1) Right: (15, 0) Ancestor: (9, 1)}', $diffs[1]->__toString()); - $this->assertSame('RangeDifference {LEFT, Left: (12, 3) Right: (15, 0) Ancestor: (10, 0)}', $diffs[2]->__toString()); - } +// public function testFindRanges_1(): void +// { +// $oldText = 'This is a green book about food
'; +// $newText = 'This is a big blue book
'; +// $left = new TagComparator($oldText); +// $right = new TagComparator($newText); +// +// $diffs = RangeDifferencer::findRanges($left, $right); +// +// $this->assertSame(5, \count($diffs)); +// $this->assertSame('RangeDifference {NOCHANGE, Left: (0, 8) Right: (0, 8)}', $diffs[0]->__toString()); +// $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (8, 1) Right: (8, 5)}', $diffs[1]->__toString()); +// $this->assertSame('RangeDifference {NOCHANGE, Left: (9, 2) Right: (13, 2)}', $diffs[2]->__toString()); +// $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (11, 4) Right: (15, 0)}', $diffs[3]->__toString()); +// $this->assertSame('RangeDifference {NOCHANGE, Left: (15, 1) Right: (15, 1)}', $diffs[4]->__toString()); +// } +// +// public function testFindRanges3(): void +// { +// $ancestorText = 'This is a book
'; +// $oldText = 'This is a green book about food
'; +// $newText = 'This is a big blue book
'; +// $ancestor = new TagComparator($ancestorText); +// $left = new TagComparator($oldText); +// $right = new TagComparator($newText); +// +// $diffs = RangeDifferencer::findDifferences3($ancestor, $left, $right); +// +// $this->assertSame(3, \count($diffs)); +// $this->assertSame('RangeDifference {CONFLICT, Left: (8, 2) Right: (8, 6) Ancestor: (8, 0)}', $diffs[0]->__toString()); +// $this->assertSame('RangeDifference {CHANGE/RIGHT, Left: (11, 1) Right: (15, 0) Ancestor: (9, 1)}', $diffs[1]->__toString()); +// $this->assertSame('RangeDifference {LEFT, Left: (12, 3) Right: (15, 0) Ancestor: (10, 0)}', $diffs[2]->__toString()); +// } } diff --git a/tests/StringComparator.php b/tests/StringComparator.php new file mode 100644 index 0000000..e113043 --- /dev/null +++ b/tests/StringComparator.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SN\RangeDifferencer; + +/** + * A comparator that compares strings. + * + * @internal + */ +class StringComparator implements RangeComparatorInterface +{ + /** @var string[] */ + private $leafs = []; + + /** + * Default values. + * + * @param string $text + */ + public function __construct(string $text) + { + $split = \preg_split('/\s+/', $text); + + foreach ($split as $word) { + $this->leafs[] = $word; + } + } + + /** + * @param int $index + * @return string + * + * @throws \OutOfRangeException + */ + public function getLeaf(int $index): string + { + if (isset($this->lines[$index])) { + return $this->leafs[$index]; + } + + throw new \OutOfRangeException(); + } + + /** + * @return int + */ + public function getRangeCount(): int + { + return \count($this->leafs); + } + + /** + * @param int $thisIndex + * @param RangeComparatorInterface $other + * @param int $otherIndex + * @return bool + */ + public function rangesEqual(int $thisIndex, RangeComparatorInterface $other, int $otherIndex): bool + { + if ($other instanceof StringComparator) { + return $other->getLeaf($otherIndex) === $this->getLeaf($thisIndex); + } + + return false; + } + + /** + * @param int $length + * @param int $maxLength + * @param RangeComparatorInterface $other + * @return bool + */ + public function skipRangeComparison(int $length, int $maxLength, RangeComparatorInterface $other): bool + { + return false; + } +}