Skip to content

Commit

Permalink
Fix anonymous-migrations parsing beyond class declaration (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
flap152 authored Oct 20, 2023
1 parent cee60f6 commit 4d85c93
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 2 deletions.
21 changes: 19 additions & 2 deletions src/Tasks/AnonymousMigrations.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace Shift\Cli\Tasks;

use Illuminate\Support\Str;
use Shift\Cli\Sdk\Contracts\Task;
use Shift\Cli\Sdk\Models\File;
use Shift\Cli\Sdk\Traits\FindsFiles;

class AnonymousMigrations implements Task
Expand All @@ -22,6 +22,15 @@ public function perform(): int
return 0;
}

private function parseClass(string $contents)
{
static $finder;

$finder ??= new \Shift\Cli\Sdk\Parsers\NikicParser(new \Shift\Cli\Sdk\Parsers\Finders\ClassDefinition());

return $finder->parse($contents);
}

private function updateMigrations(): void
{
foreach ($this->findFilesContaining('/\bclass\s+\S+\s+extends\s+Migration\s/') as $path) {
Expand Down Expand Up @@ -77,14 +86,22 @@ private function updateStubs(): void

private function convertClassDefinition($contents): ?string
{
$file = File::fromString($contents);
$class = $this->parseClass($file->contents());

$found = \preg_match('/^class\s+(\S+)\s+extends\s+Migration(\s+)/m', $contents, $matches);
if (! $found) {
return null;
}
$contents = \substr_replace($contents,
';',
$class['offset']['end'] + 1,
0
);

$contents = \str_replace(\rtrim($matches[0]), 'return new class extends Migration', $contents);
$contents = \preg_replace('/\b' . \preg_quote($matches[1], '/') . '::/', 'self::', $contents);

return Str::replaceLast('}', '};', $contents);
return $contents;
}
}
14 changes: 14 additions & 0 deletions tests/Feature/Tasks/AnonymousMigrationsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,18 @@ public function it_converts_migrations_and_stubs()
$this->assertFileChanges('tests/fixtures/anonymous-migrations/simple.after.php', 'other/migrations/2014_10_12_000000_create_users_table.php');
$this->assertFileChanges('tests/fixtures/anonymous-migrations/stub.after.php', 'stubs/migration.stub');
}

#[Test]
public function it_converts_with_comments_beyond_the_class()
{
$this->fakeProject([
'database/migrations/2015_10_12_000000_create_users_table.php' => 'tests/fixtures/anonymous-migrations/post-class-comments.php',
]);

$result = $this->subject->perform();

$this->assertSame(0, $result);

$this->assertFileChanges('tests/fixtures/anonymous-migrations/post-class-comments.after.php', 'database/migrations/2015_10_12_000000_create_users_table.php');
}
}
36 changes: 36 additions & 0 deletions tests/fixtures/anonymous-migrations/post-class-comments.after.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('videos', function (Blueprint $table) {
$table->integer('runtime')->nullable();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('videos', function (Blueprint $table) {
$table->dropColumn('runtime');
});
}
};

/* a closing bracket in a comment here can confuse the parsing
{ id: 1, name: "Doug" }
*/
36 changes: 36 additions & 0 deletions tests/fixtures/anonymous-migrations/post-class-comments.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class PostClassComments extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('videos', function (Blueprint $table) {
$table->integer('runtime')->nullable();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('videos', function (Blueprint $table) {
$table->dropColumn('runtime');
});
}
}

/* a closing bracket in a comment here can confuse the parsing
{ id: 1, name: "Doug" }
*/

0 comments on commit 4d85c93

Please sign in to comment.