Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ private function detectOldWhitespaces(Node $node, array $tokens, StartEndValueOb

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')) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@ public function refactor(Node $node): ?Node
}

$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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
6 changes: 5 additions & 1 deletion packages/NodeTypeResolver/src/NodeTypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ private function correctPregMatchType(Node $node, Type $originalType): Type
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)
Expand All @@ -665,6 +665,10 @@ private function getVariableUsages(Variable $variable): array
{
$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;
});
Expand Down
9 changes: 7 additions & 2 deletions packages/NodeTypeResolver/src/StaticTypeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -622,15 +622,20 @@ public function mapPHPStanPhpDocTypeNodeToPHPStanType(TypeNode $typeNode, Node $

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);
}

$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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public function refactor(Node $node): ?Node
}

// simple check argument count fits to method required args
if ((count($values) % $numberOfParameters) !== 0) {
if (count($values) % $numberOfParameters !== 0) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function refactor(Node $node): ?Node
unset($node->stmts[$key]);
}

$node->stmts = array_merge($node->stmts, (array) $proccesed);
$node->stmts = array_merge((array) $node->stmts, (array) $proccesed);

return $node;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ private function getExpectedNamespace(Node $node): ?string
$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);

Expand Down
2 changes: 2 additions & 0 deletions packages/Php53/src/Rector/Ternary/TernaryToElvisRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

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;
Expand Down Expand Up @@ -55,6 +56,7 @@ public function refactor(Node $node): ?Node
return null;
}

$node->setAttribute(AttributeKey::ORIGINAL_NODE, null);
$node->if = null;

return $node;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

namespace Rector\Php53\Tests\Rector\Ternary\TernaryToElvisRector\Fixture;

function elvis()
{
$value = $a ? $a : false;
Expand All @@ -9,6 +11,8 @@ function elvis()
-----
<?php

namespace Rector\Php53\Tests\Rector\Ternary\TernaryToElvisRector\Fixture;

function elvis()
{
$value = $a ?: false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

namespace Rector\Php53\Tests\Rector\Ternary\TernaryToElvisRector\Fixture;

function elvisRemoveParenthesis()
{
$value = ($a - $b) ? ($a - $b) : $c;
Expand All @@ -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;
}

?>
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

namespace Rector\Php53\Tests\Rector\Ternary\TernaryToElvisRector\Fixture;

function elvisYolo()
{
1 ?: 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@
*/
final class AddDefaultValueForUndefinedVariableRector extends AbstractRector
{
/**
* @var string[]
*/
private $undefinedVariables = [];

/**
* @var string[]
*/
Expand Down Expand Up @@ -92,47 +87,14 @@ public function getNodeTypes(): array
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;
}
Expand Down Expand Up @@ -170,7 +132,6 @@ private function collectDefinedVariablesFromForeach(Node $node): void
private function shouldSkipVariable(Variable $variable): bool
{
$parentNode = $variable->getAttribute(AttributeKey::PARENT_NODE);

if ($parentNode instanceof Global_) {
return true;
}
Expand All @@ -188,21 +149,23 @@ private function shouldSkipVariable(Variable $variable): bool
}

// 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;
}

Expand All @@ -218,4 +181,57 @@ private function isStaticVariable(Node $parentNode): bool

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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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";
13 changes: 8 additions & 5 deletions packages/Php71/src/Rector/FuncCall/CountOnNullRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,6 @@ public function refactor(Node $node): ?Node
return null;
}

if (! isset($node->args[0])) {
return null;
}

$countedNode = $node->args[0]->value;
if ($this->isCountableType($countedNode)) {
return null;
Expand Down Expand Up @@ -111,7 +107,14 @@ private function shouldSkip(FuncCall $funcCall): bool
}

$parentNode = $funcCall->getAttribute(AttributeKey::PARENT_NODE);
if ($parentNode instanceof Ternary) {
return true;
}

if (! isset($funcCall->args[0])) {
return true;
}

return $parentNode instanceof Ternary;
return false;
}
}
7 changes: 5 additions & 2 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -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
3 changes: 3 additions & 0 deletions rector.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
services:
Rector\PSR4\Rector\Namespace_\NormalizeNamespaceByPSR4ComposerAutoloadRector: ~

parameters:
exclude_paths:
- "/Fixture/"
Expand Down
Loading