Skip to content

Commit c95120d

Browse files
Merge branch '7.2' into 7.3
* 7.2: [VarExporter] Fix support for hooks and asymmetric visibility [TypeInfo] Fix promoted property with `@var` tag fix(process): use a pipe for stderr in pty mode to avoid mixed output between stdout and stderr [Cache] fix data collector
2 parents 64fcb41 + 9f7257e commit c95120d

25 files changed

+299
-151
lines changed

src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public function lateCollect(): void
6060

6161
$this->data['instances']['statistics'] = $this->calculateStatistics();
6262
$this->data['total']['statistics'] = $this->calculateTotalStatistics();
63+
$this->data['instances']['calls'] = $this->cloneVar($this->data['instances']['calls']);
6364
}
6465

6566
public function getName(): string

src/Symfony/Component/Cache/Tests/DataCollector/CacheDataCollectorTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\Cache\DataCollector\CacheDataCollector;
1818
use Symfony\Component\HttpFoundation\Request;
1919
use Symfony\Component\HttpFoundation\Response;
20+
use Symfony\Component\VarDumper\Cloner\Data;
2021

2122
class CacheDataCollectorTest extends TestCase
2223
{
@@ -122,6 +123,7 @@ public function testLateCollect()
122123
$this->assertEquals($stats[self::INSTANCE_NAME]['hits'], 0, 'hits');
123124
$this->assertEquals($stats[self::INSTANCE_NAME]['misses'], 1, 'misses');
124125
$this->assertEquals($stats[self::INSTANCE_NAME]['calls'], 1, 'calls');
126+
$this->assertInstanceOf(Data::class, $collector->getCalls());
125127
}
126128

127129
private function getCacheDataCollectorStatisticsFromEvents(array $traceableAdapterEvents)

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_wither_lazy.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class WitherProxy1991f2a extends \Symfony\Component\DependencyInjection\Tests\Co
7676
use \Symfony\Component\VarExporter\LazyProxyTrait;
7777

7878
private const LAZY_OBJECT_PROPERTY_SCOPES = [
79-
'foo' => [parent::class, 'foo', null],
79+
'foo' => [parent::class, 'foo', null, 4],
8080
];
8181
}
8282

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_wither_lazy_non_shared.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class WitherProxyE94fdba extends \Symfony\Component\DependencyInjection\Tests\Co
7878
use \Symfony\Component\VarExporter\LazyProxyTrait;
7979

8080
private const LAZY_OBJECT_PROPERTY_SCOPES = [
81-
'foo' => [parent::class, 'foo', null],
81+
'foo' => [parent::class, 'foo', null, 4],
8282
];
8383
}
8484

src/Symfony/Component/DependencyInjection/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"psr/container": "^1.1|^2.0",
2121
"symfony/deprecation-contracts": "^2.5|^3",
2222
"symfony/service-contracts": "^3.5",
23-
"symfony/var-exporter": "^6.4|^7.0"
23+
"symfony/var-exporter": "^6.4.20|^7.2.5"
2424
},
2525
"require-dev": {
2626
"symfony/yaml": "^6.4|^7.0",

src/Symfony/Component/Process/Pipes/UnixPipes.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public function getDescriptors(): array
7070
return [
7171
['pty'],
7272
['pty'],
73-
['pty'],
73+
['pipe', 'w'], // stderr needs to be in a pipe to correctly split error and output, since PHP will use the same stream for both
7474
];
7575
}
7676

src/Symfony/Component/Process/Tests/ProcessTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,20 @@ public function testExitCodeTextIsNullWhenExitCodeIsNull()
559559
$this->assertNull($process->getExitCodeText());
560560
}
561561

562+
public function testStderrNotMixedWithStdout()
563+
{
564+
if (!Process::isPtySupported()) {
565+
$this->markTestSkipped('PTY is not supported on this operating system.');
566+
}
567+
568+
$process = $this->getProcess('echo "foo" && echo "bar" >&2');
569+
$process->setPty(true);
570+
$process->run();
571+
572+
$this->assertSame("foo\r\n", $process->getOutput());
573+
$this->assertSame("bar\n", $process->getErrorOutput());
574+
}
575+
562576
public function testPTYCommand()
563577
{
564578
if (!Process::isPtySupported()) {

src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyWithPhpDoc.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,18 @@ final class DummyWithPhpDoc
2929

3030
/**
3131
* @param bool $promoted
32+
* @param bool $promotedVarAndParam
3233
*/
3334
public function __construct(
3435
public mixed $promoted,
36+
/**
37+
* @var string
38+
*/
39+
public mixed $promotedVar,
40+
/**
41+
* @var string
42+
*/
43+
public mixed $promotedVarAndParam,
3544
) {
3645
}
3746

src/Symfony/Component/TypeInfo/Tests/TypeResolver/PhpDocAwareReflectionTypeResolverTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ public static function readPhpDocDataProvider(): iterable
4141

4242
yield [Type::array(Type::object(Dummy::class)), $reflection->getProperty('arrayOfDummies')];
4343
yield [Type::bool(), $reflection->getProperty('promoted')];
44+
yield [Type::string(), $reflection->getProperty('promotedVar')];
45+
yield [Type::string(), $reflection->getProperty('promotedVarAndParam')];
4446
yield [Type::object(Dummy::class), $reflection->getMethod('getNextDummy')];
4547
yield [Type::object(Dummy::class), $reflection->getMethod('getNextDummy')->getParameters()[0]];
4648
yield [Type::int(), $reflection->getProperty('aliasedInt')];

src/Symfony/Component/TypeInfo/TypeResolver/PhpDocAwareReflectionTypeResolver.php

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -64,36 +64,38 @@ public function resolve(mixed $subject, ?TypeContext $typeContext = null): Type
6464
throw new UnsupportedException(\sprintf('Expected subject to be a "ReflectionProperty", a "ReflectionParameter" or a "ReflectionFunctionAbstract", "%s" given.', get_debug_type($subject)), $subject);
6565
}
6666

67-
$docComment = match (true) {
68-
$subject instanceof \ReflectionProperty => $subject->isPromoted() ? $subject->getDeclaringClass()?->getConstructor()?->getDocComment() : $subject->getDocComment(),
69-
$subject instanceof \ReflectionParameter => $subject->getDeclaringFunction()->getDocComment(),
70-
$subject instanceof \ReflectionFunctionAbstract => $subject->getDocComment(),
67+
$typeContext ??= $this->typeContextFactory->createFromReflection($subject);
68+
69+
$docComments = match (true) {
70+
$subject instanceof \ReflectionProperty => $subject->isPromoted()
71+
? ['@var' => $subject->getDocComment(), '@param' => $subject->getDeclaringClass()?->getConstructor()?->getDocComment()]
72+
: ['@var' => $subject->getDocComment()],
73+
$subject instanceof \ReflectionParameter => ['@param' => $subject->getDeclaringFunction()->getDocComment()],
74+
$subject instanceof \ReflectionFunctionAbstract => ['@return' => $subject->getDocComment()],
7175
};
7276

73-
if (!$docComment) {
74-
return $this->reflectionTypeResolver->resolve($subject);
75-
}
77+
foreach ($docComments as $tagName => $docComment) {
78+
if (!$docComment) {
79+
continue;
80+
}
7681

77-
$typeContext ??= $this->typeContextFactory->createFromReflection($subject);
82+
$tokens = new TokenIterator($this->lexer->tokenize($docComment));
83+
$docNode = $this->phpDocParser->parse($tokens);
7884

79-
$tagName = match (true) {
80-
$subject instanceof \ReflectionProperty => $subject->isPromoted() ? '@param' : '@var',
81-
$subject instanceof \ReflectionParameter => '@param',
82-
$subject instanceof \ReflectionFunctionAbstract => '@return',
83-
};
85+
foreach ($docNode->getTagsByName($tagName) as $tag) {
86+
$tagValue = $tag->value;
8487

85-
$tokens = new TokenIterator($this->lexer->tokenize($docComment));
86-
$docNode = $this->phpDocParser->parse($tokens);
88+
if ('@var' === $tagName && $tagValue instanceof VarTagValueNode) {
89+
return $this->stringTypeResolver->resolve((string) $tagValue, $typeContext);
90+
}
8791

88-
foreach ($docNode->getTagsByName($tagName) as $tag) {
89-
$tagValue = $tag->value;
92+
if ('@param' === $tagName && $tagValue instanceof ParamTagValueNode && '$'.$subject->getName() === $tagValue->parameterName) {
93+
return $this->stringTypeResolver->resolve((string) $tagValue, $typeContext);
94+
}
9095

91-
if (
92-
$tagValue instanceof VarTagValueNode
93-
|| $tagValue instanceof ParamTagValueNode && $tagName && '$'.$subject->getName() === $tagValue->parameterName
94-
|| $tagValue instanceof ReturnTagValueNode
95-
) {
96-
return $this->stringTypeResolver->resolve((string) $tagValue, $typeContext);
96+
if ('@return' === $tagName && $tagValue instanceof ReturnTagValueNode) {
97+
return $this->stringTypeResolver->resolve((string) $tagValue, $typeContext);
98+
}
9799
}
98100
}
99101

0 commit comments

Comments
 (0)