Skip to content

Commit 9beb77b

Browse files
authored
Merge pull request #207 from php-school/code-patching-with-strict-types
Keep position of declare statements when patching code
2 parents 98733db + b1798e6 commit 9beb77b

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

src/CodePatcher.php

+14
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,16 @@ public function patch(ExerciseInterface $exercise, string $code): string
8585
private function applyPatch(Patch $patch, string $code): string
8686
{
8787
$statements = $this->parser->parse($code);
88+
89+
if ($statements === null) {
90+
$statements = [];
91+
}
92+
93+
$declare = null;
94+
if (isset($statements[0]) && $statements[0] instanceof \PhpParser\Node\Stmt\Declare_) {
95+
$declare = array_shift($statements);
96+
}
97+
8898
foreach ($patch->getModifiers() as $modifier) {
8999
if ($modifier instanceof CodeInsertion) {
90100
$statements = $this->applyCodeInsertion($modifier, $statements);
@@ -97,6 +107,10 @@ private function applyPatch(Patch $patch, string $code): string
97107
}
98108
}
99109

110+
if ($declare !== null) {
111+
array_unshift($statements, $declare);
112+
}
113+
100114
return $this->printer->prettyPrintFile($statements);
101115
}
102116

test/CodePatcherTest.php

+48
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,52 @@ public function codeProvider(): array
121121
],
122122
];
123123
}
124+
125+
public function testBeforeInsertionInsertsAfterStrictTypesDeclaration(): void
126+
{
127+
$code = '<?php declare(strict_types=1); $original = true;';
128+
$patch = (new Patch())->withInsertion(new Insertion(Insertion::TYPE_BEFORE, '$before = "here";'));
129+
130+
$patcher = new CodePatcher((new ParserFactory())->create(ParserFactory::PREFER_PHP7), new Standard());
131+
132+
$exercise = $this->createMock(PatchableExercise::class);
133+
134+
$exercise
135+
->expects($this->once())
136+
->method('getPatch')
137+
->willReturn($patch);
138+
139+
$this->assertEquals(
140+
"<?php\n\ndeclare (strict_types=1);\n\$before = \"here\";\n\$original = true;",
141+
$patcher->patch($exercise, $code)
142+
);
143+
}
144+
145+
public function testTransformerWithStrictTypes(): void
146+
{
147+
$code = '<?php declare(strict_types=1); $original = true;';
148+
$patch = (new Patch())
149+
->withTransformer(function (array $statements) {
150+
return [
151+
new TryCatch(
152+
$statements,
153+
[new Catch_([new Name(\Exception::class)], new Variable('e'), [])]
154+
)
155+
];
156+
});
157+
158+
$patcher = new CodePatcher((new ParserFactory())->create(ParserFactory::PREFER_PHP7), new Standard());
159+
160+
$exercise = $this->createMock(PatchableExercise::class);
161+
162+
$exercise
163+
->expects($this->once())
164+
->method('getPatch')
165+
->willReturn($patch);
166+
167+
$this->assertEquals(
168+
"<?php\n\ndeclare (strict_types=1);\ntry {\n \$original = true;\n} catch (Exception \$e) {\n}",
169+
$patcher->patch($exercise, $code)
170+
);
171+
}
124172
}

0 commit comments

Comments
 (0)