restore types

This commit is contained in:
TomasVotruba 2020-07-27 08:56:25 +02:00
parent d94e529f29
commit 99db894192
62 changed files with 305 additions and 145 deletions

View File

@ -6,6 +6,7 @@ use PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\MethodDeclarationSniff;
use PhpCsFixer\Fixer\Import\GlobalNamespaceImportFixer;
use PhpCsFixer\Fixer\Operator\UnaryOperatorSpacesFixer;
use PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocAnnotationRemoveFixer;
use PhpCsFixer\Fixer\Phpdoc\NoSuperfluousPhpdocTagsFixer;
use PhpCsFixer\Fixer\Phpdoc\PhpdocTypesFixer;
use PhpCsFixer\Fixer\PhpUnit\PhpUnitStrictFixer;
use PhpCsFixer\Fixer\Strict\StrictComparisonFixer;
@ -43,6 +44,11 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$services->set(LineLengthFixer::class);
$services->set(NoSuperfluousPhpdocTagsFixer::class)
->call('configure', [[
'allow_mixed' => true,
]]);
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::PATHS, [

View File

@ -11,11 +11,17 @@ trait AttributeTrait
*/
private $attributes = [];
/**
* @return mixed|null
*/
public function getAttribute(string $name)
{
return $this->attributes[$name] ?? null;
}
/**
* @param mixed $value
*/
public function setAttribute(string $name, $value): void
{
$this->attributes[$name] = $value;

View File

@ -461,7 +461,7 @@ final class PhpDocInfo
return null;
}
private function getTypeOrMixed(?PhpDocTagValueNode $phpDocTagValueNode)
private function getTypeOrMixed(?PhpDocTagValueNode $phpDocTagValueNode): Type
{
if ($phpDocTagValueNode === null) {
return new MixedType();

View File

@ -180,7 +180,7 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD
return implode(', ', $itemsAsStrings);
}
private function correctArraySingleItemPrint($value, string $arrayItemAsString): string
private function correctArraySingleItemPrint(array $value, string $arrayItemAsString): string
{
if (count($value) !== 1) {
return $arrayItemAsString;

View File

@ -61,7 +61,10 @@ trait PrintTagValueNodeTrait
return $items;
}
private function shouldSkipFromExplicitKey($contentItem, $key): bool
/**
* @param mixed $contentItem
*/
private function shouldSkipFromExplicitKey($contentItem, string $key): bool
{
if (is_array($contentItem)) {
return true;

View File

@ -118,6 +118,9 @@ final class ChangedFilesDetector
return hash_file('sha1', $smartFileInfo->getRealPath());
}
/**
* @param mixed $value
*/
private function saveItemWithValue(string $key, $value): void
{
$cacheItem = $this->tagAwareAdapter->getItem($key);

View File

@ -11,6 +11,9 @@ final class ResolvedConstantStaticCollector
*/
private static $valuesByIdentifier = [];
/**
* @param mixed $value
*/
public static function collect(string $identifier, $value): void
{
// skip PHP values

View File

@ -75,6 +75,7 @@ final class ConstantReferenceIdentifierRestorer
}
/**
* @param mixed $value
* @return mixed|null
*/
private function matchIdentifierBasedOnResolverValue(array $identifierToResolvedValues, $value)

View File

@ -22,6 +22,9 @@ final class TypeStaticProbe
*/
private static $probeStorage;
/**
* @param mixed $value
*/
public static function recordArgumentType($value, string $method, int $argumentPosition): void
{
$probeItem = self::createProbeItem($value, $method, $argumentPosition);
@ -29,6 +32,9 @@ final class TypeStaticProbe
self::recordProbeItem($probeItem);
}
/**
* @param mixed $value
*/
public static function createProbeItem($value, string $method, int $argumentPosition): string
{
$type = self::resolveValueTypeToString($value);
@ -37,6 +43,9 @@ final class TypeStaticProbe
return implode(';', $data) . PHP_EOL;
}
/**
* @param object|mixed[]|mixed $value
*/
public static function resolveValueTypeToString($value): string
{
if (is_object($value)) {

View File

@ -13,6 +13,7 @@ final class TypeStaticProbeTest extends TestCase
{
/**
* @dataProvider provideData()
* @param mixed $value
*/
public function test($value, string $methodName, int $argumentPosition, string $expectedProbeItem): void
{
@ -26,6 +27,7 @@ final class TypeStaticProbeTest extends TestCase
}
/**
* @param mixed $value
* @dataProvider provideDataResolveValueTypeToString()
*/
public function testResolveValueTypeToString($value, string $expectedValueTypeString): void

View File

@ -258,6 +258,9 @@ final class NodeTypeResolver
}
}
/**
* @param ObjectType|string|mixed $requiredType
*/
private function ensureRequiredTypeIsStringOrObjectType($requiredType, string $location): void
{
if (is_string($requiredType)) {

View File

@ -65,11 +65,14 @@ final class PhpDocTypeRenamer
});
}
/**
* @param string[] $excludedClasses
*/
private function shouldSkip(
PhpDocParserNode $phpDocParserNode,
Node $phpParserNode,
string $namespacePrefix,
$excludedClasses
array $excludedClasses
): bool {
if (! $phpDocParserNode instanceof IdentifierTypeNode) {
return true;

View File

@ -31,6 +31,9 @@ final class ConditionEvaluator
return null;
}
/**
* @return bool|int
*/
private function evaluateVersionCompareCondition(VersionCompareCondition $versionCompareCondition)
{
$compareSign = $versionCompareCondition->getCompareSign();

View File

@ -61,11 +61,7 @@ final class ConditionResolver
if ($this->isVersionCompareFuncCall($expr->left)) {
/** @var FuncCall $funcCall */
$funcCall = $expr->left;
$versionCompareCondition = $this->resolveVersionCompareConditionForFuncCall($funcCall);
$expectedValue = $this->valueResolver->getValue($expr->right);
return new BinaryToVersionCompareCondition($versionCompareCondition, $binaryClass, $expectedValue);
return $this->resolveFuncCall($funcCall, $expr->right, $binaryClass);
}
if ($this->isVersionCompareFuncCall($expr->right)) {
@ -73,6 +69,10 @@ final class ConditionResolver
$funcCall = $expr->right;
$versionCompareCondition = $this->resolveVersionCompareConditionForFuncCall($funcCall);
if ($versionCompareCondition === null) {
return null;
}
$expectedValue = $this->valueResolver->getValue($expr->left);
return new BinaryToVersionCompareCondition($versionCompareCondition, $binaryClass, $expectedValue);
@ -90,7 +90,7 @@ final class ConditionResolver
return $this->nodeNameResolver->isName($node, 'version_compare');
}
private function resolveVersionCompareConditionForFuncCall(FuncCall $funcCall)
private function resolveVersionCompareConditionForFuncCall(FuncCall $funcCall): ?VersionCompareCondition
{
$firstVersion = $this->resolveArgumentValue($funcCall, 0);
if ($firstVersion === null) {
@ -121,4 +121,19 @@ final class ConditionResolver
return $version;
}
private function resolveFuncCall(
FuncCall $funcCall,
Expr $expr,
string $binaryClass
): ?BinaryToVersionCompareCondition {
$versionCompareCondition = $this->resolveVersionCompareConditionForFuncCall($funcCall);
if ($versionCompareCondition === null) {
return null;
}
$expectedValue = $this->valueResolver->getValue($expr);
return new BinaryToVersionCompareCondition($versionCompareCondition, $binaryClass, $expectedValue);
}
}

View File

@ -8,6 +8,9 @@ use Rector\Polyfill\Contract\ConditionInterface;
final class BinaryToVersionCompareCondition implements ConditionInterface
{
/**
* @var mixed
*/
private $expectedValue;
/**
@ -20,6 +23,9 @@ final class BinaryToVersionCompareCondition implements ConditionInterface
*/
private $versionCompareCondition;
/**
* @param mixed $expectedValue
*/
public function __construct(
VersionCompareCondition $versionCompareCondition,
string $binaryClass,
@ -40,6 +46,9 @@ final class BinaryToVersionCompareCondition implements ConditionInterface
return $this->binaryClass;
}
/**
* @return mixed
*/
public function getExpectedValue()
{
return $this->expectedValue;

View File

@ -24,7 +24,10 @@ final class NodesToReplaceCollector implements NodeCollectorInterface
return count($this->nodesToReplace) > 0;
}
public function getNodes()
/**
* @return Node[][]
*/
public function getNodes(): array
{
return $this->nodesToReplace;
}

View File

@ -34,7 +34,7 @@ final class OverrideGuard
array $templateFileInfos,
array $templateVariables,
Configuration $configuration
) {
): bool {
foreach ($templateFileInfos as $templateFileInfo) {
if (! $this->doesFileInfoAlreadyExist($templateVariables, $configuration, $templateFileInfo)) {
continue;

View File

@ -45,7 +45,7 @@ parameters:
'PHPUnit\TextUI\Configuration\Variable': 'PhpParser\Node\Expr\Variable'
# to allow installing with various phsptan versions without reporting old errors here
# reportUnmatchedIgnoredErrors: false
reportUnmatchedIgnoredErrors: false
checkGenericClassInNonGenericObjectType: false
@ -83,14 +83,6 @@ parameters:
ignoreErrors:
# false positive
-
message: '#Class with base \"[a-zA-Z0-9\\_]+\" name is already used in#'
paths:
- src/Console/Application.php
- src/PhpParser/Parser/Parser.php
# false positive
# - '#Call to function method_exists\(\) with string and (.*?) will always evaluate to false#'
- '#PHPDoc tag \@param for parameter \$node with type float is incompatible with native type PhpParser\\Node#'
# misuse of interface and class
@ -187,9 +179,6 @@ parameters:
- '#Method Rector\\NodeTypeResolver\\PHPStan\\Type\\TypeFactory\:\:createUnionOrSingleType\(\) should return PHPStan\\Type\\MixedType\|PHPStan\\Type\\UnionType but returns PHPStan\\Type\\Type#'
#phpstan seems to be missing the entire docblock, though it's there
- '#.*keepLivingCodeFromExpr.*#'
# test
- '#Class Rector\\DynamicTypeAnalysis\\Tests\\Rector\\ClassMethod\\AddArgumentTypeWithProbeDataRector\\Fixture\\SomeClass not found#'
@ -201,14 +190,8 @@ parameters:
- '#Class "Rector\\Utils\\(.*?)" is missing @see annotation with test case class reference#'
# mixed
- '#in iterable type Iterator#'
- '#with no typehint specified#'
- '#return type has no value type specified in iterable type array#'
- '#has no return typehint#'
- '#Offset int\|string\|null does not exist on array<PhpParser\\Node\\Stmt>\|null#'
- '#class-string<T of object>\|T of object#'
- '#with no value type specified in iterable type array#'
- '#type specified in iterable type (array|iterable)#'
# known values
- '#Offset 0 does not exist on array<PhpParser\\Node\\Stmt>\|null#'
@ -228,7 +211,6 @@ parameters:
- '#Method (.*?) returns bool type, so the name should start with is/has/was#'
# known value
# - "#^Parameter \\#1 \\$variable of class Rector\\\\Php70\\\\ValueObject\\\\VariableAssignPair constructor expects PhpParser\\\\Node\\\\Expr\\\\ArrayDimFetch\\|PhpParser\\\\Node\\\\Expr\\\\PropertyFetch\\|PhpParser\\\\Node\\\\Expr\\\\StaticPropertyFetch\\|PhpParser\\\\Node\\\\Expr\\\\Variable, PhpParser\\\\Node\\\\Expr given\\.$#"
- '#Cannot cast \(array<string\>\)\|string\|true to string#'
- '#In method "Rector\\BetterPhpDocParser\\AnnotationReader\\NodeAnnotationReader\:\:createPropertyReflectionFromPropertyNode", caught "Throwable" must be rethrown\. Either catch a more specific exception or add a "throw" clause in the "catch" block to propagate the exception\. More info\: http\://bit\.ly/failloud#'
@ -265,8 +247,6 @@ parameters:
- '#Parameter \#2 \$name of method Rector\\Core\\Rector\\AbstractRector\:\:isVariableName\(\) expects string, string\|null given#'
# mixed
- '#Property Rector\\Polyfill\\ValueObject\\BinaryToVersionCompareCondition\:\:\$expectedValue has no typehint specified#'
# node finder
- '#Method Rector\\Core\\PhpParser\\Node\\Manipulator\\MethodCallManipulator\:\:findAssignToVariableName\(\) should return PhpParser\\Node\\Expr\\Assign\|null but returns PhpParser\\Node\|null#'
@ -293,16 +273,21 @@ parameters:
count: 1
path: packages/better-php-doc-parser/src/PhpDocInfo/PhpDocInfo.php
-
message: "#in iterable type Iterator#"
paths:
- *Test.php
- *TestCase.php
# iterable types
- '#with no value type specified in iterable type array#'
- '#type specified in iterable type (array|iterable)#'
-
message: "#^Cognitive complexity for \"Rector\\\\BetterPhpDocParser\\\\Printer\\\\WhitespaceDetector\\:\\:detectOldWhitespaces\\(\\)\" is 18, keep it under 9$#"
count: 1
path: packages/better-php-doc-parser/src/Printer/WhitespaceDetector.php
# copy-pasted magic from symfony
-
message: '#Use default null value and nullable compare instead of isset/empty on object#'
path: 'rules/symfony/src/ServiceMapProvider.php'
-
message: "#^Parameter \\#1 \\$input of function array_splice expects array, array\\<PhpParser\\\\Node\\\\Stmt\\>\\|null given\\.$#"
count: 1
@ -349,12 +334,9 @@ parameters:
- '#Cognitive complexity for "Rector\\NetteKdyby\\ContributeEventClassResolver\:\:resolveGetterMethodByEventClassAndParam\(\)" is \d+, keep it under 9#'
- '#Parameter \#1 \$type of class PhpParser\\Node\\NullableType constructor expects PhpParser\\Node\\Identifier\|PhpParser\\Node\\Name\|string, PhpParser\\Node\\Identifier\|PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType given#'
- '#Parameter \#1 \$object of function get_class expects object, PhpParser\\Node\|null given#'
- '#Cognitive complexity for "Rector\\Core\\Application\\RectorApplication\:\:runOnFileInfos\(\)" is 10, keep it under 9#'
- '#Class "Rector\\FileSystemRector\\Rector\\Removing\\RemoveProjectFileRector" is missing @see annotation with test case class reference#'
- '#Class "Rector\\Php73\\Rector\\FuncCall\\SetCookieRector" is missing @see annotation with test case class reference#'
- '#Parameter \#1 \$type of method PhpParser\\Builder\\Param\:\:setType\(\) expects PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType\|string, PhpParser\\Node\\Identifier\|PhpParser\\Node\\Name\|PhpParser\\Node\\NullableType\|PhpParser\\Node\\UnionType given#'
- '#Parameter \#1 \$node of method Rector\\Core\\PhpParser\\Node\\BetterNodeFinder\:\:findFirstAncestorInstanceOf\(\) expects PhpParser\\Node, PhpParser\\Node\\Expr\\Variable\|null given#'
- '#Parameter \#1 \$assignAndRootExpr of method Rector\\MagicDisclosure\\NodeFactory\\NonFluentMethodCallFactory\:\:createFromAssignObjectAndMethodCalls\(\) expects Rector\\Core\\ValueObject\\AssignAndRootExpr, Rector\\Core\\ValueObject\\AssignAndRootExpr\|null given#'
- '#Parameter \#1 \$expr of method Rector\\MagicDisclosure\\Matcher\\ClassNameTypeMatcher\:\:doesExprMatchNames\(\) expects PhpParser\\Node\\Expr, PhpParser\\Node\\Expr\|null given#'
- '#Parameter \#1 \$objectType of method Rector\\Naming\\Naming\\PropertyNaming\:\:fqnToVariableName\(\) expects PHPStan\\Type\\ObjectType\|string, PHPStan\\Type\\Type given#'
- '#Method Rector\\Core\\PhpParser\\Node\\NodeFactory\:\:createConcat\(\) should return PhpParser\\Node\\Expr\\BinaryOp\\Concat\|null but returns PhpParser\\Node\\Expr#'
@ -382,10 +364,11 @@ parameters:
message: '#Separate function "Symfony\\Component\\DependencyInjection\\Loader\\Configurator\\ref\(\)" in method call to standalone row to improve readability#'
path: 'packages/rector-generator/config/config.php'
- '#Method Rector\\Nette\\NodeResolver\\FormVariableInputNameTypeResolver\:\:findPreviousAssignToVariable\(\) should return PhpParser\\Node\\Expr\\Assign\|null but returns PhpParser\\Node\|null#'
- '#Method Rector\\Nette\\NodeResolver\\FormVariableInputNameTypeResolver\:\:resolveFromGetComponentMethodCall\(\) should return array<string, string\> but returns array<int\|string, string\>#'
- '#Method Rector\\Core\\PhpParser\\Node\\BetterNodeFinder\:\:findPreviousAssignToExpr\(\) should return PhpParser\\Node\\Expr\\Assign\|null but returns PhpParser\\Node\|null#'
- '#Method Rector\\Nette\\FormControlTypeResolver\\GetComponentMethodCallFormControlTypeResolver\:\:resolve\(\) should return array<string, string\> but returns array<int\|string, string\>#'
- '#Class with base "LexerFactory" name is already used in "PHPStan\\Parser\\LexerFactory", "Rector\\Core\\PhpParser\\Parser\\LexerFactory"\. Use unique name to make classes easy to recognize#'
- '#Parameter \#1 \$shortControlString of method Rector\\NetteCodeQuality\\Rector\\Assign\\MakeGetComponentAssignAnnotatedRector\:\:resolveTypeFromShortControlNameAndVariable\(\) expects PhpParser\\Node\\Scalar\\String_, PhpParser\\Node\\Expr\|null given#'
- '#Parameter \#1 \$variable of class Rector\\Php70\\ValueObject\\VariableAssignPair constructor expects PhpParser\\Node\\Expr\\ArrayDimFetch\|PhpParser\\Node\\Expr\\PropertyFetch\|PhpParser\\Node\\Expr\\StaticPropertyFetch\|PhpParser\\Node\\Expr\\Variable, PhpParser\\Node\\Expr given#'
# is nested expr
- '#Access to an undefined property PhpParser\\Node\\Expr\:\:\$expr#'
- '#Cognitive complexity for "Rector\\DeadCode\\NodeManipulator\\LivingCodeManipulator\:\:keepLivingCodeFromExpr\(\)" is \d+, keep it under 9#'
- '#Class with base "LexerFactory" name is already used in "PHPStan\\Parser\\LexerFactory", "Rector\\Core\\PhpParser\\Parser\\LexerFactory"\. Use unique name to make classes easy to recognize#'

View File

@ -104,7 +104,7 @@ final class ClassAnalyzer
return false;
}
private function hasAllPropertiesWithSerialize(Class_ $class)
private function hasAllPropertiesWithSerialize(Class_ $class): bool
{
foreach ($class->stmts as $stmt) {
if (! $stmt instanceof Property) {

View File

@ -81,22 +81,22 @@ PHP
return $node;
}
private function shouldSkip($node): bool
private function shouldSkip(Assign $assign): bool
{
if (! $node->var instanceof Array_ && ! $node->var instanceof List_) {
if (! $assign->var instanceof Array_ && ! $assign->var instanceof List_) {
return true;
}
if (! $node->expr instanceof Array_) {
if (! $assign->expr instanceof Array_) {
return true;
}
if (count($node->var->items) !== count($node->expr->items)) {
if (count($assign->var->items) !== count($assign->expr->items)) {
return true;
}
// is value swap
return $this->isValueSwap($node->var, $node->expr);
return $this->isValueSwap($assign->var, $assign->expr);
}
/**

View File

@ -74,16 +74,18 @@ PHP
return $node;
}
private function determineDelimiter(FuncCall $funcCall)
private function determineDelimiter(FuncCall $funcCall): ?string
{
$concat = $this->getUppermostConcat($funcCall);
if ($concat === null) {
return null;
}
$leftMostConcatNode = $concat->left;
while ($leftMostConcatNode instanceof Concat) {
$leftMostConcatNode = $leftMostConcatNode->left;
}
$rightMostConcatNode = $concat->right;
while ($rightMostConcatNode instanceof Concat) {
$rightMostConcatNode = $rightMostConcatNode->right;
@ -92,10 +94,12 @@ PHP
if (! $leftMostConcatNode instanceof String_) {
return null;
}
$possibleLeftDelimiter = Strings::substring($leftMostConcatNode->value, 0, 1);
if (! $rightMostConcatNode instanceof String_) {
return null;
}
$possibleRightDelimiter = Strings::substring(rtrim($rightMostConcatNode->value, self::ALL_MODIFIERS), -1, 1);
if ($possibleLeftDelimiter === $possibleRightDelimiter) {
return $possibleLeftDelimiter;

View File

@ -102,7 +102,7 @@ PHP
return $node;
}
private function ensurePreferenceIsValid($preference): void
private function ensurePreferenceIsValid(string $preference): void
{
$allowedPreferences = [self::PREFER_THIS, self::PREFER_SELF];
if (in_array($preference, $allowedPreferences, true)) {

View File

@ -205,10 +205,13 @@ PHP
$useUse->alias = null;
}
private function renameTraitUse(string $lastName, TraitUse $traitUse, $usedName): void
/**
* @param Name|Identifier $usedNameNode
*/
private function renameTraitUse(string $lastName, TraitUse $traitUse, Node $usedNameNode): void
{
foreach ($traitUse->traits as $key => $traitName) {
if (! $this->areNamesEqual($traitName, $usedName)) {
if (! $this->areNamesEqual($traitName, $usedNameNode)) {
continue;
}
@ -216,45 +219,60 @@ PHP
}
}
private function renameClass(string $lastName, Class_ $class, $usedName): void
/**
* @param Name|Identifier $usedNameNode
*/
private function renameClass(string $lastName, Class_ $class, Node $usedNameNode): void
{
if ($class->name !== null && $this->areNamesEqual($class->name, $usedName)) {
if ($class->name !== null && $this->areNamesEqual($class->name, $usedNameNode)) {
$class->name = new Identifier($lastName);
}
if ($class->extends !== null && $this->areNamesEqual($class->extends, $usedName)) {
if ($class->extends !== null && $this->areNamesEqual($class->extends, $usedNameNode)) {
$class->extends = new Name($lastName);
}
foreach ($class->implements as $key => $implementNode) {
if ($this->areNamesEqual($implementNode, $usedName)) {
if ($this->areNamesEqual($implementNode, $usedNameNode)) {
$class->implements[$key] = new Name($lastName);
}
}
}
private function renameParam(string $lastName, $parentNode, $usedName): void
/**
* @param Name|Identifier $usedNameNode
*/
private function renameParam(string $lastName, Node $parentNode, Node $usedNameNode): void
{
if ($parentNode->type !== null && $this->areNamesEqual($parentNode->type, $usedName)) {
if ($parentNode->type !== null && $this->areNamesEqual($parentNode->type, $usedNameNode)) {
$parentNode->type = new Name($lastName);
}
}
private function renameNew(string $lastName, $parentNode, $usedName): void
/**
* @param Name|Identifier $usedNameNode
*/
private function renameNew(string $lastName, Node $parentNode, Node $usedNameNode): void
{
if ($this->areNamesEqual($parentNode->class, $usedName)) {
if ($this->areNamesEqual($parentNode->class, $usedNameNode)) {
$parentNode->class = new Name($lastName);
}
}
private function renameClassMethod(string $lastName, ClassMethod $classMethod, $usedName): void
/**
* @param Name|Identifier $usedNameNode
*/
private function renameClassMethod(string $lastName, ClassMethod $classMethod, Node $usedNameNode): void
{
if ($classMethod->returnType !== null && $this->areNamesEqual($classMethod->returnType, $usedName)) {
if ($classMethod->returnType !== null && $this->areNamesEqual($classMethod->returnType, $usedNameNode)) {
$classMethod->returnType = new Name($lastName);
}
}
private function renameInterface(string $lastName, Interface_ $interface, $usedName): void
/**
* @param Name|Identifier $usedName
*/
private function renameInterface(string $lastName, Interface_ $interface, Node $usedName): void
{
foreach ($interface->extends as $key => $extendInterfaceName) {
if ($this->areNamesEqual($extendInterfaceName, $usedName)) {

View File

@ -67,7 +67,7 @@ final class CountManipulator
return $this->isCountWithExpression($greater->left, $expr);
}
private function processGreaterOrEqual(GreaterOrEqual $greaterOrEqual, Expr $expr)
private function processGreaterOrEqual(GreaterOrEqual $greaterOrEqual, Expr $expr): bool
{
if (! $this->isNumber($greaterOrEqual->right, 1)) {
return false;

View File

@ -28,8 +28,6 @@ use PhpParser\Node\Expr\StaticPropertyFetch;
use PhpParser\Node\Expr\UnaryMinus;
use PhpParser\Node\Expr\UnaryPlus;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar;
final class LivingCodeManipulator
@ -40,13 +38,11 @@ final class LivingCodeManipulator
*/
public function keepLivingCodeFromExpr($expr): array
{
if (! $expr instanceof Node ||
$expr instanceof Closure ||
$expr instanceof Name ||
$expr instanceof Identifier ||
$expr instanceof Scalar ||
$expr instanceof ConstFetch
) {
if (! $expr instanceof Expr) {
return [];
}
if ($expr instanceof Closure || $expr instanceof Scalar || $expr instanceof ConstFetch) {
return [];
}
@ -72,8 +68,7 @@ final class LivingCodeManipulator
);
}
if ($expr instanceof ClassConstFetch ||
$expr instanceof StaticPropertyFetch) {
if ($expr instanceof ClassConstFetch || $expr instanceof StaticPropertyFetch) {
return array_merge(
$this->keepLivingCodeFromExpr($expr->class),
$this->keepLivingCodeFromExpr($expr->name)
@ -81,10 +76,9 @@ final class LivingCodeManipulator
}
if ($this->isBinaryOpWithoutChange($expr)) {
return array_merge(
$this->keepLivingCodeFromExpr($expr->left),
$this->keepLivingCodeFromExpr($expr->right)
);
/** @var BinaryOp $binaryOp */
$binaryOp = $expr;
return $this->processBinary($binaryOp);
}
if ($expr instanceof Instanceof_) {
@ -95,15 +89,13 @@ final class LivingCodeManipulator
}
if ($expr instanceof Isset_) {
return array_merge(...array_map(function (Expr $expr): array {
return $this->keepLivingCodeFromExpr($expr);
}, $expr->vars));
return $this->processIsset($expr);
}
return [$expr];
}
private function isNestedExpr($expr): bool
private function isNestedExpr(Expr $expr): bool
{
return $expr instanceof Cast ||
$expr instanceof Empty_ ||
@ -114,15 +106,33 @@ final class LivingCodeManipulator
$expr instanceof Clone_;
}
private function isBinaryOpWithoutChange($expr): bool
private function isBinaryOpWithoutChange(Expr $expr): bool
{
return $expr instanceof BinaryOp
&& ! (
$expr instanceof LogicalAnd ||
$expr instanceof BooleanAnd ||
$expr instanceof LogicalOr ||
$expr instanceof BooleanOr ||
$expr instanceof Coalesce
);
if (! $expr instanceof BinaryOp) {
return false;
}
return ! (
$expr instanceof LogicalAnd ||
$expr instanceof BooleanAnd ||
$expr instanceof LogicalOr ||
$expr instanceof BooleanOr ||
$expr instanceof Coalesce
);
}
private function processIsset(Isset_ $isset): array
{
return array_merge(...array_map(function (Expr $expr): array {
return $this->keepLivingCodeFromExpr($expr);
}, $isset->vars));
}
private function processBinary(BinaryOp $binaryOp): array
{
return array_merge(
$this->keepLivingCodeFromExpr($binaryOp->left),
$this->keepLivingCodeFromExpr($binaryOp->right)
);
}
}

View File

@ -64,7 +64,10 @@ PHP
return $node;
}
private function getArrayItemsWithDuplicatedKey(Array_ $array)
/**
* @return ArrayItem[][]
*/
private function getArrayItemsWithDuplicatedKey(Array_ $array): array
{
$arrayItemsByKeys = [];

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Rector\Decouple\Tests\Rector\DecoupleClassMethodToOwnClassRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\Decouple\Rector\DecoupleClassMethodToOwnClassRector;
use Rector\Decouple\Tests\Rector\DecoupleClassMethodToOwnClassRector\Source\AbstractFather;
@ -22,7 +23,7 @@ final class DecoupleClassMethodToOwnClassRectorTest extends AbstractRectorTestCa
$this->assertFileEquals($expectedContentFilePath, $expectedFilePath);
}
public function provideData()
public function provideData(): Iterator
{
yield [
new SmartFileInfo(__DIR__ . '/Fixture/basic.php.inc'),

View File

@ -169,7 +169,7 @@ PHP
FuncCall $funcCall,
ArrayFunctionToMethodCall $arrayFunctionToMethodCall,
PropertyFetch $propertyFetch
) {
): ?MethodCall {
if ($arrayFunctionToMethodCall->getArrayMethod() && $this->isArrayType($funcCall->args[0]->value)) {
return new MethodCall($propertyFetch, $arrayFunctionToMethodCall->getArrayMethod(), $funcCall->args);
}

View File

@ -111,6 +111,9 @@ PHP
$chainMethodCalls = $this->chainMethodCallNodeAnalyzer->collectAllMethodCallsInChain($methodCall);
$assignAndRootExpr = $this->chainMethodCallRootExtractor->extractFromMethodCalls($chainMethodCalls);
if ($assignAndRootExpr === null) {
return null;
}
if ($this->shouldSkip($assignAndRootExpr, $chainMethodCalls)) {
return null;
@ -151,7 +154,10 @@ PHP
return $node;
}
private function isHandledByReturn($node): bool
/**
* @param MethodCall|Return_ $node
*/
private function isHandledByReturn(Node $node): bool
{
if ($node instanceof MethodCall) {
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
@ -167,12 +173,8 @@ PHP
/**
* @param MethodCall[] $chainMethodCalls
*/
private function shouldSkip(?AssignAndRootExpr $assignAndRootExpr, array $chainMethodCalls): bool
private function shouldSkip(AssignAndRootExpr $assignAndRootExpr, array $chainMethodCalls): bool
{
if ($assignAndRootExpr === null) {
return true;
}
if (! $this->chainMethodCallNodeAnalyzer->isCalleeSingleType($assignAndRootExpr, $chainMethodCalls)) {
return true;
}
@ -183,7 +185,10 @@ PHP
);
}
private function removeCurrentNode($node): void
/**
* @param MethodCall|Return_ $node
*/
private function removeCurrentNode(Node $node): void
{
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
if ($parentNode instanceof Assign) {

View File

@ -74,7 +74,7 @@ final class VariableRenamer
);
}
private function renameVariableIfMatchesName(Variable $variable, string $oldName, string $expectedName)
private function renameVariableIfMatchesName(Variable $variable, string $oldName, string $expectedName): ?Variable
{
if (! $this->nodeNameResolver->isName($variable, $oldName)) {
return null;

View File

@ -8,5 +8,5 @@ use Rector\NetteCodeQuality\NodeResolver\MethodNamesByInputNamesResolver;
interface MethodNamesByInputNamesResolverAwareInterface
{
public function setResolver(MethodNamesByInputNamesResolver $methodNamesByInputNamesResolver);
public function setResolver(MethodNamesByInputNamesResolver $methodNamesByInputNamesResolver): void;
}

View File

@ -199,8 +199,11 @@ PHP
return is_a($varStaticType->getClassName(), 'Nette\Application\UI\Control', true);
}
private function resolveTypeFromShortControlNameAndVariable(String_ $shortControlString, Scope $scope, Expr $expr)
{
private function resolveTypeFromShortControlNameAndVariable(
String_ $shortControlString,
Scope $scope,
Expr $expr
): Type {
$componentName = $this->getValue($shortControlString);
$methodName = sprintf('createComponent%s', ucfirst($componentName));

View File

@ -181,7 +181,7 @@ final class EregToPcreTransformer
return [implode('|', $r), $i];
}
private function processBracket(string $content, int $i, int $l, array &$r, int $rr)
private function processBracket(string $content, int $i, int $l, array &$r, int $rr): int
{
// special case
if ($i + 1 < $l && $content[$i + 1] === ')') {

View File

@ -19,8 +19,8 @@ use Rector\Core\ValueObject\PhpVersionFeature;
/**
* Convert legacy setcookie arguments to new array options
*
* @see \Rector\Php73\Tests\Rector\FuncCall\SetcookieRector\SetcookieRectorTest
* @see \Rector\Php73\Tests\Rector\FuncCall\SetcookieRector\SetCookieRectorTest
*
* @see https://www.php.net/setcookie
* @see https://wiki.php.net/rfc/same-site-cookie
*/

View File

@ -156,9 +156,10 @@ PHP
}
/**
* @param ClassMethod|Function_ $functionLike
* @return Foreach_[]
*/
private function findForeachesOverTokenVariable($functionLike, Expr $assignedExpr): array
private function findForeachesOverTokenVariable(FunctionLike $functionLike, Expr $assignedExpr): array
{
return $this->betterNodeFinder->find((array) $functionLike->stmts, function (Node $node) use (
$assignedExpr

View File

@ -9,7 +9,7 @@ use Rector\Core\Configuration\ChangeConfiguration;
final class RenamedClassesCollector
{
/**
* @var string[]
* @var array<string, string>
*/
private $oldToNewClass = [];
@ -29,7 +29,7 @@ final class RenamedClassesCollector
}
/**
* @return string[]
* @return array<string, string>
*/
public function getOldToNewClasses(): array
{

View File

@ -78,6 +78,9 @@ final class ClassRenamer
$this->betterNodeFinder = $betterNodeFinder;
}
/**
* @param array<string, string> $oldToNewClasses
*/
public function renameNode(Node $node, array $oldToNewClasses): ?Node
{
$this->refactorPhpDoc($node, $oldToNewClasses);
@ -101,7 +104,7 @@ final class ClassRenamer
* Replace types in @var/@param/@return/@throws,
* Doctrine @ORM entity targetClass, Serialize, Assert etc.
*/
private function refactorPhpDoc(Node $node, $oldToNewClasses): void
private function refactorPhpDoc(Node $node, array $oldToNewClasses): void
{
if (! $this->docBlockManipulator->hasNodeTypeTags($node)) {
return;

View File

@ -33,7 +33,7 @@ final class RenameClassRector extends AbstractRector
private $classRenamer;
/**
* @param string[] $oldToNewClasses
* @param array<string, string> $oldToNewClasses
*/
public function __construct(
ChangeConfiguration $changeConfiguration,

View File

@ -147,8 +147,9 @@ PHP
/**
* @param MethodCall|StaticCall|ClassMethod $node
* @param string|string[] $newMethod
*/
private function skipClassMethod($node, $newMethod, string $type): bool
private function skipClassMethod(Node $node, $newMethod, string $type): bool
{
if (! $node instanceof ClassMethod) {
return false;

View File

@ -9,6 +9,7 @@ use PhpParser\Node;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Interface_;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
@ -176,10 +177,15 @@ CODE_SAMPLE
$this->renamedClassesCollector->addClassRename($implementedInterfaceName, $className);
}
private function resolveClassFileLocation(string $implementedInterfaceName)
private function resolveClassFileLocation(string $implementedInterfaceName): string
{
$reflectionClass = new ReflectionClass($implementedInterfaceName);
return $reflectionClass->getFileName();
$fileName = $reflectionClass->getFileName();
if (! $fileName) {
throw new ShouldNotHappenException();
}
return $fileName;
}
private function removeOrReplaceImlementedInterface(string $implementedInterfaceName, Class_ $class, int $key): void

View File

@ -95,17 +95,17 @@ PHP
return $node;
}
private function shouldSkipProperty($node): bool
private function shouldSkipProperty(Property $property): bool
{
if (count($node->props) !== 1) {
if (count($property->props) !== 1) {
return true;
}
if ($node->type === null) {
if ($property->type === null) {
return true;
}
return $node->type instanceof NullableType;
return $property->type instanceof NullableType;
}
private function isPropertyNullChecked(PropertyProperty $onlyPropertyProperty): bool
@ -171,7 +171,7 @@ PHP
return $isIdenticalOrNotIdenticalToNull;
}
private function isBooleanNot(Class_ $class, PropertyProperty $onlyPropertyProperty)
private function isBooleanNot(Class_ $class, PropertyProperty $onlyPropertyProperty): bool
{
$isBooleanNot = false;

View File

@ -144,6 +144,9 @@ final class ReturnClosurePrinter
return Strings::replace($content, '#\)->#', $nextCallIndentReplacement);
}
/**
* @param mixed[]|mixed $value
*/
private function shouldSkipObjectConfiguration($value): bool
{
if (! is_array($value)) {

View File

@ -195,6 +195,9 @@ final class ServiceMapProvider
return $data;
}
/**
* @param string|int $key
*/
private function convertedNestedArrayOrXml(array $value, array $data, $key): array
{
foreach ($value as $subKey => $subValue) {

View File

@ -189,8 +189,11 @@ final class NonInformativeReturnTagRemover
return null;
}
private function removeShortObjectType(Type $returnType, $returnTagValueNode, ?PhpDocInfo $phpDocInfo): void
{
private function removeShortObjectType(
Type $returnType,
ReturnTagValueNode $returnTagValueNode,
?PhpDocInfo $phpDocInfo
): void {
if (! $returnType instanceof ShortenedObjectType) {
return;
}

View File

@ -142,7 +142,7 @@ PHP
private function refactorClassMethodWithTypehintByParameterPosition(
ClassMethod $classMethod,
$typehintByParameterPosition
array $typehintByParameterPosition
): void {
foreach ($typehintByParameterPosition as $parameterPosition => $type) {
if (! isset($classMethod->params[$parameterPosition])) {

View File

@ -281,7 +281,7 @@ PHP
$this->notifyNodeFileInfo($currentClassMethod);
}
private function isVoidDueToThrow(Node $node, $inferredReturnNode): bool
private function isVoidDueToThrow(Node $node, Node $inferredReturnNode): bool
{
if (! $inferredReturnNode instanceof Identifier) {
return false;

View File

@ -7,12 +7,12 @@ namespace Rector\Core\Configuration;
final class ChangeConfiguration
{
/**
* @var string[]
* @var array<string, string>
*/
private $oldToNewClasses = [];
/**
* @param string[] $oldToNewClasses
* @param array<string, string> $oldToNewClasses
*/
public function setOldToNewClasses(array $oldToNewClasses): void
{
@ -20,7 +20,7 @@ final class ChangeConfiguration
}
/**
* @return string[]
* @return array<string, string>
*/
public function getOldToNewClasses(): array
{

View File

@ -46,6 +46,9 @@ final class RectorServiceArgumentCollector
}
}
/**
* @param mixed $argumentValue
*/
private function addArgumentValue(string $serviceClassName, string $argumentName, $argumentValue): void
{
if (! isset($this->cachedRectorServiceKeyArguments[$serviceClassName][$argumentName])) {

View File

@ -96,6 +96,9 @@ final class BinaryOpManipulator
return new $inversedNodeClass($binaryOp->left, $binaryOp->right);
}
/**
* @param string|callable $firstCondition
*/
private function validateCondition($firstCondition): void
{
if (is_callable($firstCondition)) {

View File

@ -126,7 +126,7 @@ final class ClassInsertManipulator
return false;
}
private function hasClassConstant(Class_ $class, string $constantName)
private function hasClassConstant(Class_ $class, string $constantName): bool
{
foreach ($class->getConstants() as $classConst) {
if ($this->nodeNameResolver->isName($classConst, $constantName)) {

View File

@ -86,7 +86,7 @@ final class IdentifierManipulator
));
}
private function resolveOldMethodName(Node $node)
private function resolveOldMethodName(Node $node): ?string
{
if ($node instanceof StaticCall || $node instanceof MethodCall) {
return $this->nodeNameResolver->getName($node->name);

View File

@ -156,7 +156,7 @@ final class NodeFactory
}
/**
* Creates "($arg)"
* @param mixed $argument
*/
public function createArg($argument): Arg
{
@ -314,11 +314,17 @@ final class NodeFactory
return $property;
}
/**
* @param mixed $value
*/
public function createPrivateClassConst(string $name, $value): ClassConst
{
return $this->createClassConstant($name, $value, Class_::MODIFIER_PRIVATE);
}
/**
* @param mixed $value
*/
public function createPublicClassConst(string $name, $value): ClassConst
{
return $this->createClassConstant($name, $value, Class_::MODIFIER_PUBLIC);
@ -366,6 +372,7 @@ final class NodeFactory
}
/**
* @param mixed $item
* @param string|int|null $key
*/
private function createArrayItem($item, $key = null): ArrayItem
@ -452,6 +459,9 @@ final class NodeFactory
$phpDocInfo->changeVarType($type);
}
/**
* @param mixed $value
*/
private function createClassConstant(string $name, $value, int $modifier): ClassConst
{
$value = BuilderHelpers::normalizeValue($value);

View File

@ -56,6 +56,9 @@ final class ValueResolver
$this->nodeTypeResolver = $nodeTypeResolver;
}
/**
* @param mixed $value
*/
public function isValue(Expr $expr, $value): bool
{
return $this->getValue($expr) === $value;
@ -188,7 +191,7 @@ final class ValueResolver
return $fileInfo->getPathname();
}
private function resolveClassConstFetch(ClassConstFetch $classConstFetch)
private function resolveClassConstFetch(ClassConstFetch $classConstFetch): string
{
$class = $this->nodeNameResolver->getName($classConstFetch->class);
$constant = $this->nodeNameResolver->getName($classConstFetch->name);
@ -219,10 +222,10 @@ final class ValueResolver
return $this->constExprEvaluator->evaluateDirectly($classConstNode->consts[0]->value);
}
private function processConcat($expr, bool $resolvedClassReference): string
private function processConcat(Concat $concat, bool $resolvedClassReference): string
{
return $this->getValue($expr->left, $resolvedClassReference) . $this->getValue(
$expr->right,
return $this->getValue($concat->left, $resolvedClassReference) . $this->getValue(
$concat->right,
$resolvedClassReference
);
}

View File

@ -84,6 +84,9 @@ trait NodeFactoryTrait
return new ConstFetch(new Name('true'));
}
/**
* @param mixed $argument
*/
protected function createArg($argument): Arg
{
return $this->nodeFactory->createArg($argument);

View File

@ -26,17 +26,26 @@ trait ValueResolverTrait
$this->valueResolver = $valueResolver;
}
/**
* @return mixed|mixed[]
*/
protected function getValue(Expr $expr, bool $resolvedClassReference = false)
{
return $this->valueResolver->getValue($expr, $resolvedClassReference);
}
/**
* @param mixed $expectedValue
*/
protected function isValue(Expr $expr, $expectedValue): bool
{
return $this->getValue($expr) === $expectedValue;
}
protected function isValues(Expr $expr, $expectedValues): bool
/**
* @param mixed[] $expectedValues
*/
protected function isValues(Expr $expr, array $expectedValues): bool
{
foreach ($expectedValues as $expectedValue) {
if ($this->isValue($expr, $expectedValue)) {

View File

@ -200,6 +200,9 @@ PHP
return ! $this->isInCorrectScope($node, $parameterConfiguration);
}
/**
* @param mixed $defaultValue
*/
private function addClassMethodParam(
ClassMethod $classMethod,
string $name,
@ -215,7 +218,7 @@ PHP
$classMethod->params[$position] = $param;
}
private function processStaticCall(StaticCall $staticCall, int $position, $name): void
private function processStaticCall(StaticCall $staticCall, int $position, string $name): void
{
if (! $staticCall->class instanceof Name) {
return;

View File

@ -150,6 +150,9 @@ PHP
}
}
/**
* @param mixed $value
*/
private function normalizeValueToArgument($value): Arg
{
// class constants → turn string to composite
@ -193,7 +196,7 @@ PHP
* @param Arg[] $argumentNodes
* @param mixed[] $before
*/
private function resolveArgumentValuesToBeforeRecipe(array $argumentNodes, int $position, array $before)
private function resolveArgumentValuesToBeforeRecipe(array $argumentNodes, int $position, array $before): array
{
$argumentValues = [];

View File

@ -6,5 +6,8 @@ namespace Rector\Core\Testing\Contract;
interface RunnableInterface
{
/**
* @return mixed
*/
public function run();
}

View File

@ -98,6 +98,9 @@ abstract class AbstractGenericRectorTestCase extends AbstractKernelTestCase
return StaticFixtureFinder::yieldDirectory($directory, $suffix);
}
/**
* @param mixed $value
*/
protected function setParameter(string $name, $value): void
{
$parameterProvider = self::$container->get(ParameterProvider::class);

View File

@ -14,7 +14,7 @@ final class ComposerJsonParserTest extends AbstractKernelTestCase
/**
* @dataProvider dataProvider
*/
public function test($expectedVersion, string $version): void
public function test(string $expectedVersion, string $version): void
{
$actualPhpVersion = $this->getComposerJsonPhpVersion($version);

View File

@ -28,6 +28,7 @@ final class ValueResolverTest extends AbstractKernelTestCase
}
/**
* @param mixed $expected
* @dataProvider dataProvider
*/
public function test($expected, Expr $expr): void

View File

@ -78,7 +78,7 @@ final class RequireStringArgumentInMethodCallRule implements Rule
}
/**
* @param array<string, int> $positionsByMethods
* @param array<string, array<int>> $positionsByMethods
*/
private function matchPositions(
MethodCall $methodCall,
@ -86,7 +86,7 @@ final class RequireStringArgumentInMethodCallRule implements Rule
string $desiredType,
array $positionsByMethods,
string $methodName
) {
): ?array {
if (! $this->isNodeVarType($methodCall, $scope, $desiredType)) {
return null;
}