Skip to content

Commit ead99dc

Browse files
authored
fix: Preserve heredoc/newdoc indentation (#1037)
1 parent f21ea1b commit ead99dc

File tree

5 files changed

+99
-15
lines changed

5 files changed

+99
-15
lines changed

phpstan.neon.dist

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,6 @@ parameters:
6060
path: 'src/PhpParser/NodeVisitor/ClassAliasStmtAppender.php'
6161
- message: '#PhpVersion::fromComponents#'
6262
path: 'tests/SpecFramework/SpecScenario.php'
63+
# Fixed in https://github.com/nikic/PHP-Parser/pull/1003
64+
- message: '#Standard constructor expects array#'
65+
path: 'src/Container.php'

specs/misc/nowdoc.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*/
1414

1515
use Humbug\PhpScoper\SpecFramework\Config\Meta;
16+
use Humbug\PhpScoper\SpecFramework\Config\SpecWithConfig;
1617

1718
return [
1819
'meta' => new Meta(
@@ -171,4 +172,46 @@
171172
PHP_HEREDOC;
172173

173174
PHP,
175+
176+
// As per the RFC: https://wiki.php.net/rfc/flexible_heredoc_nowdoc_syntaxes
177+
'Nowdoc and Heredoc indentation' => SpecWithConfig::create(
178+
phpVersionUsed: 70_200,
179+
spec: <<<'PHP'
180+
<?php
181+
182+
// no indentation
183+
echo <<<END
184+
a
185+
b
186+
c
187+
END;
188+
189+
// 4 spaces of indentation
190+
echo <<<END
191+
a
192+
b
193+
c
194+
END;
195+
196+
----
197+
<?php
198+
199+
namespace Humbug;
200+
201+
// no indentation
202+
echo <<<END
203+
a
204+
b
205+
c
206+
END;
207+
// 4 spaces of indentation
208+
echo <<<END
209+
a
210+
b
211+
c
212+
END
213+
;
214+
215+
PHP,
216+
),
174217
];

src/Container.php

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ final class Container
3737
private Filesystem $filesystem;
3838
private ConfigurationFactory $configFactory;
3939
private Parser $parser;
40-
private ?PhpVersion $phpVersion = null;
40+
private ?PhpVersion $parserPhpVersion = null;
41+
private ?PhpVersion $printerPhpVersion = null;
4142
private Reflector $reflector;
4243
private ScoperFactory $scoperFactory;
4344
private EnrichedReflectorFactory $enrichedReflectorFactory;
@@ -82,20 +83,11 @@ public function getScoperFactory(?PhpVersion $phpVersion = null): ScoperFactory
8283
public function getParser(?PhpVersion $phpVersion = null): Parser
8384
{
8485
if (!isset($this->parser)) {
85-
$this->phpVersion = $phpVersion;
86+
$this->parserPhpVersion = $phpVersion;
8687
$this->parser = $this->createParser($phpVersion);
8788
}
8889

89-
$parserVersion = $this->phpVersion;
90-
91-
$parserMessage = 'Cannot use the existing parser: its PHP version is different than the one requested.';
92-
93-
if (null === $parserVersion) {
94-
Assert::null($phpVersion, $parserMessage);
95-
} else {
96-
Assert::notNull($phpVersion, $parserMessage);
97-
Assert::true($parserVersion->equals($phpVersion), $parserMessage);
98-
}
90+
self::checkSamePhpVersion($this->parserPhpVersion, $phpVersion);
9991

10092
return $this->parser;
10193
}
@@ -130,14 +122,33 @@ public function getEnrichedReflectorFactory(): EnrichedReflectorFactory
130122
return $this->enrichedReflectorFactory;
131123
}
132124

133-
public function getPrinter(): Printer
125+
public function getPrinter(?PhpVersion $phpVersion = null): Printer
134126
{
135127
if (!isset($this->printer)) {
128+
$this->printerPhpVersion = $phpVersion;
136129
$this->printer = new StandardPrinter(
137-
new Standard(),
130+
new Standard([
131+
'phpVersion' => $phpVersion,
132+
]),
138133
);
139134
}
140135

136+
self::checkSamePhpVersion($this->printerPhpVersion, $phpVersion);
137+
141138
return $this->printer;
142139
}
140+
141+
private static function checkSamePhpVersion(
142+
?PhpVersion $versionUsed,
143+
?PhpVersion $versionRequest,
144+
): void {
145+
$parserMessage = 'Cannot use the existing parser: its PHP version is different than the one requested.';
146+
147+
if (null === $versionUsed) {
148+
Assert::null($versionRequest, $parserMessage);
149+
} else {
150+
Assert::notNull($versionRequest, $parserMessage);
151+
Assert::true($versionUsed->equals($versionRequest), $parserMessage);
152+
}
153+
}
143154
}

tests/ContainerTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,19 @@ public function test_it_can_get_the_parser_if_the_version_does_not_change(
7474
$this->addToAssertionCount(1);
7575
}
7676

77+
#[DataProvider('samePhpVersionProvider')]
78+
public function test_it_can_get_the_printer_if_the_version_does_not_change(
79+
?PhpVersion $version1,
80+
?PhpVersion $version2,
81+
): void {
82+
$container = new Container();
83+
84+
$container->getPrinter($version1);
85+
$container->getPrinter($version2);
86+
87+
$this->addToAssertionCount(1);
88+
}
89+
7790
public static function samePhpVersionProvider(): iterable
7891
{
7992
yield 'no PHP version configured' => [
@@ -108,6 +121,20 @@ public function test_it_cannot_create_two_different_versions_of_the_parser(
108121
$container->getParser($version2);
109122
}
110123

124+
#[DataProvider('differentPhpVersionProvider')]
125+
public function test_it_cannot_create_two_different_versions_of_the_printer(
126+
?PhpVersion $version1,
127+
?PhpVersion $version2,
128+
): void {
129+
$container = new Container();
130+
131+
$container->getPrinter($version1);
132+
133+
$this->expectException(InvalidArgumentException::class);
134+
135+
$container->getPrinter($version2);
136+
}
137+
111138
public static function differentPhpVersionProvider(): iterable
112139
{
113140
$phpVersion = PhpVersion::fromString('7.2');

tests/Scoper/PhpScoperSpecTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ private static function createScoper(
136136
$prefix,
137137
$symbolsRegistry,
138138
),
139-
$container->getPrinter(),
139+
$container->getPrinter($phpVersionUsed),
140140
);
141141
}
142142

0 commit comments

Comments
 (0)