diff --git a/src/BetterReflection.php b/src/BetterReflection.php index 00c69e298..41e617a14 100644 --- a/src/BetterReflection.php +++ b/src/BetterReflection.php @@ -7,6 +7,7 @@ use PhpParser\Lexer\Emulative; use PhpParser\Parser; use PhpParser\ParserFactory; +use PhpParser\PrettyPrinter\Standard; use Roave\BetterReflection\Reflector\DefaultReflector; use Roave\BetterReflection\Reflector\Reflector; use Roave\BetterReflection\SourceLocator\Ast\Locator as AstLocator; @@ -48,18 +49,30 @@ final class BetterReflection private static SourceStubber|null $sharedSourceStubber = null; + /** + * @var Standard|null + */ + private static $sharedPrinter = null; + + /** + * @var Standard|null + */ + private $printer = null; + public static function populate( int $phpVersion, SourceLocator $sourceLocator, Reflector $classReflector, Parser $phpParser, SourceStubber $sourceStubber, + Standard $printer, ): void { self::$phpVersion = $phpVersion; self::$sharedSourceLocator = $sourceLocator; self::$sharedReflector = $classReflector; self::$sharedPhpParser = $phpParser; self::$sharedSourceStubber = $sourceStubber; + self::$sharedPrinter = $printer; } public function __construct() @@ -68,6 +81,7 @@ public function __construct() $this->reflector = self::$sharedReflector; $this->phpParser = self::$sharedPhpParser; $this->sourceStubber = self::$sharedSourceStubber; + $this->printer = self::$sharedPrinter; } public function sourceLocator(): SourceLocator @@ -113,8 +127,13 @@ public function sourceStubber(): SourceStubber { return $this->sourceStubber ?? $this->sourceStubber = new AggregateSourceStubber( - new PhpStormStubsSourceStubber($this->phpParser(), self::$phpVersion), - new ReflectionSourceStubber(), + new PhpStormStubsSourceStubber($this->phpParser(), $this->printer(), self::$phpVersion), + new ReflectionSourceStubber($this->printer()), ); } + + public function printer(): Standard + { + return $this->printer ?? $this->printer = new Standard(['shortArraySyntax' => true]); + } } diff --git a/src/Reflection/Exception/InvalidArrowFunctionBodyNode.php b/src/Reflection/Exception/InvalidArrowFunctionBodyNode.php index 99d6f7673..82abf1522 100644 --- a/src/Reflection/Exception/InvalidArrowFunctionBodyNode.php +++ b/src/Reflection/Exception/InvalidArrowFunctionBodyNode.php @@ -5,7 +5,7 @@ namespace Roave\BetterReflection\Reflection\Exception; use PhpParser\Node\Stmt; -use PhpParser\PrettyPrinter\Standard; +use Roave\BetterReflection\BetterReflection; use RuntimeException; use function sprintf; @@ -15,9 +15,10 @@ class InvalidArrowFunctionBodyNode extends RuntimeException { public static function create(Stmt $node): self { + $printer = (new BetterReflection)->printer(); return new self(sprintf( 'Invalid arrow function body node (first 50 characters: %s)', - substr((new Standard())->prettyPrint([$node]), 0, 50), + substr($printer->prettyPrint([$node]), 0, 50), )); } } diff --git a/src/Reflection/Exception/InvalidConstantNode.php b/src/Reflection/Exception/InvalidConstantNode.php index 5eae9aeba..fafec209f 100644 --- a/src/Reflection/Exception/InvalidConstantNode.php +++ b/src/Reflection/Exception/InvalidConstantNode.php @@ -5,7 +5,7 @@ namespace Roave\BetterReflection\Reflection\Exception; use PhpParser\Node; -use PhpParser\PrettyPrinter\Standard; +use Roave\BetterReflection\BetterReflection; use RuntimeException; use function sprintf; @@ -15,9 +15,10 @@ class InvalidConstantNode extends RuntimeException { public static function create(Node $node): self { + $printer = (new BetterReflection())->printer(); return new self(sprintf( 'Invalid constant node (first 50 characters: %s)', - substr((new Standard())->prettyPrint([$node]), 0, 50), + substr($printer->prettyPrint([$node]), 0, 50), )); } } diff --git a/src/SourceLocator/SourceStubber/PhpStormStubsSourceStubber.php b/src/SourceLocator/SourceStubber/PhpStormStubsSourceStubber.php index 282546723..be943af0b 100644 --- a/src/SourceLocator/SourceStubber/PhpStormStubsSourceStubber.php +++ b/src/SourceLocator/SourceStubber/PhpStormStubsSourceStubber.php @@ -52,7 +52,6 @@ /** @internal */ final class PhpStormStubsSourceStubber implements SourceStubber { - private const BUILDER_OPTIONS = ['shortArraySyntax' => true]; private const SEARCH_DIRECTORIES = [ __DIR__ . '/../../../../../jetbrains/phpstorm-stubs', __DIR__ . '/../../../vendor/jetbrains/phpstorm-stubs', @@ -178,10 +177,10 @@ final class PhpStormStubsSourceStubber implements SourceStubber /** @var array */ private static array $constantMap; - public function __construct(private Parser $phpParser, private int $phpVersion = PHP_VERSION_ID) + public function __construct(private Parser $phpParser, Standard $prettyPrinter, private int $phpVersion = PHP_VERSION_ID) { $this->builderFactory = new BuilderFactory(); - $this->prettyPrinter = new Standard(self::BUILDER_OPTIONS); + $this->prettyPrinter = $prettyPrinter; $this->cachingVisitor = new CachingVisitor($this->builderFactory); diff --git a/src/SourceLocator/SourceStubber/ReflectionSourceStubber.php b/src/SourceLocator/SourceStubber/ReflectionSourceStubber.php index 94cb77d15..00b2df1ab 100644 --- a/src/SourceLocator/SourceStubber/ReflectionSourceStubber.php +++ b/src/SourceLocator/SourceStubber/ReflectionSourceStubber.php @@ -64,16 +64,14 @@ */ final class ReflectionSourceStubber implements SourceStubber { - private const BUILDER_OPTIONS = ['shortArraySyntax' => true]; - private BuilderFactory $builderFactory; private Standard $prettyPrinter; - public function __construct() + public function __construct(Standard $prettyPrinter) { $this->builderFactory = new BuilderFactory(); - $this->prettyPrinter = new Standard(self::BUILDER_OPTIONS); + $this->prettyPrinter = $prettyPrinter; } /** @param class-string|trait-string $className */ diff --git a/test/unit/Reflection/ReflectionFunctionAbstractTest.php b/test/unit/Reflection/ReflectionFunctionAbstractTest.php index a9aa0ccd1..bede79bed 100644 --- a/test/unit/Reflection/ReflectionFunctionAbstractTest.php +++ b/test/unit/Reflection/ReflectionFunctionAbstractTest.php @@ -6,6 +6,7 @@ use PhpParser\Node\Stmt\Function_; use PhpParser\Parser; +use PhpParser\PrettyPrinter\Standard; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -38,13 +39,16 @@ class ReflectionFunctionAbstractTest extends TestCase private Locator $astLocator; + private Standard $prettyPrinter; + protected function setUp(): void { parent::setUp(); - $configuration = BetterReflectionSingleton::instance(); - $this->parser = $configuration->phpParser(); - $this->astLocator = $configuration->astLocator(); + $configuration = BetterReflectionSingleton::instance(); + $this->parser = $configuration->phpParser(); + $this->astLocator = $configuration->astLocator(); + $this->prettyPrinter = $configuration->printer(); } public function testNameMethodsWithNamespace(): void @@ -505,7 +509,7 @@ public function testGetNullableReturnTypeWithDeclaredType(string $functionToRefl public function testHasTentativeReturnType(): void { - $classInfo = (new DefaultReflector(new PhpInternalSourceLocator($this->astLocator, new ReflectionSourceStubber())))->reflectClass(CoreReflectionClass::class); + $classInfo = (new DefaultReflector(new PhpInternalSourceLocator($this->astLocator, new ReflectionSourceStubber($this->prettyPrinter))))->reflectClass(CoreReflectionClass::class); $methodInfo = $classInfo->getMethod('getName'); self::assertTrue($methodInfo->hasTentativeReturnType()); @@ -524,7 +528,7 @@ public function testHasNotTentativeReturnType(): void public function testGetTentativeReturnType(): void { - $classInfo = (new DefaultReflector(new PhpInternalSourceLocator($this->astLocator, new ReflectionSourceStubber())))->reflectClass(CoreReflectionClass::class); + $classInfo = (new DefaultReflector(new PhpInternalSourceLocator($this->astLocator, new ReflectionSourceStubber($this->prettyPrinter))))->reflectClass(CoreReflectionClass::class); $methodInfo = $classInfo->getMethod('getName'); $returnType = $methodInfo->getTentativeReturnType(); diff --git a/test/unit/SourceLocator/SourceStubber/PhpStormStubsSourceStubberTest.php b/test/unit/SourceLocator/SourceStubber/PhpStormStubsSourceStubberTest.php index 516ed69df..615f549be 100644 --- a/test/unit/SourceLocator/SourceStubber/PhpStormStubsSourceStubberTest.php +++ b/test/unit/SourceLocator/SourceStubber/PhpStormStubsSourceStubberTest.php @@ -16,6 +16,7 @@ use PDO; use PDOException; use PhpParser\Parser; +use PhpParser\PrettyPrinter\Standard; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -77,6 +78,8 @@ class PhpStormStubsSourceStubberTest extends TestCase private PhpStormStubsSourceStubber $sourceStubber; + private Standard $prettyPrinter; + private PhpInternalSourceLocator $phpInternalSourceLocator; private Reflector $reflector; @@ -99,7 +102,8 @@ protected function setUp(): void $this->phpParser = $betterReflection->phpParser(); $this->astLocator = $betterReflection->astLocator(); - $this->sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, PHP_VERSION_ID); + $this->prettyPrinter = $betterReflection->printer(); + $this->sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter, PHP_VERSION_ID); $this->phpInternalSourceLocator = new PhpInternalSourceLocator($this->astLocator, $this->sourceStubber); $this->reflector = new DefaultReflector($this->phpInternalSourceLocator); } @@ -611,7 +615,7 @@ public function testUpdateConstantValue(): void { require __DIR__ . '/../../Fixture/FakeConstants.php'; - $sourceStubber = new PhpStormStubsSourceStubber(BetterReflectionSingleton::instance()->phpParser()); + $sourceStubber = new PhpStormStubsSourceStubber(BetterReflectionSingleton::instance()->phpParser(), BetterReflectionSingleton::instance()->printer()); $stubberReflection = new CoreReflectionClass($sourceStubber); @@ -665,7 +669,7 @@ public static function dataClassInPhpVersion(): array #[DataProvider('dataClassInPhpVersion')] public function testClassInPhpVersion(string $className, int $phpVersion, bool $isSupported): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter, $phpVersion); $stub = $sourceStubber->generateClassStub($className); @@ -695,7 +699,7 @@ public static function dataClassConstantInPhpVersion(): array #[DataProvider('dataClassConstantInPhpVersion')] public function testClassConstantInPhpVersion(string $className, string $constantName, int $phpVersion, bool $isSupported): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $phpInternalSourceLocator = new PhpInternalSourceLocator($this->astLocator, $sourceStubber); $reflector = new DefaultReflector($phpInternalSourceLocator); @@ -740,7 +744,7 @@ public function testMethodInPhpVersion( string|null $returnType = null, string|null $tentativeReturnType = null, ): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $sourceLocator = new AggregateSourceLocator([ // We need to hack Stringable to make the test work new StringSourceLocator('astLocator), @@ -791,7 +795,7 @@ public function testMethodParameterInPhpVersion( string|null $type = null, bool|null $allowsNull = null, ): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $phpInternalSourceLocator = new PhpInternalSourceLocator($this->astLocator, $sourceStubber); $reflector = new DefaultReflector($phpInternalSourceLocator); @@ -830,7 +834,7 @@ public static function dataPropertyInPhpVersion(): array #[DataProvider('dataPropertyInPhpVersion')] public function testPropertyInPhpVersion(string $className, string $propertyName, int $phpVersion, bool $isSupported, string|null $type = null): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $phpInternalSourceLocator = new PhpInternalSourceLocator($this->astLocator, $sourceStubber); $reflector = new DefaultReflector($phpInternalSourceLocator); @@ -882,7 +886,7 @@ public static function dataFunctionInPhpVersion(): array #[DataProvider('dataFunctionInPhpVersion')] public function testFunctionInPhpVersion(string $functionName, int $phpVersion, bool $isSupported, string|null $returnType = null): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $phpInternalSourceLocator = new PhpInternalSourceLocator($this->astLocator, $sourceStubber); $reflector = new DefaultReflector($phpInternalSourceLocator); @@ -927,7 +931,7 @@ public function testFunctionParameterInPhpVersion( string|null $type = null, bool|null $allowsNull = null, ): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $phpInternalSourceLocator = new PhpInternalSourceLocator($this->astLocator, $sourceStubber); $reflector = new DefaultReflector($phpInternalSourceLocator); @@ -965,7 +969,7 @@ public static function dataConstantInPhpVersion(): array #[DataProvider('dataConstantInPhpVersion')] public function testConstantInPhpVersion(string $constantName, int $phpVersion, bool $isSupported): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $stub = $sourceStubber->generateConstantStub($constantName); @@ -990,7 +994,7 @@ public static function dataClassIsDeprecatedInPhpVersion(): array #[DataProvider('dataClassIsDeprecatedInPhpVersion')] public function testClassIsDeprecatedInPhpVersion(string $className, int $phpVersion, bool $isDeprecated): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $reflector = new DefaultReflector(new PhpInternalSourceLocator($this->astLocator, $sourceStubber)); $classReflection = $reflector->reflectClass($className); @@ -1013,7 +1017,7 @@ public static function dataClassConstantIsDeprecatedInPhpVersion(): array #[DataProvider('dataClassConstantIsDeprecatedInPhpVersion')] public function testClassConstantIsDeprecatedInPhpVersion(string $className, string $constantName, int $phpVersion, bool $isDeprecated): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $reflector = new DefaultReflector(new PhpInternalSourceLocator($this->astLocator, $sourceStubber)); $classReflection = $reflector->reflectClass($className); @@ -1037,7 +1041,7 @@ public static function dataMethodIsDeprecatedInPhpVersion(): array #[DataProvider('dataMethodIsDeprecatedInPhpVersion')] public function testMethodIsDeprecatedInPhpVersion(string $className, string $methodName, int $phpVersion, bool $isDeprecated): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $sourceLocator = new AggregateSourceLocator([ // We need to hack Stringable to make the test work new StringSourceLocator('astLocator), @@ -1066,7 +1070,7 @@ public static function dataPropertyIsDeprecatedInPhpVersion(): array #[DataProvider('dataPropertyIsDeprecatedInPhpVersion')] public function testPropertyIsDeprecatedInPhpVersion(string $className, string $propertyName, int $phpVersion, bool $isDeprecated): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $reflector = new DefaultReflector(new PhpInternalSourceLocator($this->astLocator, $sourceStubber)); $classReflection = $reflector->reflectClass($className); @@ -1093,7 +1097,7 @@ public static function dataFunctionIsDeprecatedInPhpVersion(): array #[DataProvider('dataFunctionIsDeprecatedInPhpVersion')] public function testFunctionIsDeprecatedInPhpVersion(string $functionName, int $phpVersion, bool $isDeprecated): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $reflector = new DefaultReflector(new PhpInternalSourceLocator($this->astLocator, $sourceStubber)); $functionReflection = $reflector->reflectFunction($functionName); @@ -1190,7 +1194,7 @@ public function testImmediateInterfaces( array $interfaceNames, int $phpVersion, ): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $phpInternalSourceLocator = new PhpInternalSourceLocator($this->astLocator, $sourceStubber); $reflector = new DefaultReflector($phpInternalSourceLocator); $class = $reflector->reflectClass($className); @@ -1226,7 +1230,7 @@ public function testSubclass( string $subclassName, int $phpVersion, ): void { - $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $phpVersion); + $sourceStubber = new PhpStormStubsSourceStubber($this->phpParser, $this->prettyPrinter,$phpVersion); $phpInternalSourceLocator = new PhpInternalSourceLocator($this->astLocator, $sourceStubber); $reflector = new DefaultReflector($phpInternalSourceLocator); $class = $reflector->reflectClass($className); diff --git a/test/unit/SourceLocator/SourceStubber/ReflectionSourceStubberTest.php b/test/unit/SourceLocator/SourceStubber/ReflectionSourceStubberTest.php index f7917c9bb..1bfb9c658 100644 --- a/test/unit/SourceLocator/SourceStubber/ReflectionSourceStubberTest.php +++ b/test/unit/SourceLocator/SourceStubber/ReflectionSourceStubberTest.php @@ -65,7 +65,7 @@ protected function setUp(): void { parent::setUp(); - $this->stubber = new ReflectionSourceStubber(); + $this->stubber = new ReflectionSourceStubber(BetterReflectionSingleton::instance()->printer()); $this->phpInternalSourceLocator = new PhpInternalSourceLocator( BetterReflectionSingleton::instance()->astLocator(), $this->stubber,