Merge pull request #2435 from rectorphp/fixes

Various fixes
This commit is contained in:
Tomáš Votruba 2019-12-15 21:10:34 +01:00 committed by GitHub
commit d337f6e6e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 129 additions and 65 deletions

View File

@ -199,7 +199,7 @@
"ecs check bin packages src tests utils compiler --fix --ansi",
"ci/clean_trailing_spaces.sh"
],
"phpstan": "phpstan analyse packages src tests compiler/src --ansi",
"phpstan": "phpstan analyse packages src tests compiler/src --ansi --error-format symplify",
"changelog": [
"changelog-linker dump-merges --in-categories",
"changelog-linker link",

View File

@ -69,7 +69,7 @@ final class OriginalSpacingRestorer
if ($node instanceof DoctrineTagNodeInterface) {
// give back "\s+\*" as well
if (($i - 1) > $start) { // do not overlap to previous node
if ($i - 1 > $start) { // do not overlap to previous node
if (isset($tokens[$i - 1]) && $tokens[$i - 1][1] === Lexer::TOKEN_PHPDOC_EOL) {
$previousTokenValue = $tokens[$i - 1][0];
if (Strings::match($previousTokenValue, '#\s+\*#m')) {

View File

@ -63,9 +63,13 @@ PHP
}
$functionName = $this->getValue($node->args[0]->value);
if (! is_string($functionName)) {
return null;
}
$args = [];
$args[] = new Arg($node->args[1]->value, false, true);
return $this->createFunction($functionName, $args);
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace Rector\CodingStyle\Tests\Rector\FuncCall\CallUserFuncCallToVariadicRector\Fixture;
class SkipUnknownValue
{
public function run($name)
{
call_user_func_array($name, $items);
}
}

View File

@ -651,7 +651,7 @@ final class NodeTypeResolver
return $originalType;
}
private function getScopeNode(Node $node): Node
private function getScopeNode(Node $node): ?Node
{
return $node->getAttribute(AttributeKey::METHOD_NODE)
?? $node->getAttribute(AttributeKey::FUNCTION_NODE)
@ -665,6 +665,10 @@ final class NodeTypeResolver
{
$scope = $this->getScopeNode($variable);
if ($scope === null) {
return [];
}
return $this->betterNodeFinder->find((array) $scope->stmts, function (Node $node) use ($variable): bool {
return $node instanceof Variable && $node->name === $variable->name;
});

View File

@ -622,7 +622,8 @@ final class StaticTypeMapper
if ($typeNode instanceof GenericTypeNode) {
if ($typeNode->type instanceof IdentifierTypeNode) {
if ($typeNode->type->name === 'array') {
$typeName = $typeNode->type->name;
if (in_array($typeName, ['array', 'iterable'], true)) {
$genericTypes = [];
foreach ($typeNode->genericTypes as $genericTypeNode) {
$genericTypes[] = $this->mapPHPStanPhpDocTypeNodeToPHPStanType($genericTypeNode, $node);
@ -630,7 +631,11 @@ final class StaticTypeMapper
$genericType = $this->typeFactory->createMixedPassedOrUnionType($genericTypes);
return new ArrayType(new MixedType(), $genericType);
if ($typeName === 'array') {
return new ArrayType(new MixedType(), $genericType);
}
return new IterableType(new MixedType(), $genericType);
}
}
}

View File

@ -132,7 +132,7 @@ PHP
}
// simple check argument count fits to method required args
if ((count($values) % $numberOfParameters) !== 0) {
if (count($values) % $numberOfParameters !== 0) {
return null;
}

View File

@ -83,7 +83,7 @@ PHP
unset($node->stmts[$key]);
}
$node->stmts = array_merge($node->stmts, (array) $proccesed);
$node->stmts = array_merge((array) $node->stmts, (array) $proccesed);
return $node;
}

View File

@ -118,6 +118,9 @@ final class NormalizeNamespaceByPSR4ComposerAutoloadRector extends AbstractRecto
$psr4Autoloads = $this->psR4AutoloadPathsProvider->provide();
foreach ($psr4Autoloads as $namespace => $path) {
// remove extra slash
$path = rtrim($path, '/');
if (Strings::startsWith($smartFileInfo->getRelativeDirectoryPath(), $path)) {
$expectedNamespace = $namespace . $this->resolveExtraNamespace($smartFileInfo, $path);

View File

@ -6,6 +6,7 @@ namespace Rector\Php53\Rector\Ternary;
use PhpParser\Node;
use PhpParser\Node\Expr\Ternary;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
@ -55,6 +56,7 @@ PHP
return null;
}
$node->setAttribute(AttributeKey::ORIGINAL_NODE, null);
$node->if = null;
return $node;

View File

@ -1,5 +1,7 @@
<?php
namespace Rector\Php53\Tests\Rector\Ternary\TernaryToElvisRector\Fixture;
function elvis()
{
$value = $a ? $a : false;
@ -9,6 +11,8 @@ function elvis()
-----
<?php
namespace Rector\Php53\Tests\Rector\Ternary\TernaryToElvisRector\Fixture;
function elvis()
{
$value = $a ?: false;

View File

@ -1,5 +1,7 @@
<?php
namespace Rector\Php53\Tests\Rector\Ternary\TernaryToElvisRector\Fixture;
function elvisRemoveParenthesis()
{
$value = ($a - $b) ? ($a - $b) : $c;
@ -9,9 +11,11 @@ function elvisRemoveParenthesis()
-----
<?php
namespace Rector\Php53\Tests\Rector\Ternary\TernaryToElvisRector\Fixture;
function elvisRemoveParenthesis()
{
$value = ($a - $b) ?: $c;
$value = $a - $b ?: $c;
}
?>

View File

@ -1,5 +1,7 @@
<?php
namespace Rector\Php53\Tests\Rector\Ternary\TernaryToElvisRector\Fixture;
function elvisYolo()
{
1 ?: 2;

View File

@ -34,11 +34,6 @@ use Rector\RectorDefinition\RectorDefinition;
*/
final class AddDefaultValueForUndefinedVariableRector extends AbstractRector
{
/**
* @var string[]
*/
private $undefinedVariables = [];
/**
* @var string[]
*/
@ -92,47 +87,14 @@ PHP
public function refactor(Node $node): ?Node
{
$this->definedVariables = [];
$this->undefinedVariables = [];
$this->traverseNodesWithCallable((array) $node->stmts, function (Node $node): ?int {
// entering new scope - break!
if ($node instanceof FunctionLike) {
return NodeTraverser::STOP_TRAVERSAL;
}
$this->collectDefinedVariablesFromForeach($node);
if (! $node instanceof Variable) {
return null;
}
if ($this->shouldSkipVariable($node)) {
return null;
}
/** @var string $variableName */
$variableName = $this->getName($node);
// defined 100 %
/** @var Scope $nodeScope */
$nodeScope = $node->getAttribute(AttributeKey::SCOPE);
if ($nodeScope->hasVariableType($variableName)->yes()) {
return null;
}
$this->undefinedVariables[] = $variableName;
return null;
});
if ($this->undefinedVariables === []) {
$undefinedVariables = $this->collectUndefinedVariableScope($node);
if ($undefinedVariables === []) {
return null;
}
$this->undefinedVariables = array_unique($this->undefinedVariables);
$variablesInitiation = [];
foreach ($this->undefinedVariables as $undefinedVariable) {
foreach ($undefinedVariables as $undefinedVariable) {
if (in_array($undefinedVariable, $this->definedVariables, true)) {
continue;
}
@ -170,7 +132,6 @@ PHP
private function shouldSkipVariable(Variable $variable): bool
{
$parentNode = $variable->getAttribute(AttributeKey::PARENT_NODE);
if ($parentNode instanceof Global_) {
return true;
}
@ -188,21 +149,23 @@ PHP
}
// list() = | [$values] = defines variables as null
if ($parentNode instanceof Node) {
$parentParentNode = $parentNode->getAttribute(AttributeKey::PARENT_NODE);
if ($parentParentNode instanceof List_ || $parentParentNode instanceof Array_) {
return true;
}
if ($this->isListAssign($parentNode)) {
return true;
}
/** @var Scope|null $nodeScope */
$nodeScope = $variable->getAttribute(AttributeKey::SCOPE);
if ($nodeScope === null) {
return true;
}
$variableName = $this->getName($variable);
// skip $this, as probably in outer scope
if ($variableName === 'this') {
return true;
}
return $variableName === null;
}
@ -218,4 +181,57 @@ PHP
return false;
}
/**
* @param ClassMethod|Function_|Closure $node
* @return string[]
*/
private function collectUndefinedVariableScope(Node $node): array
{
$undefinedVariables = [];
$this->traverseNodesWithCallable((array) $node->stmts, function (Node $node) use (&$undefinedVariables): ?int {
// entering new scope - break!
if ($node instanceof FunctionLike) {
return NodeTraverser::STOP_TRAVERSAL;
}
$this->collectDefinedVariablesFromForeach($node);
if (! $node instanceof Variable) {
return null;
}
if ($this->shouldSkipVariable($node)) {
return null;
}
/** @var string $variableName */
$variableName = $this->getName($node);
// defined 100 %
/** @var Scope $nodeScope */
$nodeScope = $node->getAttribute(AttributeKey::SCOPE);
if ($nodeScope->hasVariableType($variableName)->yes()) {
return null;
}
$undefinedVariables[] = $variableName;
return null;
});
return array_unique($undefinedVariables);
}
private function isListAssign(?Node $parentNode): bool
{
if ($parentNode instanceof Node) {
$parentParentNode = $parentNode->getAttribute(AttributeKey::PARENT_NODE);
if ($parentParentNode instanceof List_ || $parentParentNode instanceof Array_) {
return true;
}
}
return false;
}
}

View File

@ -11,5 +11,5 @@ $fn = function() {
return $this->val;
};
$closure = Closure::bind($fn, new SkipThisAssign(), 'SkipThisAssign');
$closure = \Closure::bind($fn, new SkipThisAssign(), '\Rector\Php56\Tests\Rector\FunctionLike\AddDefaultValueForUndefinedVariableRector\Fixture\SkipThisAssign');
echo $closure(), "\n";

View File

@ -68,10 +68,6 @@ PHP
return null;
}
if (! isset($node->args[0])) {
return null;
}
$countedNode = $node->args[0]->value;
if ($this->isCountableType($countedNode)) {
return null;
@ -111,7 +107,14 @@ PHP
}
$parentNode = $funcCall->getAttribute(AttributeKey::PARENT_NODE);
if ($parentNode instanceof Ternary) {
return true;
}
return $parentNode instanceof Ternary;
if (! isset($funcCall->args[0])) {
return true;
}
return false;
}
}

View File

@ -1,7 +1,6 @@
includes:
- 'utils/PHPStanExtensions/config/phpstan-extensions.neon'
- 'vendor/symplify/phpstan-extensions/config/php.level.neon'
- 'vendor/symplify/phpstan-extensions/config/symfony.level.neon'
- 'vendor/symplify/phpstan-extensions/config/config.neon'
- 'vendor/thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon'
parameters:
@ -224,3 +223,7 @@ parameters:
# phpstan compiler bug
- '#Parameter \#1 \$docComment of method PhpParser\\Builder\\Property::setDocComment\(\) expects _HumbugBox(.*?)\\PhpParser\\Comment\\Doc\|string, PhpParser\\Comment\\Doc given#'
-
message: '#Call to function in_array\(\) with arguments PhpParser\\Node\\Expr\\Variable, array\(\) and true will always evaluate to false#'
path: packages/Php56/src/Rector/FunctionLike/AddDefaultValueForUndefinedVariableRector.php

View File

@ -1,3 +1,6 @@
services:
Rector\PSR4\Rector\Namespace_\NormalizeNamespaceByPSR4ComposerAutoloadRector: ~
parameters:
exclude_paths:
- "/Fixture/"

View File

@ -189,7 +189,7 @@ PHP
// clear following arguments
$argumentCountToClear = count($before);
for ($i = $position + 1; $i <= ($position + $argumentCountToClear); ++$i) {
for ($i = $position + 1; $i <= $position + $argumentCountToClear; ++$i) {
unset($argumentNodes[$i]);
}
}