diff --git a/src/CodePatcher.php b/src/CodePatcher.php index c6ba019a..3cd1c0d5 100644 --- a/src/CodePatcher.php +++ b/src/CodePatcher.php @@ -85,6 +85,16 @@ public function patch(ExerciseInterface $exercise, string $code): string private function applyPatch(Patch $patch, string $code): string { $statements = $this->parser->parse($code); + + if ($statements === null) { + $statements = []; + } + + $declare = null; + if (isset($statements[0]) && $statements[0] instanceof \PhpParser\Node\Stmt\Declare_) { + $declare = array_shift($statements); + } + foreach ($patch->getModifiers() as $modifier) { if ($modifier instanceof CodeInsertion) { $statements = $this->applyCodeInsertion($modifier, $statements); @@ -97,6 +107,10 @@ private function applyPatch(Patch $patch, string $code): string } } + if ($declare !== null) { + array_unshift($statements, $declare); + } + return $this->printer->prettyPrintFile($statements); } diff --git a/test/CodePatcherTest.php b/test/CodePatcherTest.php index 64adab6f..3f8df187 100644 --- a/test/CodePatcherTest.php +++ b/test/CodePatcherTest.php @@ -121,4 +121,52 @@ public function codeProvider(): array ], ]; } + + public function testBeforeInsertionInsertsAfterStrictTypesDeclaration(): void + { + $code = 'withInsertion(new Insertion(Insertion::TYPE_BEFORE, '$before = "here";')); + + $patcher = new CodePatcher((new ParserFactory())->create(ParserFactory::PREFER_PHP7), new Standard()); + + $exercise = $this->createMock(PatchableExercise::class); + + $exercise + ->expects($this->once()) + ->method('getPatch') + ->willReturn($patch); + + $this->assertEquals( + "patch($exercise, $code) + ); + } + + public function testTransformerWithStrictTypes(): void + { + $code = 'withTransformer(function (array $statements) { + return [ + new TryCatch( + $statements, + [new Catch_([new Name(\Exception::class)], new Variable('e'), [])] + ) + ]; + }); + + $patcher = new CodePatcher((new ParserFactory())->create(ParserFactory::PREFER_PHP7), new Standard()); + + $exercise = $this->createMock(PatchableExercise::class); + + $exercise + ->expects($this->once()) + ->method('getPatch') + ->willReturn($patch); + + $this->assertEquals( + "patch($exercise, $code) + ); + } }