Updated Rector to commit b97ce487e6

b97ce487e6 [CodeQuality] Handle Param by reference in target method on CallableThisArrayToAnonymousFunctionRector (#1974)
This commit is contained in:
Tomas Votruba 2022-03-28 22:48:45 +00:00
parent 4f5f9f8bda
commit 98175f2608
35 changed files with 667 additions and 124 deletions

View File

@ -120,7 +120,7 @@ CODE_SAMPLE
if ($expectedArgOrParamOrder === null) {
return null;
}
$new->args = $this->argumentSorter->sortArgsByExpectedParamOrder($new->args, $expectedArgOrParamOrder);
$new->args = $this->argumentSorter->sortArgsByExpectedParamOrder($new->getArgs(), $expectedArgOrParamOrder);
return $new;
}
private function refactorMethodCall(\PhpParser\Node\Expr\MethodCall $methodCall) : ?\PhpParser\Node\Expr\MethodCall
@ -133,7 +133,7 @@ CODE_SAMPLE
if ($expectedArgOrParamOrder === null) {
return null;
}
$newArgs = $this->argumentSorter->sortArgsByExpectedParamOrder($methodCall->args, $expectedArgOrParamOrder);
$newArgs = $this->argumentSorter->sortArgsByExpectedParamOrder($methodCall->getArgs(), $expectedArgOrParamOrder);
if ($methodCall->args === $newArgs) {
return null;
}

View File

@ -48,7 +48,9 @@ use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
use Rector\StaticTypeMapper\StaticTypeMapper;
use ReflectionParameter;
use RectorPrefix20220328\Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser;
use RectorPrefix20220328\Symplify\PackageBuilder\Reflection\PrivatesAccessor;
final class AnonymousFunctionFactory
{
/**
@ -101,7 +103,12 @@ final class AnonymousFunctionFactory
* @var \Rector\Core\PhpParser\Printer\BetterStandardPrinter
*/
private $betterStandardPrinter;
public function __construct(\Rector\NodeNameResolver\NodeNameResolver $nodeNameResolver, \Rector\Core\PhpParser\Node\BetterNodeFinder $betterNodeFinder, \Rector\Core\PhpParser\Node\NodeFactory $nodeFactory, \Rector\StaticTypeMapper\StaticTypeMapper $staticTypeMapper, \RectorPrefix20220328\Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser $simpleCallableNodeTraverser, \Rector\Core\PhpParser\Parser\SimplePhpParser $simplePhpParser, \Rector\Core\PhpParser\Comparing\NodeComparator $nodeComparator, \Rector\Core\PhpParser\AstResolver $astResolver, \Rector\Core\PhpParser\Printer\BetterStandardPrinter $betterStandardPrinter)
/**
* @readonly
* @var \Symplify\PackageBuilder\Reflection\PrivatesAccessor
*/
private $privatesAccessor;
public function __construct(\Rector\NodeNameResolver\NodeNameResolver $nodeNameResolver, \Rector\Core\PhpParser\Node\BetterNodeFinder $betterNodeFinder, \Rector\Core\PhpParser\Node\NodeFactory $nodeFactory, \Rector\StaticTypeMapper\StaticTypeMapper $staticTypeMapper, \RectorPrefix20220328\Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser $simpleCallableNodeTraverser, \Rector\Core\PhpParser\Parser\SimplePhpParser $simplePhpParser, \Rector\Core\PhpParser\Comparing\NodeComparator $nodeComparator, \Rector\Core\PhpParser\AstResolver $astResolver, \Rector\Core\PhpParser\Printer\BetterStandardPrinter $betterStandardPrinter, \RectorPrefix20220328\Symplify\PackageBuilder\Reflection\PrivatesAccessor $privatesAccessor)
{
$this->nodeNameResolver = $nodeNameResolver;
$this->betterNodeFinder = $betterNodeFinder;
@ -112,6 +119,7 @@ final class AnonymousFunctionFactory
$this->nodeComparator = $nodeComparator;
$this->astResolver = $astResolver;
$this->betterStandardPrinter = $betterStandardPrinter;
$this->privatesAccessor = $privatesAccessor;
}
/**
* @param Param[] $params
@ -307,6 +315,7 @@ final class AnonymousFunctionFactory
$param = new \PhpParser\Node\Param(new \PhpParser\Node\Expr\Variable($parameterReflection->getName()));
$this->applyParamType($param, $parameterReflection);
$this->applyParamDefaultValue($param, $parameterReflection, $key, $classMethod);
$this->applyParamByReference($param, $parameterReflection);
$params[] = $param;
}
return $params;
@ -318,6 +327,12 @@ final class AnonymousFunctionFactory
}
$param->type = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($parameterReflection->getType(), \Rector\PHPStanStaticTypeMapper\Enum\TypeKind::PARAM());
}
private function applyParamByReference(\PhpParser\Node\Param $param, \PHPStan\Reflection\ParameterReflection $parameterReflection) : void
{
/** @var ReflectionParameter $reflection */
$reflection = $this->privatesAccessor->getPrivateProperty($parameterReflection, 'reflection');
$param->byRef = $reflection->isPassedByReference();
}
private function applyParamDefaultValue(\PhpParser\Node\Param $param, \PHPStan\Reflection\ParameterReflection $parameterReflection, int $key, \PhpParser\Node\Stmt\ClassMethod $classMethod) : void
{
if (!$parameterReflection->getDefaultValue() instanceof \PHPStan\Type\Type) {

View File

@ -16,11 +16,11 @@ final class VersionResolver
/**
* @var string
*/
public const PACKAGE_VERSION = 'df0d552cffdd8fa4fda51647839438b84ad93aac';
public const PACKAGE_VERSION = 'b97ce487e6a3a94df8bcefe4e5c30c302253a678';
/**
* @var string
*/
public const RELEASE_DATE = '2022-03-28 11:11:32';
public const RELEASE_DATE = '2022-03-29 00:41:39';
public static function resolvePackageVersion() : string
{
$process = new \RectorPrefix20220328\Symfony\Component\Process\Process(['git', 'log', '--pretty="%H"', '-n1', 'HEAD'], __DIR__);

2
vendor/autoload.php vendored
View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit784ff7722743891cd3bc094793583fb2::getLoader();
return ComposerAutoloaderInite10d76492c42050d4ac6c3834dd4a982::getLoader();

View File

@ -47,6 +47,8 @@ return array(
'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeForParameterNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php',

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit784ff7722743891cd3bc094793583fb2
class ComposerAutoloaderInite10d76492c42050d4ac6c3834dd4a982
{
private static $loader;
@ -22,15 +22,15 @@ class ComposerAutoloaderInit784ff7722743891cd3bc094793583fb2
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit784ff7722743891cd3bc094793583fb2', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInite10d76492c42050d4ac6c3834dd4a982', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInit784ff7722743891cd3bc094793583fb2', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInite10d76492c42050d4ac6c3834dd4a982', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit784ff7722743891cd3bc094793583fb2::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInite10d76492c42050d4ac6c3834dd4a982::getInitializer($loader));
} else {
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
@ -42,12 +42,12 @@ class ComposerAutoloaderInit784ff7722743891cd3bc094793583fb2
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit784ff7722743891cd3bc094793583fb2::$files;
$includeFiles = Composer\Autoload\ComposerStaticInite10d76492c42050d4ac6c3834dd4a982::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire784ff7722743891cd3bc094793583fb2($fileIdentifier, $file);
composerRequiree10d76492c42050d4ac6c3834dd4a982($fileIdentifier, $file);
}
return $loader;
@ -59,7 +59,7 @@ class ComposerAutoloaderInit784ff7722743891cd3bc094793583fb2
* @param string $file
* @return void
*/
function composerRequire784ff7722743891cd3bc094793583fb2($fileIdentifier, $file)
function composerRequiree10d76492c42050d4ac6c3834dd4a982($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInit784ff7722743891cd3bc094793583fb2
class ComposerStaticInite10d76492c42050d4ac6c3834dd4a982
{
public static $files = array (
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
@ -416,6 +416,8 @@ class ComposerStaticInit784ff7722743891cd3bc094793583fb2
'PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeForParameterNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\ConditionalTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php',
'PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php',
@ -3838,9 +3840,9 @@ class ComposerStaticInit784ff7722743891cd3bc094793583fb2
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit784ff7722743891cd3bc094793583fb2::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit784ff7722743891cd3bc094793583fb2::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit784ff7722743891cd3bc094793583fb2::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInite10d76492c42050d4ac6c3834dd4a982::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInite10d76492c42050d4ac6c3834dd4a982::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInite10d76492c42050d4ac6c3834dd4a982::$classMap;
}, null, ClassLoader::class);
}

View File

@ -1036,17 +1036,17 @@
},
{
"name": "phpstan\/phpdoc-parser",
"version": "1.3.0",
"version_normalized": "1.3.0.0",
"version": "1.4.0",
"version_normalized": "1.4.0.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/phpstan\/phpdoc-parser.git",
"reference": "c08946968bda74869e696982b0af40a9a8784c84"
"reference": "aa111aa1fecbc436f01e5439d88906bd3b612027"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpdoc-parser\/zipball\/c08946968bda74869e696982b0af40a9a8784c84",
"reference": "c08946968bda74869e696982b0af40a9a8784c84",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpdoc-parser\/zipball\/aa111aa1fecbc436f01e5439d88906bd3b612027",
"reference": "aa111aa1fecbc436f01e5439d88906bd3b612027",
"shasum": ""
},
"require": {
@ -1060,7 +1060,7 @@
"phpunit\/phpunit": "^9.5",
"symfony\/process": "^5.2"
},
"time": "2022-03-28T07:53:31+00:00",
"time": "2022-03-28T10:52:48+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1077,23 +1077,23 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https:\/\/github.com\/phpstan\/phpdoc-parser\/issues",
"source": "https:\/\/github.com\/phpstan\/phpdoc-parser\/tree\/1.3.0"
"source": "https:\/\/github.com\/phpstan\/phpdoc-parser\/tree\/1.4.0"
},
"install-path": "..\/phpstan\/phpdoc-parser"
},
{
"name": "phpstan\/phpstan",
"version": "1.5.0",
"version_normalized": "1.5.0.0",
"version": "1.5.1",
"version_normalized": "1.5.1.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/phpstan\/phpstan.git",
"reference": "2be8dd6dfa09ab1a21c49956ff591979cd5ab29e"
"reference": "cc67578d9afd0f5f2545067285613d7a529aefac"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpstan\/zipball\/2be8dd6dfa09ab1a21c49956ff591979cd5ab29e",
"reference": "2be8dd6dfa09ab1a21c49956ff591979cd5ab29e",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpstan\/zipball\/cc67578d9afd0f5f2545067285613d7a529aefac",
"reference": "cc67578d9afd0f5f2545067285613d7a529aefac",
"shasum": ""
},
"require": {
@ -1102,7 +1102,7 @@
"conflict": {
"phpstan\/phpstan-shim": "*"
},
"time": "2022-03-24T18:18:00+00:00",
"time": "2022-03-28T15:34:48+00:00",
"bin": [
"phpstan",
"phpstan.phar"
@ -1121,7 +1121,7 @@
"description": "PHPStan - PHP Static Analysis Tool",
"support": {
"issues": "https:\/\/github.com\/phpstan\/phpstan\/issues",
"source": "https:\/\/github.com\/phpstan\/phpstan\/tree\/1.5.0"
"source": "https:\/\/github.com\/phpstan\/phpstan\/tree\/1.5.1"
},
"funding": [
{
@ -1145,22 +1145,22 @@
},
{
"name": "phpstan\/phpstan-phpunit",
"version": "1.0.0",
"version_normalized": "1.0.0.0",
"version": "1.1.0",
"version_normalized": "1.1.0.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/phpstan\/phpstan-phpunit.git",
"reference": "9eb88c9f689003a8a2a5ae9e010338ee94dc39b3"
"reference": "09133ce914f1388a8bb8c7f8573aaa3723cff52a"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpstan-phpunit\/zipball\/9eb88c9f689003a8a2a5ae9e010338ee94dc39b3",
"reference": "9eb88c9f689003a8a2a5ae9e010338ee94dc39b3",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpstan-phpunit\/zipball\/09133ce914f1388a8bb8c7f8573aaa3723cff52a",
"reference": "09133ce914f1388a8bb8c7f8573aaa3723cff52a",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0",
"phpstan\/phpstan": "^1.0"
"php": "^7.2 || ^8.0",
"phpstan\/phpstan": "^1.5.0"
},
"conflict": {
"phpunit\/phpunit": "<7.0"
@ -1171,12 +1171,9 @@
"phpstan\/phpstan-strict-rules": "^1.0",
"phpunit\/phpunit": "^9.5"
},
"time": "2021-10-14T08:03:54+00:00",
"time": "2022-03-28T09:20:49+00:00",
"type": "phpstan-extension",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
},
"phpstan": {
"includes": [
"extension.neon",
@ -1197,7 +1194,7 @@
"description": "PHPUnit extensions and rules for PHPStan",
"support": {
"issues": "https:\/\/github.com\/phpstan\/phpstan-phpunit\/issues",
"source": "https:\/\/github.com\/phpstan\/phpstan-phpunit\/tree\/1.0.0"
"source": "https:\/\/github.com\/phpstan\/phpstan-phpunit\/tree\/1.1.0"
},
"install-path": "..\/phpstan\/phpstan-phpunit"
},

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,33 @@
<?php
declare (strict_types=1);
namespace PHPStan\PhpDocParser\Ast\Type;
use PHPStan\PhpDocParser\Ast\NodeAttributes;
use function sprintf;
class ConditionalTypeForParameterNode implements \PHPStan\PhpDocParser\Ast\Type\TypeNode
{
use NodeAttributes;
/** @var string */
public $parameterName;
/** @var TypeNode */
public $targetType;
/** @var TypeNode */
public $if;
/** @var TypeNode */
public $else;
/** @var bool */
public $negated;
public function __construct(string $parameterName, \PHPStan\PhpDocParser\Ast\Type\TypeNode $targetType, \PHPStan\PhpDocParser\Ast\Type\TypeNode $if, \PHPStan\PhpDocParser\Ast\Type\TypeNode $false, bool $negated)
{
$this->parameterName = $parameterName;
$this->targetType = $targetType;
$this->if = $if;
$this->else = $false;
$this->negated = $negated;
}
public function __toString() : string
{
return \sprintf('%s %s %s ? %s : %s', $this->parameterName, $this->negated ? 'is not' : 'is', $this->targetType, $this->if, $this->else);
}
}

View File

@ -0,0 +1,33 @@
<?php
declare (strict_types=1);
namespace PHPStan\PhpDocParser\Ast\Type;
use PHPStan\PhpDocParser\Ast\NodeAttributes;
use function sprintf;
class ConditionalTypeNode implements \PHPStan\PhpDocParser\Ast\Type\TypeNode
{
use NodeAttributes;
/** @var TypeNode */
public $subjectType;
/** @var TypeNode */
public $targetType;
/** @var TypeNode */
public $if;
/** @var TypeNode */
public $else;
/** @var bool */
public $negated;
public function __construct(\PHPStan\PhpDocParser\Ast\Type\TypeNode $subjectType, \PHPStan\PhpDocParser\Ast\Type\TypeNode $targetType, \PHPStan\PhpDocParser\Ast\Type\TypeNode $if, \PHPStan\PhpDocParser\Ast\Type\TypeNode $false, bool $negated)
{
$this->subjectType = $subjectType;
$this->targetType = $targetType;
$this->if = $if;
$this->else = $false;
$this->negated = $negated;
}
public function __toString() : string
{
return \sprintf('%s %s %s ? %s : %s', $this->subjectType, $this->negated ? 'is not' : 'is', $this->targetType, $this->if, $this->else);
}
}

View File

@ -20,15 +20,16 @@ class ParserException extends \Exception
private $currentOffset;
/** @var int */
private $expectedTokenType;
public function __construct(string $currentTokenValue, int $currentTokenType, int $currentOffset, int $expectedTokenType)
/** @var string|null */
private $expectedTokenValue;
public function __construct(string $currentTokenValue, int $currentTokenType, int $currentOffset, int $expectedTokenType, ?string $expectedTokenValue = null)
{
$this->currentTokenValue = $currentTokenValue;
$this->currentTokenType = $currentTokenType;
$this->currentOffset = $currentOffset;
$this->expectedTokenType = $expectedTokenType;
$json = \json_encode($currentTokenValue, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES);
\assert($json !== \false);
parent::__construct(\sprintf('Unexpected token %s, expected %s at offset %d', $json, \PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_LABELS[$expectedTokenType], $currentOffset));
$this->expectedTokenValue = $expectedTokenValue;
parent::__construct(\sprintf('Unexpected token %s, expected %s%s at offset %d', $this->formatValue($currentTokenValue), \PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_LABELS[$expectedTokenType], $expectedTokenValue !== null ? \sprintf(' (%s)', $this->formatValue($expectedTokenValue)) : '', $currentOffset));
}
public function getCurrentTokenValue() : string
{
@ -46,4 +47,14 @@ class ParserException extends \Exception
{
return $this->expectedTokenType;
}
public function getExpectedTokenValue() : ?string
{
return $this->expectedTokenValue;
}
private function formatValue(string $value) : string
{
$json = \json_encode($value, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES);
\assert($json !== \false);
return $json;
}
}

View File

@ -68,6 +68,20 @@ class TokenIterator
}
$this->index++;
}
/**
* @throws ParserException
*/
public function consumeTokenValue(int $tokenType, string $tokenValue) : void
{
if ($this->tokens[$this->index][\PHPStan\PhpDocParser\Lexer\Lexer::TYPE_OFFSET] !== $tokenType || $this->tokens[$this->index][\PHPStan\PhpDocParser\Lexer\Lexer::VALUE_OFFSET] !== $tokenValue) {
$this->throwError($tokenType, $tokenValue);
}
$this->index++;
if (($this->tokens[$this->index][\PHPStan\PhpDocParser\Lexer\Lexer::TYPE_OFFSET] ?? -1) !== \PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_HORIZONTAL_WS) {
return;
}
$this->index++;
}
/** @phpstan-impure */
public function tryConsumeTokenValue(string $tokenValue) : bool
{
@ -139,8 +153,8 @@ class TokenIterator
/**
* @throws ParserException
*/
private function throwError(int $expectedTokenType) : void
private function throwError(int $expectedTokenType, ?string $expectedTokenValue = null) : void
{
throw new \PHPStan\PhpDocParser\Parser\ParserException($this->currentTokenValue(), $this->currentTokenType(), $this->currentTokenOffset(), $expectedTokenType);
throw new \PHPStan\PhpDocParser\Parser\ParserException($this->currentTokenValue(), $this->currentTokenType(), $this->currentTokenOffset(), $expectedTokenType, $expectedTokenValue);
}
}

View File

@ -32,10 +32,29 @@ class TypeParser
return $type;
}
/** @phpstan-impure */
private function subParse(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens) : \PHPStan\PhpDocParser\Ast\Type\TypeNode
{
if ($tokens->isCurrentTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_NULLABLE)) {
$type = $this->parseNullable($tokens);
} elseif ($tokens->isCurrentTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_VARIABLE)) {
$type = $this->parseConditionalForParameter($tokens, $tokens->currentTokenValue());
} else {
$type = $this->parseAtomic($tokens);
if ($tokens->isCurrentTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_UNION)) {
$type = $this->parseUnion($tokens, $type);
} elseif ($tokens->isCurrentTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_INTERSECTION)) {
$type = $this->parseIntersection($tokens, $type);
} elseif ($tokens->isCurrentTokenValue('is')) {
$type = $this->parseConditional($tokens, $type);
}
}
return $type;
}
/** @phpstan-impure */
private function parseAtomic(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens) : \PHPStan\PhpDocParser\Ast\Type\TypeNode
{
if ($tokens->tryConsumeTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_OPEN_PARENTHESES)) {
$type = $this->parse($tokens);
$type = $this->subParse($tokens);
$tokens->consumeTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_CLOSE_PARENTHESES);
if ($tokens->isCurrentTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
return $this->tryParseArray($tokens, $type);
@ -120,6 +139,39 @@ class TypeParser
return new \PHPStan\PhpDocParser\Ast\Type\IntersectionTypeNode($types);
}
/** @phpstan-impure */
private function parseConditional(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens, \PHPStan\PhpDocParser\Ast\Type\TypeNode $subjectType) : \PHPStan\PhpDocParser\Ast\Type\TypeNode
{
$tokens->consumeTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_IDENTIFIER);
$negated = \false;
if ($tokens->isCurrentTokenValue('not')) {
$negated = \true;
$tokens->consumeTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_IDENTIFIER);
}
$targetType = $this->parseAtomic($tokens);
$tokens->consumeTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_NULLABLE);
$ifType = $this->parseAtomic($tokens);
$tokens->consumeTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_COLON);
$elseType = $this->parseAtomic($tokens);
return new \PHPStan\PhpDocParser\Ast\Type\ConditionalTypeNode($subjectType, $targetType, $ifType, $elseType, $negated);
}
/** @phpstan-impure */
private function parseConditionalForParameter(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens, string $parameterName) : \PHPStan\PhpDocParser\Ast\Type\TypeNode
{
$tokens->consumeTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_VARIABLE);
$tokens->consumeTokenValue(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_IDENTIFIER, 'is');
$negated = \false;
if ($tokens->isCurrentTokenValue('not')) {
$negated = \true;
$tokens->consumeTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_IDENTIFIER);
}
$targetType = $this->parseAtomic($tokens);
$tokens->consumeTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_NULLABLE);
$ifType = $this->parseAtomic($tokens);
$tokens->consumeTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_COLON);
$elseType = $this->parseAtomic($tokens);
return new \PHPStan\PhpDocParser\Ast\Type\ConditionalTypeForParameterNode($parameterName, $targetType, $ifType, $elseType, $negated);
}
/** @phpstan-impure */
private function parseNullable(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens) : \PHPStan\PhpDocParser\Ast\Type\TypeNode
{
$tokens->consumeTokenType(\PHPStan\PhpDocParser\Lexer\Lexer::TOKEN_NULLABLE);

View File

@ -2,6 +2,11 @@
"require-dev": {
"consistence-community\/coding-standard": "^3.10",
"dealerdirect\/phpcodesniffer-composer-installer": "^0.7.0",
"slevomat\/coding-standard": "^6.4"
"slevomat\/coding-standard": "^7.0"
},
"config": {
"allow-plugins": {
"dealerdirect\/phpcodesniffer-composer-installer": true
}
}
}

327
vendor/phpstan/phpstan-phpunit/build-cs/composer.lock generated vendored Normal file
View File

@ -0,0 +1,327 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4485bbedba7bcc71ace5f69dbb9b6c47",
"packages": [],
"packages-dev": [
{
"name": "consistence-community/coding-standard",
"version": "3.11.1",
"source": {
"type": "git",
"url": "https://github.com/consistence-community/coding-standard.git",
"reference": "4632fead8c9ee8f50044fcbce9f66c797b34c0df"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/consistence-community/coding-standard/zipball/4632fead8c9ee8f50044fcbce9f66c797b34c0df",
"reference": "4632fead8c9ee8f50044fcbce9f66c797b34c0df",
"shasum": ""
},
"require": {
"php": ">=7.4",
"slevomat/coding-standard": "~7.0",
"squizlabs/php_codesniffer": "~3.6.0"
},
"replace": {
"consistence/coding-standard": "3.10.*"
},
"require-dev": {
"phing/phing": "2.16.4",
"php-parallel-lint/php-parallel-lint": "1.3.0",
"phpunit/phpunit": "9.5.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Consistence\\": [
"Consistence"
]
},
"classmap": [
"Consistence"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Vašek Purchart",
"email": "me@vasekpurchart.cz",
"homepage": "http://vasekpurchart.cz"
}
],
"description": "Consistence - Coding Standard - PHP Code Sniffer rules",
"keywords": [
"Coding Standard",
"PHPCodeSniffer",
"codesniffer",
"coding",
"cs",
"phpcs",
"ruleset",
"sniffer",
"standard"
],
"support": {
"issues": "https://github.com/consistence-community/coding-standard/issues",
"source": "https://github.com/consistence-community/coding-standard/tree/3.11.1"
},
"time": "2021-05-03T18:13:22+00:00"
},
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0",
"php": ">=5.3",
"squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0"
},
"require-dev": {
"composer/composer": "*",
"php-parallel-lint/php-parallel-lint": "^1.3.1",
"phpcompatibility/php-compatibility": "^9.0"
},
"type": "composer-plugin",
"extra": {
"class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
},
"autoload": {
"psr-4": {
"Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Franck Nijhof",
"email": "franck.nijhof@dealerdirect.com",
"homepage": "http://www.frenck.nl",
"role": "Developer / IT Manager"
},
{
"name": "Contributors",
"homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors"
}
],
"description": "PHP_CodeSniffer Standards Composer Installer Plugin",
"homepage": "http://www.dealerdirect.com",
"keywords": [
"PHPCodeSniffer",
"PHP_CodeSniffer",
"code quality",
"codesniffer",
"composer",
"installer",
"phpcbf",
"phpcs",
"plugin",
"qa",
"quality",
"standard",
"standards",
"style guide",
"stylecheck",
"tests"
],
"support": {
"issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues",
"source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer"
},
"time": "2022-02-04T12:51:07+00:00"
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "dbc093d7af60eff5cd575d2ed761b15ed40bd08e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/dbc093d7af60eff5cd575d2ed761b15ed40bd08e",
"reference": "dbc093d7af60eff5cd575d2ed761b15ed40bd08e",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"symfony/process": "^5.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"PHPStan\\PhpDocParser\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.2.0"
},
"time": "2021-09-16T20:46:02+00:00"
},
{
"name": "slevomat/coding-standard",
"version": "7.0.20",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "cbfadfe34c2c29473bf1e891306b3950b3b4350b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/cbfadfe34c2c29473bf1e891306b3950b3b4350b",
"reference": "cbfadfe34c2c29473bf1e891306b3950b3b4350b",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.1 || ^8.0",
"phpstan/phpdoc-parser": "^1.0.0",
"squizlabs/php_codesniffer": "^3.6.2"
},
"require-dev": {
"phing/phing": "2.17.2",
"php-parallel-lint/php-parallel-lint": "1.3.2",
"phpstan/phpstan": "1.4.10|1.5.0",
"phpstan/phpstan-deprecation-rules": "1.0.0",
"phpstan/phpstan-phpunit": "1.0.0",
"phpstan/phpstan-strict-rules": "1.1.0",
"phpunit/phpunit": "7.5.20|8.5.21|9.5.19"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "7.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
"source": "https://github.com/slevomat/coding-standard/tree/7.0.20"
},
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2022-03-25T09:43:20+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.6.2",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a",
"reference": "5e4e71592f69da17871dba6e80dd51bce74a351a",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"support": {
"issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues",
"source": "https://github.com/squizlabs/PHP_CodeSniffer",
"wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki"
},
"time": "2021-12-12T21:44:58+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.2.0"
}

View File

@ -6,8 +6,8 @@
"MIT"
],
"require": {
"php": "^7.1 || ^8.0",
"phpstan\/phpstan": "^1.0"
"php": "^7.2 || ^8.0",
"phpstan\/phpstan": "^1.5.0"
},
"conflict": {
"phpunit\/phpunit": "<7.0"
@ -25,9 +25,6 @@
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
},
"phpstan": {
"includes": [
"extension.neon",

View File

@ -12,6 +12,7 @@ parameters:
- stubs/InvocationMocker.stub
- stubs/MockBuilder.stub
- stubs/MockObject.stub
- stubs/Stub.stub
- stubs/TestCase.stub
exceptions:
uncheckedExceptionRegexes:

View File

@ -3,6 +3,7 @@
declare (strict_types=1);
namespace PHPStan\PhpDoc\PHPUnit;
use PHPStan\Analyser\NameScope;
use PHPStan\PhpDoc\TypeNodeResolver;
use PHPStan\PhpDoc\TypeNodeResolverAwareExtension;
use PHPStan\PhpDoc\TypeNodeResolverExtension;
@ -10,7 +11,9 @@ use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode;
use PHPStan\Type\NeverType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypeWithClassName;
use function array_key_exists;
class MockObjectTypeNodeResolverExtension implements \PHPStan\PhpDoc\TypeNodeResolverExtension, \PHPStan\PhpDoc\TypeNodeResolverAwareExtension
{
/** @var TypeNodeResolver */
@ -28,7 +31,7 @@ class MockObjectTypeNodeResolverExtension implements \PHPStan\PhpDoc\TypeNodeRes
if (!$typeNode instanceof \PHPStan\PhpDocParser\Ast\Type\UnionTypeNode) {
return null;
}
static $mockClassNames = ['PHPUnit_Framework_MockObject_MockObject' => \true, 'RectorPrefix20220328\\PHPUnit\\Framework\\MockObject\\MockObject' => \true];
static $mockClassNames = ['PHPUnit_Framework_MockObject_MockObject' => \true, 'RectorPrefix20220328\\PHPUnit\\Framework\\MockObject\\MockObject' => \true, 'RectorPrefix20220328\\PHPUnit\\Framework\\MockObject\\Stub' => \true];
$types = $this->typeNodeResolver->resolveMultiple($typeNode->types, $nameScope);
foreach ($types as $type) {
if (!$type instanceof \PHPStan\Type\TypeWithClassName) {

View File

@ -6,6 +6,8 @@ namespace PHPStan\Rules\PHPUnit;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Type\ObjectType;
use function in_array;
use function strtolower;
class AssertRuleHelper
{
public static function isMethodOrStaticCallOnAssert(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scope) : bool

View File

@ -4,10 +4,16 @@ declare (strict_types=1);
namespace PHPStan\Rules\PHPUnit;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\NodeAbstract;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\Constant\ConstantBooleanType;
use function count;
use function strtolower;
/**
* @implements \PHPStan\Rules\Rule<\PhpParser\NodeAbstract>
* @implements Rule<NodeAbstract>
*/
class AssertSameBooleanExpectedRule implements \PHPStan\Rules\Rule
{
@ -20,7 +26,7 @@ class AssertSameBooleanExpectedRule implements \PHPStan\Rules\Rule
if (!\PHPStan\Rules\PHPUnit\AssertRuleHelper::isMethodOrStaticCallOnAssert($node, $scope)) {
return [];
}
/** @var \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $node */
/** @var MethodCall|StaticCall $node */
$node = $node;
if (\count($node->getArgs()) < 2) {
return [];

View File

@ -4,10 +4,16 @@ declare (strict_types=1);
namespace PHPStan\Rules\PHPUnit;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\NodeAbstract;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\NullType;
use function count;
use function strtolower;
/**
* @implements \PHPStan\Rules\Rule<\PhpParser\NodeAbstract>
* @implements Rule<NodeAbstract>
*/
class AssertSameNullExpectedRule implements \PHPStan\Rules\Rule
{
@ -20,7 +26,7 @@ class AssertSameNullExpectedRule implements \PHPStan\Rules\Rule
if (!\PHPStan\Rules\PHPUnit\AssertRuleHelper::isMethodOrStaticCallOnAssert($node, $scope)) {
return [];
}
/** @var \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $node */
/** @var MethodCall|StaticCall $node */
$node = $node;
if (\count($node->getArgs()) < 2) {
return [];

View File

@ -3,11 +3,18 @@
declare (strict_types=1);
namespace PHPStan\Rules\PHPUnit;
use Countable;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\NodeAbstract;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\ObjectType;
use function count;
use function strtolower;
/**
* @implements \PHPStan\Rules\Rule<\PhpParser\NodeAbstract>
* @implements Rule<NodeAbstract>
*/
class AssertSameWithCountRule implements \PHPStan\Rules\Rule
{
@ -20,7 +27,7 @@ class AssertSameWithCountRule implements \PHPStan\Rules\Rule
if (!\PHPStan\Rules\PHPUnit\AssertRuleHelper::isMethodOrStaticCallOnAssert($node, $scope)) {
return [];
}
/** @var \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $node */
/** @var MethodCall|StaticCall $node */
$node = $node;
if (\count($node->getArgs()) < 2) {
return [];

View File

@ -4,15 +4,23 @@ declare (strict_types=1);
namespace PHPStan\Rules\PHPUnit;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\Constant\ConstantStringType;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\ObjectType;
use RectorPrefix20220328\PHPUnit\Framework\MockObject\Builder\InvocationMocker;
use RectorPrefix20220328\PHPUnit\Framework\MockObject\MockObject;
use RectorPrefix20220328\PHPUnit\Framework\MockObject\Stub;
use function array_filter;
use function count;
use function implode;
use function in_array;
use function sprintf;
/**
* @implements \PHPStan\Rules\Rule<\PhpParser\Node\Expr\MethodCall>
* @implements Rule<MethodCall>
*/
class MockMethodCallRule implements \PHPStan\Rules\Rule
{
@ -36,9 +44,9 @@ class MockMethodCallRule implements \PHPStan\Rules\Rule
}
$method = $argType->getValue();
$type = $scope->getType($node->var);
if ($type instanceof \PHPStan\Type\IntersectionType && \in_array(\RectorPrefix20220328\PHPUnit\Framework\MockObject\MockObject::class, $type->getReferencedClasses(), \true) && !$type->hasMethod($method)->yes()) {
$mockClass = \array_filter($type->getReferencedClasses(), function (string $class) : bool {
return $class !== \RectorPrefix20220328\PHPUnit\Framework\MockObject\MockObject::class;
if ($type instanceof \PHPStan\Type\IntersectionType && (\in_array(\RectorPrefix20220328\PHPUnit\Framework\MockObject\MockObject::class, $type->getReferencedClasses(), \true) || \in_array(\RectorPrefix20220328\PHPUnit\Framework\MockObject\Stub::class, $type->getReferencedClasses(), \true)) && !$type->hasMethod($method)->yes()) {
$mockClass = \array_filter($type->getReferencedClasses(), static function (string $class) : bool {
return $class !== \RectorPrefix20220328\PHPUnit\Framework\MockObject\MockObject::class && $class !== \RectorPrefix20220328\PHPUnit\Framework\MockObject\Stub::class;
});
return [\sprintf('Trying to mock an undefined method %s() on class %s.', $method, \implode('&', $mockClass))];
}

View File

@ -6,10 +6,14 @@ namespace PHPStan\Rules\PHPUnit;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\InClassMethodNode;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use RectorPrefix20220328\PHPUnit\Framework\TestCase;
use function in_array;
use function sprintf;
use function strtolower;
/**
* @implements \PHPStan\Rules\Rule<InClassMethodNode>
* @implements Rule<InClassMethodNode>
*/
class ShouldCallParentMethodsRule implements \PHPStan\Rules\Rule
{
@ -48,9 +52,7 @@ class ShouldCallParentMethodsRule implements \PHPStan\Rules\Rule
}
/**
* @param Node\Stmt[]|null $stmts
* @param string $methodName
*
* @return bool
*/
private function hasParentClassCall(?array $stmts, string $methodName) : bool
{

View File

@ -11,6 +11,9 @@ use PHPStan\Analyser\TypeSpecifierAwareExtension;
use PHPStan\Analyser\TypeSpecifierContext;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Type\FunctionTypeSpecifyingExtension;
use function strlen;
use function strpos;
use function substr;
class AssertFunctionTypeSpecifyingExtension implements \PHPStan\Type\FunctionTypeSpecifyingExtension, \PHPStan\Analyser\TypeSpecifierAwareExtension
{
/** @var TypeSpecifier */

View File

@ -3,8 +3,12 @@
declare (strict_types=1);
namespace PHPStan\Type\PHPUnit\Assert;
use Closure;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\BinaryOp\Identical;
use PhpParser\Node\Expr\BooleanNot;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\Instanceof_;
use PhpParser\Node\Name;
@ -13,14 +17,18 @@ use PHPStan\Analyser\SpecifiedTypes;
use PHPStan\Analyser\TypeSpecifier;
use PHPStan\Analyser\TypeSpecifierContext;
use PHPStan\Type\Constant\ConstantStringType;
use ReflectionObject;
use function array_key_exists;
use function count;
use function strlen;
use function strpos;
use function substr;
class AssertTypeSpecifyingExtensionHelper
{
/** @var \Closure[] */
/** @var Closure[] */
private static $resolvers;
/**
* @param string $name
* @param \PhpParser\Node\Arg[] $args
* @return bool
* @param Arg[] $args
*/
public static function isSupported(string $name, array $args) : bool
{
@ -48,11 +56,7 @@ class AssertTypeSpecifyingExtensionHelper
return $name;
}
/**
* @param TypeSpecifier $typeSpecifier
* @param Scope $scope
* @param string $name
* @param \PhpParser\Node\Arg[] $args $args
* @return SpecifiedTypes
* @param Arg[] $args $args
*/
public static function specifyTypes(\PHPStan\Analyser\TypeSpecifier $typeSpecifier, \PHPStan\Analyser\Scope $scope, string $name, array $args) : \PHPStan\Analyser\SpecifiedTypes
{
@ -63,10 +67,7 @@ class AssertTypeSpecifyingExtensionHelper
return $typeSpecifier->specifyTypesInCondition($scope, $expression, \PHPStan\Analyser\TypeSpecifierContext::createTruthy());
}
/**
* @param Scope $scope
* @param string $name
* @param \PhpParser\Node\Arg[] $args
* @return \PhpParser\Node\Expr|null
* @param Arg[] $args
*/
private static function createExpression(\PHPStan\Analyser\Scope $scope, string $name, array $args) : ?\PhpParser\Node\Expr
{
@ -83,48 +84,48 @@ class AssertTypeSpecifyingExtensionHelper
return $expression;
}
/**
* @return \Closure[]
* @return Closure[]
*/
private static function getExpressionResolvers() : array
{
if (self::$resolvers === null) {
self::$resolvers = ['InstanceOf' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $class, \PhpParser\Node\Arg $object) : ?Instanceof_ {
self::$resolvers = ['InstanceOf' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $class, \PhpParser\Node\Arg $object) : ?Instanceof_ {
$classType = $scope->getType($class->value);
if (!$classType instanceof \PHPStan\Type\Constant\ConstantStringType) {
return null;
}
return new \PhpParser\Node\Expr\Instanceof_($object->value, new \PhpParser\Node\Name($classType->getValue()));
}, 'Same' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $expected, \PhpParser\Node\Arg $actual) : Identical {
}, 'Same' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $expected, \PhpParser\Node\Arg $actual) : Identical {
return new \PhpParser\Node\Expr\BinaryOp\Identical($expected->value, $actual->value);
}, 'True' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : Identical {
}, 'True' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : Identical {
return new \PhpParser\Node\Expr\BinaryOp\Identical($actual->value, new \PhpParser\Node\Expr\ConstFetch(new \PhpParser\Node\Name('true')));
}, 'False' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : Identical {
}, 'False' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : Identical {
return new \PhpParser\Node\Expr\BinaryOp\Identical($actual->value, new \PhpParser\Node\Expr\ConstFetch(new \PhpParser\Node\Name('false')));
}, 'Null' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : Identical {
}, 'Null' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : Identical {
return new \PhpParser\Node\Expr\BinaryOp\Identical($actual->value, new \PhpParser\Node\Expr\ConstFetch(new \PhpParser\Node\Name('null')));
}, 'IsArray' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
}, 'IsArray' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name('is_array'), [$actual]);
}, 'IsBool' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
}, 'IsBool' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name('is_bool'), [$actual]);
}, 'IsCallable' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
}, 'IsCallable' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name('is_callable'), [$actual]);
}, 'IsFloat' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
}, 'IsFloat' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name('is_float'), [$actual]);
}, 'IsInt' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
}, 'IsInt' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name('is_int'), [$actual]);
}, 'IsIterable' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
}, 'IsIterable' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name('is_iterable'), [$actual]);
}, 'IsNumeric' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
}, 'IsNumeric' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name('is_numeric'), [$actual]);
}, 'IsObject' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
}, 'IsObject' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name('is_object'), [$actual]);
}, 'IsResource' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
}, 'IsResource' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name('is_resource'), [$actual]);
}, 'IsString' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
}, 'IsString' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name('is_string'), [$actual]);
}, 'IsScalar' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
}, 'IsScalar' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $actual) : FuncCall {
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name('is_scalar'), [$actual]);
}, 'InternalType' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $type, \PhpParser\Node\Arg $value) : ?FuncCall {
}, 'InternalType' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $type, \PhpParser\Node\Arg $value) : ?FuncCall {
$typeType = $scope->getType($type->value);
if (!$typeType instanceof \PHPStan\Type\Constant\ConstantStringType) {
return null;
@ -171,9 +172,9 @@ class AssertTypeSpecifyingExtensionHelper
return null;
}
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name($functionName), [$value]);
}, 'ArrayHasKey' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $key, \PhpParser\Node\Arg $array) : FuncCall {
}, 'ArrayHasKey' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $key, \PhpParser\Node\Arg $array) : FuncCall {
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name('array_key_exists'), [$key, $array]);
}, 'ObjectHasAttribute' => function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $property, \PhpParser\Node\Arg $object) : FuncCall {
}, 'ObjectHasAttribute' => static function (\PHPStan\Analyser\Scope $scope, \PhpParser\Node\Arg $property, \PhpParser\Node\Arg $object) : FuncCall {
return new \PhpParser\Node\Expr\FuncCall(new \PhpParser\Node\Name('property_exists'), [$object, $property]);
}];
}

View File

@ -6,6 +6,7 @@ namespace PHPStan\Type\PHPUnit;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\Type;
use RectorPrefix20220328\PHPUnit\Framework\MockObject\Builder\InvocationMocker;
class InvocationMockerDynamicReturnTypeExtension implements \PHPStan\Type\DynamicMethodReturnTypeExtension

View File

@ -6,8 +6,10 @@ namespace PHPStan\Type\PHPUnit;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\Type;
use RectorPrefix20220328\PHPUnit\Framework\MockObject\MockBuilder;
use function in_array;
class MockBuilderDynamicReturnTypeExtension implements \PHPStan\Type\DynamicMethodReturnTypeExtension
{
public function getClass() : string

View File

@ -6,6 +6,7 @@ namespace PHPStan\Type\PHPUnit;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\ObjectType;
@ -13,6 +14,9 @@ use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;
use RectorPrefix20220328\PHPUnit\Framework\MockObject\Builder\InvocationMocker;
use RectorPrefix20220328\PHPUnit\Framework\MockObject\MockObject;
use function array_filter;
use function array_values;
use function count;
class MockObjectDynamicReturnTypeExtension implements \PHPStan\Type\DynamicMethodReturnTypeExtension
{
public function getClass() : string
@ -29,7 +33,7 @@ class MockObjectDynamicReturnTypeExtension implements \PHPStan\Type\DynamicMetho
if (!$type instanceof \PHPStan\Type\IntersectionType) {
return new \PHPStan\Type\ObjectType(\RectorPrefix20220328\PHPUnit\Framework\MockObject\Builder\InvocationMocker::class);
}
$mockClasses = \array_values(\array_filter($type->getTypes(), function (\PHPStan\Type\Type $type) : bool {
$mockClasses = \array_values(\array_filter($type->getTypes(), static function (\PHPStan\Type\Type $type) : bool {
return !$type instanceof \PHPStan\Type\TypeWithClassName || $type->getClassName() !== \RectorPrefix20220328\PHPUnit\Framework\MockObject\MockObject::class;
}));
if (\count($mockClasses) !== 1) {

View File

@ -0,0 +1,8 @@
<?php
namespace PHPUnit\Framework\MockObject;
interface Stub
{
}

View File

@ -4,6 +4,7 @@ namespace PHPUnit\Framework;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\MockObject\MockBuilder;
use PHPUnit\Framework\MockObject\Stub;
class TestCase
{
@ -11,7 +12,7 @@ class TestCase
/**
* @template T
* @phpstan-param class-string<T> $originalClassName
* @phpstan-return MockObject&T
* @phpstan-return Stub&T
*/
public function createStub($originalClassName) {}

Binary file not shown.

View File

@ -1,16 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE0yaA1ZV9xxFr4pwUzxoQjQ565yAFAmI8tdEACgkQzxoQjQ56
5yB8/w//W/Uz3MeNUe59qOTQptGdnA358uQCnkzxZC6m2wKD5qZ5FTiZX0N7sWm6
YSGPr7xtPmbJq2A3lA71XF3j0pJF5oqRr/aAbpl669C6etjkFWtMhtripIzWbKHy
mo6BBxocilRdQYZqC+CadR68J75lCC/0F7H+l7Kt9yfCdGPfhcCucB9d1sHMuOMI
ullv5gyTiCuX0gmjyHFFRU/EPX798gLoLNIwVo/2HmY9NCONcgQK6hLtWXQZDUTJ
qdekBFSHo2P4DvwlLh7dGKXiYYdtDKg14pDlJANsilEQIureZRpf4j5+3PLUsJ7q
09GFifWuSyHbZqRS0WXfJmpEH1uVTTNjv9gKXLRRQBJ/9R6yO7PFZz32EwPgdzLq
eq251RMXbRPs4zRrBUNT8GkQ+eptDhr4DWuVivRQnqldgJQUqMnj6EV9M0qmF+BD
mOTH8k/rSqLzvg1bg1Di0xVzWMM9+SGdNSrHpG+X2QDghHdPaNKqkcKxeT1pM6VV
aJrs03C7+iDrd12B4B7Z20ZVjocYWS1rcesvvqy8zu+dbwfa1ANNrb28lneyNIfd
UUKTHiZrDpP4cm9LWDTNFSiicF3bqCdl+bSkVz8la3nvdy6Q//QC+KTV0DoI6oTN
AfeE4vqmNNReZdpNHZ1/jKTliWHQ84ZkWD2OipxuNhZmeTvS080=
=/u2p
iQIzBAABCgAdFiEE0yaA1ZV9xxFr4pwUzxoQjQ565yAFAmJB1ZEACgkQzxoQjQ56
5yAw2xAAnX77doSlh8ySHfjpec1FkqsWlp8YAZ5jiXj6BFc/INwW8f1b9EHL62b7
lgQYZ5um7/XjZXSkKtL1mvqtRJLoLiFfNEN9zJluliWuey1UZbhO79cpG/jtKUqd
cB+Q/OKPqeyJCQlvazux3xORwYooXN7lesMbmLLaASzSATKamSzag8lL1WrGlJ44
O2fkn4YGvKc01cNV5Mk+2SzRF4LAKzk83tk0gkfmlUoqOSLRnBCqmzED3ZEk9PbS
4OPrvk4VIXXYEb2zL7VtABQRLxg3oYY/mu6xEVeLWAvWUzcyAxiPz07cbNsV16WK
Px69b4sXd5EVdTW2PTfH4xaIkPzwcJqq5vQOJw2l71qPdPJYfkf9kOuoyAt42owe
w/zzvn8xwKqqZKDvaM/pZs/HQDJ7ulGVQvfsSY36Lm6h8hpBpzhmjyTueZAGXzCI
rGYXZUUwHVhBDxF78gaHkiYE869trbj7icaL8cntG3Ok4JM4UySANTouNVfuQ58Q
a5ubb1omKMjzm0U+x26tZQX7TV0E+iAvFUrzE7Lj3HYdWTRxwhMQMXP15IA5Qd2o
DLOMtJcPZhtRl2vXzifPnQmKF0R30GOnqPTpQ4UHJSbt8wsZCmuxfu0FV7KCQFpv
O9mCgJAbc/nQDl6xDsLd9+dS7qzPqt6UdEikggsanxsPuA6p/S4=
=vJAj
-----END PGP SIGNATURE-----

View File

@ -9,8 +9,8 @@ $loader = require_once __DIR__.'/autoload.php';
if (!class_exists('AutoloadIncluder', false) && !interface_exists('AutoloadIncluder', false) && !trait_exists('AutoloadIncluder', false)) {
spl_autoload_call('RectorPrefix20220328\AutoloadIncluder');
}
if (!class_exists('ComposerAutoloaderInit784ff7722743891cd3bc094793583fb2', false) && !interface_exists('ComposerAutoloaderInit784ff7722743891cd3bc094793583fb2', false) && !trait_exists('ComposerAutoloaderInit784ff7722743891cd3bc094793583fb2', false)) {
spl_autoload_call('RectorPrefix20220328\ComposerAutoloaderInit784ff7722743891cd3bc094793583fb2');
if (!class_exists('ComposerAutoloaderInite10d76492c42050d4ac6c3834dd4a982', false) && !interface_exists('ComposerAutoloaderInite10d76492c42050d4ac6c3834dd4a982', false) && !trait_exists('ComposerAutoloaderInite10d76492c42050d4ac6c3834dd4a982', false)) {
spl_autoload_call('RectorPrefix20220328\ComposerAutoloaderInite10d76492c42050d4ac6c3834dd4a982');
}
if (!class_exists('Helmich\TypoScriptParser\Parser\AST\Statement', false) && !interface_exists('Helmich\TypoScriptParser\Parser\AST\Statement', false) && !trait_exists('Helmich\TypoScriptParser\Parser\AST\Statement', false)) {
spl_autoload_call('RectorPrefix20220328\Helmich\TypoScriptParser\Parser\AST\Statement');
@ -59,9 +59,9 @@ if (!function_exists('print_node')) {
return \RectorPrefix20220328\print_node(...func_get_args());
}
}
if (!function_exists('composerRequire784ff7722743891cd3bc094793583fb2')) {
function composerRequire784ff7722743891cd3bc094793583fb2() {
return \RectorPrefix20220328\composerRequire784ff7722743891cd3bc094793583fb2(...func_get_args());
if (!function_exists('composerRequiree10d76492c42050d4ac6c3834dd4a982')) {
function composerRequiree10d76492c42050d4ac6c3834dd4a982() {
return \RectorPrefix20220328\composerRequiree10d76492c42050d4ac6c3834dd4a982(...func_get_args());
}
}
if (!function_exists('scanPath')) {