bug #34560 [Config][ReflectionClassResource] Handle parameters with undefined constant as their default values (fancyweb)

This PR was merged into the 3.4 branch.

Discussion
----------

[Config][ReflectionClassResource] Handle parameters with undefined constant as their default values

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | https://github.com/symfony/symfony/issues/34053
| License       | MIT
| Doc PR        | -

Basically we can fix this bug by "reimplementing" php src way of building the __toString() of the method except that we avoid to call the undefined constant. Obviously we cannot invalidate the resource if the value of the constant changes since we never knew it. However, it's still better than now.

Commits
-------

8de2a226a8 [Config][ReflectionClassResource] Handle parameters with undefined constant as their default values
This commit is contained in:
Nicolas Grekas 2019-11-29 17:06:11 +01:00
commit 9eafff5ec0
2 changed files with 62 additions and 6 deletions

View File

@ -151,12 +151,56 @@ class ReflectionClassResource implements SelfCheckingResourceInterface, \Seriali
}
} else {
foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) {
yield preg_replace('/^ @@.*/m', '', $m);
$defaults = [];
$parametersWithUndefinedConstants = [];
foreach ($m->getParameters() as $p) {
$defaults[$p->name] = $p->isDefaultValueAvailable() ? $p->getDefaultValue() : null;
if (!$p->isDefaultValueAvailable()) {
$defaults[$p->name] = null;
continue;
}
if (!$p->isDefaultValueConstant() || \defined($p->getDefaultValueConstantName())) {
$defaults[$p->name] = $p->getDefaultValue();
continue;
}
$defaults[$p->name] = $p->getDefaultValueConstantName();
$parametersWithUndefinedConstants[$p->name] = true;
}
if (!$parametersWithUndefinedConstants) {
yield preg_replace('/^ @@.*/m', '', $m);
} else {
$stack = [
$m->getDocComment(),
$m->getName(),
$m->isAbstract(),
$m->isFinal(),
$m->isStatic(),
$m->isPublic(),
$m->isPrivate(),
$m->isProtected(),
$m->returnsReference(),
\PHP_VERSION_ID >= 70000 && $m->hasReturnType() ? (\PHP_VERSION_ID >= 70100 ? $m->getReturnType()->getName() : (string) $m->getReturnType()) : '',
];
foreach ($m->getParameters() as $p) {
if (!isset($parametersWithUndefinedConstants[$p->name])) {
$stack[] = (string) $p;
} else {
$stack[] = $p->isOptional();
$stack[] = \PHP_VERSION_ID >= 70000 && $p->hasType() ? (\PHP_VERSION_ID >= 70100 ? $p->getType()->getName() : (string) $p->getType()) : '';
$stack[] = $p->isPassedByReference();
$stack[] = \PHP_VERSION_ID >= 50600 ? $p->isVariadic() : '';
$stack[] = $p->getName();
}
}
yield implode(',', $stack);
}
yield print_r($defaults, true);
}
}

View File

@ -63,8 +63,12 @@ class ReflectionClassResourceTest extends TestCase
/**
* @dataProvider provideHashedSignature
*/
public function testHashedSignature($changeExpected, $changedLine, $changedCode)
public function testHashedSignature($changeExpected, $changedLine, $changedCode, $setContext = null)
{
if ($setContext) {
$setContext();
}
$code = <<<'EOPHP'
/* 0*/
/* 1*/ class %s extends ErrorException
@ -82,7 +86,9 @@ class ReflectionClassResourceTest extends TestCase
/*13*/ protected function prot($a = []) {}
/*14*/
/*15*/ private function priv() {}
/*16*/ }
/*16*/
/*17*/ public function ccc($bar = A_CONSTANT_THAT_FOR_SURE_WILL_NEVER_BE_DEFINED_CCCCCC) {}
/*18*/ }
EOPHP;
static $expectedSignature, $generateSignature;
@ -97,7 +103,9 @@ EOPHP;
}
$code = explode("\n", $code);
$code[$changedLine] = $changedCode;
if (null !== $changedCode) {
$code[$changedLine] = $changedCode;
}
eval(sprintf(implode("\n", $code), $class = 'Foo'.str_replace('.', '_', uniqid('', true))));
$signature = implode("\n", iterator_to_array($generateSignature(new \ReflectionClass($class))));
@ -145,6 +153,10 @@ EOPHP;
yield [0, 7, 'protected int $prot;'];
yield [0, 9, 'private string $priv;'];
}
yield [1, 17, 'public function ccc($bar = 187) {}'];
yield [1, 17, 'public function ccc($bar = ANOTHER_ONE_THAT_WILL_NEVER_BE_DEFINED_CCCCCCCCC) {}'];
yield [1, 17, null, static function () { \define('A_CONSTANT_THAT_FOR_SURE_WILL_NEVER_BE_DEFINED_CCCCCC', 'foo'); }];
}
public function testEventSubscriber()