Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ca66e6c

Browse filesBrowse files
minor #37003 [PropertyAccess] Fix TypeError parsing again (derrabus)
This PR was merged into the 3.4 branch. Discussion ---------- [PropertyAccess] Fix TypeError parsing again | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | #36872 | License | MIT | Doc PR | N/A Apparently, the format of `TypeError`s has changed again in php8. While investigating, I noticed our error message parsing is not handling anonymous classes well, so I've added some test cases for them. I chose a fuzzier regular expression to parse the expected return type from the error message. Additionally, I'm checking the stack trace if the caught `TypeError` is really caused by the accessor call. Commits ------- 03b4e98 [PropertyAccess] Fix TypeError parsing again.
2 parents 2e8ae40 + 03b4e98 commit ca66e6c
Copy full SHA for ca66e6c

File tree

Expand file treeCollapse file tree

2 files changed

+61
-2
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+61
-2
lines changed

‎src/Symfony/Component/PropertyAccess/PropertyAccessor.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyAccess/PropertyAccessor.php
+8-2Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,9 +479,15 @@ private function readProperty($zval, $property)
479479
try {
480480
$result[self::VALUE] = $object->{$access[self::ACCESS_NAME]}();
481481
} catch (\TypeError $e) {
482+
list($trace) = $e->getTrace();
483+
482484
// handle uninitialized properties in PHP >= 7
483-
if (preg_match((sprintf('/^Return value of %s::%s\(\) must be of (?:the )?type (\w+), null returned$/', preg_quote(\get_class($object)), $access[self::ACCESS_NAME])), $e->getMessage(), $matches)) {
484-
throw new AccessException(sprintf('The method "%s::%s()" returned "null", but expected type "%3$s". Did you forget to initialize a property or to make the return type nullable using "?%3$s"?', \get_class($object), $access[self::ACCESS_NAME], $matches[1]), 0, $e);
485+
if (__FILE__ === $trace['file']
486+
&& $access[self::ACCESS_NAME] === $trace['function']
487+
&& $object instanceof $trace['class']
488+
&& preg_match((sprintf('/Return value (?:of .*::\w+\(\) )?must be of (?:the )?type (\w+), null returned$/')), $e->getMessage(), $matches)
489+
) {
490+
throw new AccessException(sprintf('The method "%s::%s()" returned "null", but expected type "%3$s". Did you forget to initialize a property or to make the return type nullable using "?%3$s"?', false === strpos(\get_class($object), "@anonymous\0") ? \get_class($object) : (get_parent_class($object) ?: 'class').'@anonymous', $access[self::ACCESS_NAME], $matches[1]), 0, $e);
485491
}
486492

487493
throw $e;

‎src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
+53Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,59 @@ public function testGetValueThrowsExceptionIfUninitializedPropertyWithGetter()
142142
$this->propertyAccessor->getValue(new UninitializedPrivateProperty(), 'uninitialized');
143143
}
144144

145+
/**
146+
* @requires PHP 7
147+
*/
148+
public function testGetValueThrowsExceptionIfUninitializedPropertyWithGetterOfAnonymousClass()
149+
{
150+
$this->expectException('Symfony\Component\PropertyAccess\Exception\AccessException');
151+
$this->expectExceptionMessage('The method "class@anonymous::getUninitialized()" returned "null", but expected type "array". Did you forget to initialize a property or to make the return type nullable using "?array"?');
152+
153+
$object = eval('return new class() {
154+
private $uninitialized;
155+
156+
public function getUninitialized(): array
157+
{
158+
return $this->uninitialized;
159+
}
160+
};');
161+
162+
$this->propertyAccessor->getValue($object, 'uninitialized');
163+
}
164+
165+
/**
166+
* @requires PHP 7
167+
*/
168+
public function testGetValueThrowsExceptionIfUninitializedPropertyWithGetterOfAnonymousStdClass()
169+
{
170+
$this->expectException('Symfony\Component\PropertyAccess\Exception\AccessException');
171+
$this->expectExceptionMessage('The method "stdClass@anonymous::getUninitialized()" returned "null", but expected type "array". Did you forget to initialize a property or to make the return type nullable using "?array"?');
172+
173+
$object = eval('return new class() extends \stdClass {
174+
private $uninitialized;
175+
176+
public function getUninitialized(): array
177+
{
178+
return $this->uninitialized;
179+
}
180+
};');
181+
182+
$this->propertyAccessor->getValue($object, 'uninitialized');
183+
}
184+
185+
/**
186+
* @requires PHP 7
187+
*/
188+
public function testGetValueThrowsExceptionIfUninitializedPropertyWithGetterOfAnonymousChildClass()
189+
{
190+
$this->expectException('Symfony\Component\PropertyAccess\Exception\AccessException');
191+
$this->expectExceptionMessage('The method "Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedPrivateProperty@anonymous::getUninitialized()" returned "null", but expected type "array". Did you forget to initialize a property or to make the return type nullable using "?array"?');
192+
193+
$object = eval('return new class() extends \Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedPrivateProperty {};');
194+
195+
$this->propertyAccessor->getValue($object, 'uninitialized');
196+
}
197+
145198
public function testGetValueThrowsExceptionIfNotArrayAccess()
146199
{
147200
$this->expectException('Symfony\Component\PropertyAccess\Exception\NoSuchIndexException');

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.