Skip to content

Commit

Permalink
refactor - move write logic to Insertion class
Browse files Browse the repository at this point in the history
  • Loading branch information
holgerk committed Apr 7, 2024
1 parent 24c889c commit 706f16d
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 87 deletions.
4 changes: 2 additions & 2 deletions src/Autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
use Symfony\Component\VarExporter\VarExporter;

expect()->extend('toEqualGolden', function (mixed $golden): Expectation {
if ($golden === null || Plugin::$updateGolden) {
if ($golden === null || Plugin::$forceUpdateGolden) {
$golden = $this->value;
$replacement = VarExporter::export($golden);
Plugin::registerInsertion(Insertion::make($replacement));
Insertion::register($replacement);
}

return $this->toEqual($golden);
Expand Down
75 changes: 73 additions & 2 deletions src/Insertion.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
/** @internal */
final class Insertion
{
public static function make(string $replacement): self
/** @var self[] */
public static array $insertions = [];

public static function register(string $replacement): void
{
$filePath = null;
$lineToFind = null;
Expand Down Expand Up @@ -40,14 +43,82 @@ public static function make(string $replacement): self
/** @var Node $argumentNode */
$argumentNode = $node->getAttribute('next');

return new self(
self::$insertions[] = new self(
$filePath,
$argumentNode->getStartFilePos(),
$argumentNode->getEndFilePos(),
$replacement
);
}

public static function writeAndResetInsertions(): void
{
$insertions = self::$insertions;
self::$insertions = [];

// arrange insertions starting from the end of the file to prevent disrupting the positions during replacements
usort($insertions, function (Insertion $a, Insertion $b): int {
if ($a->file !== $b->file) {
return $a->file <=> $b->file;
}

return $b->startPos <=> $a->startPos;
});

foreach ($insertions as $insertion) {
$content = file_get_contents($insertion->file);
$indent = self::getIndent($insertion->startPos, $content);

// add indention
$replacement = $insertion->replacement;
$replacementLines = explode("\n", $replacement);
$replacement = implode("\n$indent", $replacementLines);

// insert expectation
$content = substr_replace(
$content,
$replacement,
$insertion->startPos,
$insertion->endPos - $insertion->startPos + 1
);
file_put_contents($insertion->file, $content);
}
}

private static function getIndent(int $startPos, string $content): string
{
// detect start of line position
$offset = 0;
$startOfLine = 0;
while (true) {
$offset -= 1;
$charPos = $startPos + $offset;
if ($charPos < 0) {
break;
}
$char = $content[$charPos];
if ($char === "\n" || $char === "\r") {
$startOfLine = $startPos + $offset + 1;
break;
}
}
// detect indention
$indent = '';
$offset = 0;
while (true) {
$charPos = $startOfLine + $offset;
$char = $content[$charPos];
if ($char === ' ' || $char === "\t") {
$indent .= $char;
} else {
break;
}
$offset += 1;
}

return $indent;
}

private function __construct(
public string $file,
public int $startPos,
Expand Down
84 changes: 4 additions & 80 deletions src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ final class Plugin implements AddsOutput, HandlesArguments, Terminable
{
use HandleArguments;

/** @var Insertion[] */
private static array $insertions = [];

public static bool $updateGolden = false;
public static bool $forceUpdateGolden = false;

private OutputInterface $output;

Expand All @@ -27,29 +24,24 @@ public function __construct(OutputInterface $output)
$this->output = $output;
}

public static function registerInsertion(Insertion $insertion): void
{
self::$insertions[] = $insertion;
}

public function handleArguments(array $arguments): array
{
if ($this->hasArgument('--update-golden', $arguments)) {
$arguments = $this->popArgument('--update-golden', $arguments);
self::$updateGolden = true;
self::$forceUpdateGolden = true;
}

return $arguments;
}

public function terminate(): void
{
$this->writeAndResetInsertions();
Insertion::writeAndResetInsertions();
}

public function addOutput(int $exitCode): int
{
foreach (self::$insertions as $insertion) {
foreach (Insertion::$insertions as $insertion) {
$this->output->writeln([
sprintf(
' <fg=white;options=bold;bg=blue> INFO </> Writing expectations to: %s.',
Expand All @@ -60,72 +52,4 @@ public function addOutput(int $exitCode): int

return $exitCode;
}

private function writeAndResetInsertions(): void
{
$insertions = self::$insertions;
self::$insertions = [];

// arrange insertions starting from the end of the file to prevent disrupting the positions during replacements
usort($insertions, function (Insertion $a, Insertion $b): int {
if ($a->file !== $b->file) {
return $a->file <=> $b->file;
}

return $b->startPos <=> $a->startPos;
});

foreach ($insertions as $insertion) {
$content = file_get_contents($insertion->file);
$indent = $this->getIndent($insertion->startPos, $content);

// add indention
$replacement = $insertion->replacement;
$replacementLines = explode("\n", $replacement);
$replacement = implode("\n$indent", $replacementLines);

// insert expectation
$content = substr_replace(
$content,
$replacement,
$insertion->startPos,
$insertion->endPos - $insertion->startPos + 1
);
file_put_contents($insertion->file, $content);
}
}

private function getIndent(int $startPos, string $content): string
{
// detect start of line position
$offset = 0;
$startOfLine = 0;
while (true) {
$offset -= 1;
$charPos = $startPos + $offset;
if ($charPos < 0) {
break;
}
$char = $content[$charPos];
if ($char === "\n" || $char === "\r") {
$startOfLine = $startPos + $offset + 1;
break;
}
}
// detect indention
$indent = '';
$offset = 0;
while (true) {
$charPos = $startOfLine + $offset;
$char = $content[$charPos];
if ($char === ' ' || $char === "\t") {
$indent .= $char;
} else {
break;
}
$offset += 1;
}

return $indent;
}
}
2 changes: 1 addition & 1 deletion tests/ExpectationsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use PHPUnit\Framework\ExpectationFailedException;
use Symfony\Component\Console\Output\NullOutput;

beforeEach(fn () => Plugin::$updateGolden = false);
beforeEach(fn () => Plugin::$forceUpdateGolden = false);

test('generate expectation', function (string $case) {
// GIVEN
Expand Down
2 changes: 1 addition & 1 deletion tests/cases/update-golden/expected.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

use Holgerk\EqualGolden\Plugin;

Plugin::$updateGolden = true;
Plugin::$forceUpdateGolden = true;
expect('hello')->toEqualGolden('hello');
2 changes: 1 addition & 1 deletion tests/cases/update-golden/input.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

use Holgerk\EqualGolden\Plugin;

Plugin::$updateGolden = true;
Plugin::$forceUpdateGolden = true;
expect('hello')->toEqualGolden('different');

0 comments on commit 706f16d

Please sign in to comment.