[ErrorHandler] don't throw deprecations for return-types by default
This commit is contained in:
parent
373469b53f
commit
2cb419edf4
3
.github/patch-types.php
vendored
3
.github/patch-types.php
vendored
@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
if (false === getenv('SYMFONY_PATCH_TYPE_DECLARATIONS')) {
|
if (false === getenv('SYMFONY_PATCH_TYPE_DECLARATIONS')) {
|
||||||
putenv('SYMFONY_PATCH_TYPE_DECLARATIONS=force=1&php71-compat=0');
|
echo "Please define the SYMFONY_PATCH_TYPE_DECLARATIONS env var when running this script.\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
require __DIR__.'/../.phpunit/phpunit-8.3-0/vendor/autoload.php';
|
require __DIR__.'/../.phpunit/phpunit-8.3-0/vendor/autoload.php';
|
||||||
|
@ -22,6 +22,7 @@ env:
|
|||||||
- MESSENGER_AMQP_DSN=amqp://localhost/%2f/messages
|
- MESSENGER_AMQP_DSN=amqp://localhost/%2f/messages
|
||||||
- MESSENGER_REDIS_DSN=redis://127.0.0.1:7001/messages
|
- MESSENGER_REDIS_DSN=redis://127.0.0.1:7001/messages
|
||||||
- SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE=1
|
- SYMFONY_PHPUNIT_DISABLE_RESULT_CACHE=1
|
||||||
|
- SYMFONY_PATCH_TYPE_DECLARATIONS=force=0
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
@ -298,6 +299,7 @@ install:
|
|||||||
ln -sd $(realpath src/Symfony/Contracts) vendor/symfony/contracts
|
ln -sd $(realpath src/Symfony/Contracts) vendor/symfony/contracts
|
||||||
sed -i 's/"\*\*\/Tests\/"//' composer.json
|
sed -i 's/"\*\*\/Tests\/"//' composer.json
|
||||||
composer install --optimize-autoloader
|
composer install --optimize-autoloader
|
||||||
|
export SYMFONY_PATCH_TYPE_DECLARATIONS=force=object
|
||||||
php .github/patch-types.php
|
php .github/patch-types.php
|
||||||
php .github/patch-types.php # ensure the script is idempotent
|
php .github/patch-types.php # ensure the script is idempotent
|
||||||
PHPUNIT_X="$PHPUNIT_X,legacy"
|
PHPUNIT_X="$PHPUNIT_X,legacy"
|
||||||
|
@ -24,6 +24,19 @@ use ProxyManager\Proxy\ProxyInterface;
|
|||||||
* and will throw an exception if a file is found but does
|
* and will throw an exception if a file is found but does
|
||||||
* not declare the class.
|
* not declare the class.
|
||||||
*
|
*
|
||||||
|
* It can also patch classes to turn docblocks into actual return types.
|
||||||
|
* This behavior is controlled by the SYMFONY_PATCH_TYPE_DECLARATIONS env var,
|
||||||
|
* which is a url-encoded array with the follow parameters:
|
||||||
|
* - force: any value enables deprecation notices - can be any of:
|
||||||
|
* - "docblock" to patch only docblock annotations
|
||||||
|
* - "object" to turn union types to the "object" type when possible (not recommended)
|
||||||
|
* - "1"/"0" to enable/disable patching of return types
|
||||||
|
* - php: the target version of PHP - e.g. "7.1" doesn't generate "object" types
|
||||||
|
*
|
||||||
|
* Note that patching doesn't care about any coding style so you'd better to run
|
||||||
|
* php-cs-fixer after, with rules "phpdoc_trim_consecutive_blank_line_separation"
|
||||||
|
* and "no_superfluous_phpdoc_tags" enabled typically.
|
||||||
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
* @author Christophe Coevoet <stof@notk.org>
|
* @author Christophe Coevoet <stof@notk.org>
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
@ -141,6 +154,7 @@ class DebugClassLoader
|
|||||||
private $isFinder;
|
private $isFinder;
|
||||||
private $loaded = [];
|
private $loaded = [];
|
||||||
private $patchTypes;
|
private $patchTypes;
|
||||||
|
|
||||||
private static $caseCheck;
|
private static $caseCheck;
|
||||||
private static $checkedClasses = [];
|
private static $checkedClasses = [];
|
||||||
private static $final = [];
|
private static $final = [];
|
||||||
@ -160,6 +174,10 @@ class DebugClassLoader
|
|||||||
$this->classLoader = $classLoader;
|
$this->classLoader = $classLoader;
|
||||||
$this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile');
|
$this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile');
|
||||||
parse_str(getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?: '', $this->patchTypes);
|
parse_str(getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?: '', $this->patchTypes);
|
||||||
|
$this->patchTypes += [
|
||||||
|
'force' => null,
|
||||||
|
'php' => null,
|
||||||
|
];
|
||||||
|
|
||||||
if (!isset(self::$caseCheck)) {
|
if (!isset(self::$caseCheck)) {
|
||||||
$file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR);
|
$file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR);
|
||||||
@ -551,15 +569,14 @@ class DebugClassLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$forcePatchTypes = $this->patchTypes['force'] ?? null;
|
$forcePatchTypes = $this->patchTypes['force'];
|
||||||
|
|
||||||
if ($canAddReturnType = null !== $forcePatchTypes && false === strpos($method->getFileName(), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) {
|
if ($canAddReturnType = $forcePatchTypes && false === strpos($method->getFileName(), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) {
|
||||||
if ('void' !== (self::MAGIC_METHODS[$method->name] ?? 'void')) {
|
if ('void' !== (self::MAGIC_METHODS[$method->name] ?? 'void')) {
|
||||||
$this->patchTypes['force'] = $forcePatchTypes ?: 'docblock';
|
$this->patchTypes['force'] = $forcePatchTypes ?: 'docblock';
|
||||||
}
|
}
|
||||||
|
|
||||||
$canAddReturnType = ($this->patchTypes['force'] ?? false)
|
$canAddReturnType = false !== strpos($refl->getFileName(), \DIRECTORY_SEPARATOR.'Tests'.\DIRECTORY_SEPARATOR)
|
||||||
|| false !== strpos($refl->getFileName(), \DIRECTORY_SEPARATOR.'Tests'.\DIRECTORY_SEPARATOR)
|
|
||||||
|| $refl->isFinal()
|
|| $refl->isFinal()
|
||||||
|| $method->isFinal()
|
|| $method->isFinal()
|
||||||
|| $method->isPrivate()
|
|| $method->isPrivate()
|
||||||
@ -570,20 +587,20 @@ class DebugClassLoader
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (null !== ($returnType = self::$returnTypes[$class][$method->name] ?? self::MAGIC_METHODS[$method->name] ?? null) && !$method->hasReturnType() && !($doc && preg_match('/\n\s+\* @return +(\S+)/', $doc))) {
|
if (null !== ($returnType = self::$returnTypes[$class][$method->name] ?? self::MAGIC_METHODS[$method->name] ?? null) && !$method->hasReturnType() && !($doc && preg_match('/\n\s+\* @return +(\S+)/', $doc))) {
|
||||||
if ('void' === $returnType) {
|
list($normalizedType, $returnType, $declaringClass, $declaringFile) = \is_string($returnType) ? [$returnType, $returnType, '', ''] : $returnType;
|
||||||
|
|
||||||
|
if ('void' === $normalizedType) {
|
||||||
$canAddReturnType = false;
|
$canAddReturnType = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
list($normalizedType, $returnType, $declaringClass, $declaringFile) = \is_string($returnType) ? [$returnType, $returnType, '', ''] : $returnType;
|
if ($canAddReturnType && 'docblock' !== $this->patchTypes['force']) {
|
||||||
|
|
||||||
if ($canAddReturnType && 'docblock' !== ($this->patchTypes['force'] ?? false)) {
|
|
||||||
$this->patchMethod($method, $returnType, $declaringFile, $normalizedType);
|
$this->patchMethod($method, $returnType, $declaringFile, $normalizedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp($ns, $declaringClass, $len)) {
|
if (strncmp($ns, $declaringClass, $len)) {
|
||||||
if ($canAddReturnType && 'docblock' === ($this->patchTypes['force'] ?? false) && false === strpos($method->getFileName(), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) {
|
if ($canAddReturnType && 'docblock' === $this->patchTypes['force'] && false === strpos($method->getFileName(), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) {
|
||||||
$this->patchMethod($method, $returnType, $declaringFile, $normalizedType);
|
$this->patchMethod($method, $returnType, $declaringFile, $normalizedType);
|
||||||
} elseif ('' !== $declaringClass) {
|
} elseif ('' !== $declaringClass && null !== $this->patchTypes['force']) {
|
||||||
$deprecations[] = sprintf('Method "%s::%s()" will return "%s" as of its next major version. Doing the same in child class "%s" will be required when upgrading.', $declaringClass, $method->name, $normalizedType, $className);
|
$deprecations[] = sprintf('Method "%s::%s()" will return "%s" as of its next major version. Doing the same in child class "%s" will be required when upgrading.', $declaringClass, $method->name, $normalizedType, $className);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -820,7 +837,7 @@ class DebugClassLoader
|
|||||||
} elseif ($n !== $normalizedType || !preg_match('/^\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $n)) {
|
} elseif ($n !== $normalizedType || !preg_match('/^\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $n)) {
|
||||||
if ($iterable) {
|
if ($iterable) {
|
||||||
$normalizedType = $returnType = 'iterable';
|
$normalizedType = $returnType = 'iterable';
|
||||||
} elseif ($object) {
|
} elseif ($object && 'object' === $this->patchTypes['force']) {
|
||||||
$normalizedType = $returnType = 'object';
|
$normalizedType = $returnType = 'object';
|
||||||
} else {
|
} else {
|
||||||
// ignore multi-types return declarations
|
// ignore multi-types return declarations
|
||||||
@ -947,7 +964,7 @@ class DebugClassLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('docblock' === ($this->patchTypes['force'] ?? null) || ('object' === $normalizedType && ($this->patchTypes['php71-compat'] ?? false))) {
|
if ('docblock' === $this->patchTypes['force'] || ('object' === $normalizedType && '7.1' === $this->patchTypes['php'])) {
|
||||||
$returnType = implode('|', $returnType);
|
$returnType = implode('|', $returnType);
|
||||||
|
|
||||||
if ($method->getDocComment()) {
|
if ($method->getDocComment()) {
|
||||||
@ -1015,7 +1032,7 @@ EOTXT;
|
|||||||
|
|
||||||
private function fixReturnStatements(\ReflectionMethod $method, string $returnType)
|
private function fixReturnStatements(\ReflectionMethod $method, string $returnType)
|
||||||
{
|
{
|
||||||
if (($this->patchTypes['php71-compat'] ?? false) && 'object' === ltrim($returnType, '?') && 'docblock' !== ($this->patchTypes['force'] ?? null)) {
|
if ('7.1' === $this->patchTypes['php'] && 'object' === ltrim($returnType, '?') && 'docblock' !== $this->patchTypes['force']) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1026,7 +1043,7 @@ EOTXT;
|
|||||||
$fixedCode = $code = file($file);
|
$fixedCode = $code = file($file);
|
||||||
$i = (self::$fileOffsets[$file] ?? 0) + $method->getStartLine();
|
$i = (self::$fileOffsets[$file] ?? 0) + $method->getStartLine();
|
||||||
|
|
||||||
if ('?' !== $returnType && 'docblock' !== ($this->patchTypes['force'] ?? null)) {
|
if ('?' !== $returnType && 'docblock' !== $this->patchTypes['force']) {
|
||||||
$fixedCode[$i - 1] = preg_replace('/\)(;?\n)/', "): $returnType\\1", $code[$i - 1]);
|
$fixedCode[$i - 1] = preg_replace('/\)(;?\n)/', "): $returnType\\1", $code[$i - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,16 +16,15 @@ use Symfony\Component\ErrorHandler\DebugClassLoader;
|
|||||||
|
|
||||||
class DebugClassLoaderTest extends TestCase
|
class DebugClassLoaderTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
private $patchTypes;
|
||||||
* @var int Error reporting level before running tests
|
|
||||||
*/
|
|
||||||
private $errorReporting;
|
private $errorReporting;
|
||||||
|
|
||||||
private $loader;
|
private $loader;
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
|
$this->patchTypes = getenv('SYMFONY_PATCH_TYPE_DECLARATIONS');
|
||||||
$this->errorReporting = error_reporting(E_ALL);
|
$this->errorReporting = error_reporting(E_ALL);
|
||||||
|
putenv('SYMFONY_PATCH_TYPE_DECLARATIONS=force=0');
|
||||||
$this->loader = [new DebugClassLoader([new ClassLoader(), 'loadClass']), 'loadClass'];
|
$this->loader = [new DebugClassLoader([new ClassLoader(), 'loadClass']), 'loadClass'];
|
||||||
spl_autoload_register($this->loader, true, true);
|
spl_autoload_register($this->loader, true, true);
|
||||||
}
|
}
|
||||||
@ -34,6 +33,7 @@ class DebugClassLoaderTest extends TestCase
|
|||||||
{
|
{
|
||||||
spl_autoload_unregister($this->loader);
|
spl_autoload_unregister($this->loader);
|
||||||
error_reporting($this->errorReporting);
|
error_reporting($this->errorReporting);
|
||||||
|
putenv('SYMFONY_PATCH_TYPE_DECLARATIONS'.(false !== $this->patchTypes ? '='.$this->patchTypes : ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user