From 89c89c9776795ae46923e3a27f7e60175188113c Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Fri, 25 Jan 2019 20:28:19 +0100 Subject: [PATCH] [Debug][DebugClassLoader] Match callable() type for parameters not defined in sub classes --- src/Symfony/Component/Debug/DebugClassLoader.php | 4 ++-- .../Component/Debug/Tests/DebugClassLoaderTest.php | 5 +++++ .../Fixtures/InterfaceWithAnnotatedParameters.php | 13 +++++++++++++ .../Fixtures/SubClassWithAnnotatedParameters.php | 8 ++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Debug/DebugClassLoader.php b/src/Symfony/Component/Debug/DebugClassLoader.php index efc52a2fd6..88da8fc3bb 100644 --- a/src/Symfony/Component/Debug/DebugClassLoader.php +++ b/src/Symfony/Component/Debug/DebugClassLoader.php @@ -352,7 +352,7 @@ class DebugClassLoader } foreach (self::$annotatedParameters[$class][$method->name] as $parameterName => $deprecation) { - if (!isset($definedParameters[$parameterName]) && !($doc && preg_match("/\\n\\s+\\* @param (.*?)(?<= )\\\${$parameterName}\\b/", $doc))) { + if (!isset($definedParameters[$parameterName]) && !($doc && preg_match("/\\n\\s+\\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\\\${$parameterName}\\b/", $doc))) { $deprecations[] = sprintf($deprecation, $class); } } @@ -375,7 +375,7 @@ class DebugClassLoader if ($finalOrInternal || $method->isConstructor() || false === \strpos($doc, '@param') || StatelessInvocation::class === $class) { continue; } - if (!preg_match_all('#\n\s+\* @param (.*?)(?<= )\$([a-zA-Z0-9_\x7f-\xff]++)#', $doc, $matches, PREG_SET_ORDER)) { + if (!preg_match_all('#\n\s+\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\$([a-zA-Z0-9_\x7f-\xff]++)#', $doc, $matches, PREG_SET_ORDER)) { continue; } if (!isset(self::$annotatedParameters[$class][$method->name])) { diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index d9852ade60..943b84fe27 100644 --- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -287,6 +287,11 @@ class DebugClassLoaderTest extends TestCase $this->assertSame([ 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::quzMethod()" method will require a new "Quz $quz" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\ClassWithAnnotatedParameters", not defining it is deprecated.', 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::whereAmI()" method will require a new "bool $matrix" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.', + 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "$noType" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.', + 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "callable(\Throwable|null $reason, mixed $value) $callback" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.', + 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "string $param" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.', + 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "callable ($a, $b) $anotherOne" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.', + 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "Type$WithDollarIsStillAType $ccc" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.', 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::isSymfony()" method will require a new "true $yes" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\ClassWithAnnotatedParameters", not defining it is deprecated.', ], $deprecations); } diff --git a/src/Symfony/Component/Debug/Tests/Fixtures/InterfaceWithAnnotatedParameters.php b/src/Symfony/Component/Debug/Tests/Fixtures/InterfaceWithAnnotatedParameters.php index 54abd68efa..86593db124 100644 --- a/src/Symfony/Component/Debug/Tests/Fixtures/InterfaceWithAnnotatedParameters.php +++ b/src/Symfony/Component/Debug/Tests/Fixtures/InterfaceWithAnnotatedParameters.php @@ -11,4 +11,17 @@ interface InterfaceWithAnnotatedParameters * @param bool $matrix */ public function whereAmI(); + + /** + * @param $noType + * @param callable(\Throwable|null $reason, mixed $value) $callback and a comment + * about this great param + * @param string $param (comment with $dollar) + * @param $defined + * @param callable ($a, $b) $anotherOne + * @param callable (mixed $a, $b) $definedCallable + * @param Type$WithDollarIsStillAType $ccc + * @param \JustAType + */ + public function iAmHere(); } diff --git a/src/Symfony/Component/Debug/Tests/Fixtures/SubClassWithAnnotatedParameters.php b/src/Symfony/Component/Debug/Tests/Fixtures/SubClassWithAnnotatedParameters.php index 20358e96de..5d05d79835 100644 --- a/src/Symfony/Component/Debug/Tests/Fixtures/SubClassWithAnnotatedParameters.php +++ b/src/Symfony/Component/Debug/Tests/Fixtures/SubClassWithAnnotatedParameters.php @@ -21,4 +21,12 @@ class SubClassWithAnnotatedParameters extends ClassWithAnnotatedParameters imple public function whereAmI() { } + + /** + * @param $defined + * @param Type\Does\Not\Matter $definedCallable + */ + public function iAmHere() + { + } }