[static] no nullable node (#4995)

* move phpstan.neon cusotm rules to rector-rules.neon, to cleanup main config

* enable forbidden rule on nullable nodes

* bump to Symplify 9.0.17

* make name non-nullable

* skip non-nullable

* skip null dim
This commit is contained in:
Tomas Votruba 2020-12-25 21:50:50 +01:00 committed by GitHub
parent d256bbd8c0
commit ed475a2e3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 187 additions and 175 deletions

View File

@ -30,15 +30,15 @@
"symfony/dependency-injection": "^4.4.8|^5.1",
"symfony/finder": "^4.4.8|^5.1",
"symfony/http-kernel": "^4.4.8|^5.1",
"symplify/autowire-array-parameter": "^9.0.14",
"symplify/console-color-diff": "^9.0.14",
"symplify/package-builder": "^9.0.14",
"symplify/rule-doc-generator": "^9.0.14",
"symplify/set-config-resolver": "^9.0.14",
"symplify/simple-php-doc-parser": "^9.0.14",
"symplify/skipper": "^9.0.14",
"symplify/smart-file-system": "^9.0.14",
"symplify/symfony-php-config": "^9.0.14",
"symplify/autowire-array-parameter": "^9.0.17",
"symplify/console-color-diff": "^9.0.17",
"symplify/package-builder": "^9.0.17",
"symplify/rule-doc-generator": "^9.0.17",
"symplify/set-config-resolver": "^9.0.17",
"symplify/simple-php-doc-parser": "^9.0.17",
"symplify/skipper": "^9.0.17",
"symplify/smart-file-system": "^9.0.17",
"symplify/symfony-php-config": "^9.0.17",
"webmozart/assert": "^1.9"
},
"require-dev": {
@ -51,12 +51,12 @@
"phpstan/phpstan-nette": "^0.12.12",
"phpunit/phpunit": "^9.5",
"sebastian/diff": "^4.0.4",
"symplify/changelog-linker": "^9.0.14",
"symplify/coding-standard": "^9.0.14",
"symplify/easy-coding-standard": "^9.0.14",
"symplify/easy-testing": "^9.0.14",
"symplify/phpstan-extensions": "^9.0.14",
"symplify/phpstan-rules": "^9.0.14",
"symplify/changelog-linker": "^9.0.17",
"symplify/coding-standard": "^9.0.17",
"symplify/easy-coding-standard": "^9.0.17",
"symplify/easy-testing": "^9.0.17",
"symplify/phpstan-extensions": "^9.0.17",
"symplify/phpstan-rules": "^9.0.17",
"tracy/tracy": "^2.7"
},
"replace": {

View File

@ -23,126 +23,6 @@ includes:
- vendor/symplify/phpstan-rules/config/symfony-rules.neon
- vendor/symplify/phpstan-rules/config/test-rules.neon
services:
-
class: Symplify\PHPStanRules\Rules\ForbiddenMethodCallOnTypeRule
tags: [phpstan.rules.rule]
arguments:
forbiddenMethodNamesByTypes:
PhpParser\Node:
- 'getDocComment'
- 'getComments'
- 'setDocComment'
-
class: Symplify\PHPStanRules\Rules\OnlyOneClassMethodRule
tags: [phpstan.rules.rule]
arguments:
onlyOneMethodsByType:
Rector\Testing\PHPUnit\AbstractRectorTestCase:
- getRectorClass
- provideConfigFileInfo
- getRectorsWithConfiguration
-
class: Symplify\PHPStanRules\Rules\ForbiddenNodeRule
tags: [phpstan.rules.rule]
arguments:
forbiddenNodes:
- PhpParser\Node\Expr\ErrorSuppress
- PhpParser\Node\Stmt\Switch_
- PhpParser\Node\Expr\Empty_
-
class: Symplify\PHPStanRules\Rules\RequireClassTypeInClassMethodByTypeRule
tags: [phpstan.rules.rule]
arguments:
requiredTypeInMethodByClass:
Rector\Core\Contract\Rector\PhpRectorInterface:
getNodeTypes: 'PhpParser\Node'
-
class: Symplify\PHPStanRules\CognitiveComplexity\Rules\FunctionLikeCognitiveComplexityRule
tags: [phpstan.rules.rule]
arguments:
maxMethodCognitiveComplexity: 9
-
class: Symplify\PHPStanRules\CognitiveComplexity\Rules\ClassLikeCognitiveComplexityRule
tags: [phpstan.rules.rule]
arguments:
maxClassCognitiveComplexity: 50
limitsByTypes:
Rector\Core\Rector\AbstractRector: 40
Symfony\Component\Console\Command\Command: 40
PHPStan\Rule\Rule: 30
# require constant in argument position
-
class: Symplify\PHPStanRules\Rules\RequireMethodCallArgumentConstantRule
tags: [phpstan.rules.rule]
arguments:
constantArgByMethodByType:
Symfony\Component\Console\Command\Command:
addArgument: [0]
addOption: [0]
Symfony\Component\Console\Input\InputInterface:
getOption: [0]
getArgument: [0]
PhpParser\Node:
getAttribute: [0]
hasAttribute: [0]
setAttribute: [0]
-
class: Symplify\PHPStanRules\Rules\SeeAnnotationToTestRule
tags: [phpstan.rules.rule]
arguments:
requiredSeeTypes:
- PHPStan\Rules\Rule
- Rector\Core\Rector\AbstractRector
# this rule prevents bug in phar like these: https://github.com/rectorphp/rector/pull/3692/files
-
class: Symplify\PHPStanRules\Rules\RequireStringArgumentInMethodCallRule
tags: [phpstan.rules.rule]
arguments:
stringArgByMethodByType:
Rector\Core\Rector\AbstractRector:
isObjectType: [1]
-
class: Symplify\PHPStanRules\Rules\ClassNameRespectsParentSuffixRule
tags: [phpstan.rules.rule]
arguments:
parentClasses:
- Rector
-
class: Symplify\PHPStanRules\Rules\PreferredClassRule
tags: [phpstan.rules.rule]
arguments:
oldToPreferredClasses:
# prevent PHPStorm autocomplete mess
'Symfony\Component\DependencyInjection\Variable': 'PhpParser\Node\Expr\Variable'
'phpDocumentor\Reflection\Types\Expression': 'PhpParser\Node\Stmt\Expression'
'phpDocumentor\Reflection\DocBlock\Tags\Param': 'PhpParser\Node\Param'
'phpDocumentor\Reflection\DocBlock\Tags\Return_': 'PhpParser\Node\Stmt\Return_'
'Closure': 'PhpParser\Node\Expr\Closure'
'PHPUnit\TextUI\Configuration\Variable': 'PhpParser\Node\Expr\Variable'
'SebastianBergmann\Type\MixedType': 'PHPStan\Type\MixedType'
'Hoa\Protocol\Node\Node': 'PhpParser\Node'
'Nette\Utils\FileSystem': 'Symplify\SmartFileSystem\SmartFileSystem'
'Symfony\Component\Filesystem\Filesystem': 'Symplify\SmartFileSystem\SmartFileSystem'
# builder typo nodes
PhpParser\Builder\Use_: Rector\Core\PhpParser\Builder\UseBuilder
PhpParser\Builder\Class_: Rector\Core\PhpParser\Builder\ClassBuilder
PhpParser\Builder\Method: Rector\Core\PhpParser\Builder\MethodBuilder
PhpParser\Builder\Namespace_: Rector\Core\PhpParser\Builder\NamespaceBuilder
PhpParser\Builder\Param: Rector\Core\PhpParser\Builder\ParamBuilder
PhpParser\Builder\Property: Rector\Core\PhpParser\Builder\PropertyBuilder
PhpParser\Builder\TraitUse: Rector\Core\PhpParser\Builder\TraitUseBuilder
parameters:
level: max

View File

@ -291,7 +291,12 @@ CODE_SAMPLE
throw new ShouldNotHappenException();
}
return $this->isVariableName($node->var->dim, $this->keyValueName);
$arrayDimFetch = $node->var;
if ($arrayDimFetch->dim === null) {
return false;
}
return $this->isVariableName($arrayDimFetch->dim, $this->keyValueName);
}
);
}
@ -361,6 +366,10 @@ CODE_SAMPLE
throw new ShouldNotHappenException();
}
if ($node->dim === null) {
return null;
}
if (! $this->isVariableName($node->dim, $this->keyValueName)) {
return null;
}

View File

@ -100,13 +100,17 @@ CODE_SAMPLE
// Get all the params passed by reference
/** @var Assign */
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
/** @var Variable */
$exprVariable = $parentNode->expr;
// Count number of params by ref on the right side, to remove them later on
$rightSideRemovableParamsCount = $this->countRightSideMostParamsByRefOrEmpty($node->items);
// Add new nodes to do the assignment by reference
$newNodes = $this->createAssignRefArrayFromListReferences($node->items, $exprVariable, []);
$this->addNodesAfterNode($newNodes, $node);
// Remove the stale params right-most-side
return $this->removeStaleParams($node, $rightSideRemovableParamsCount);
}

View File

@ -178,6 +178,10 @@ CODE_SAMPLE
private function shouldSkipVariable(Variable $variable): bool
{
$parentNode = $variable->getAttribute(AttributeKey::PARENT_NODE);
if ($parentNode === null) {
return true;
}
if ($parentNode instanceof Global_) {
return true;
}
@ -225,15 +229,9 @@ CODE_SAMPLE
return false;
}
private function isListAssign(?Node $parentNode): bool
private function isListAssign(Node $node): bool
{
if ($parentNode instanceof Node) {
$parentParentNode = $parentNode->getAttribute(AttributeKey::PARENT_NODE);
if (StaticInstanceOf::isOneOf($parentParentNode, [List_::class, Array_::class])) {
return true;
}
}
return false;
$parentParentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
return StaticInstanceOf::isOneOf($parentParentNode, [List_::class, Array_::class]);
}
}

View File

@ -174,14 +174,8 @@ CODE_SAMPLE
}
}
private function areVariablesEqual(BinaryOp $binaryOp, ?Expr $firstValue, ?Expr $secondValue): bool
private function areVariablesEqual(BinaryOp $binaryOp, Expr $firstValue, Expr $secondValue): bool
{
if ($firstValue === null) {
return false;
}
if ($secondValue === null) {
return false;
}
if ($this->areNodesEqual($binaryOp->left, $firstValue) && $this->areNodesEqual(
$binaryOp->right,
$secondValue

View File

@ -117,6 +117,10 @@ CODE_SAMPLE
private function shouldSkip(Property $property): bool
{
$classLike = $property->getAttribute(AttributeKey::CLASS_NODE);
if ($classLike === null) {
return true;
}
if ($this->shouldSkipClass($classLike)) {
return true;
}
@ -149,7 +153,7 @@ CODE_SAMPLE
return false;
}
private function shouldSkipClass(?ClassLike $classLike): bool
private function shouldSkipClass(ClassLike $classLike): bool
{
if (! $classLike instanceof Class_) {
return true;
@ -159,11 +163,7 @@ CODE_SAMPLE
return true;
}
if ($this->isObjectType($classLike, 'PHPUnit\Framework\TestCase')) {
return true;
}
return $this->isObjectType($classLike, 'PHP_CodeSniffer\Sniffs\Sniff');
return $this->isObjectTypes($classLike, ['PHPUnit\Framework\TestCase', 'PHP_CodeSniffer\Sniffs\Sniff']);
}
private function shouldSkipProperty(Property $property): bool

View File

@ -138,6 +138,10 @@ CODE_SAMPLE
public function refactor(Node $node): ?Node
{
$classLike = $node->getAttribute(AttributeKey::CLASS_NODE);
if ($classLike === null) {
return null;
}
if (! $this->isNonAnonymousClass($classLike)) {
return null;
}

View File

@ -144,6 +144,11 @@ CODE_SAMPLE
PHPStanStaticTypeMapper::KIND_RETURN
);
// nothing to change in PHP code
if ($inferredReturnNode === null) {
return null;
}
if ($this->shouldSkipInferredReturnNode($node, $inferredReturnNode)) {
return null;
}
@ -191,12 +196,8 @@ CODE_SAMPLE
/**
* @param ClassMethod|Function_ $functionLike
*/
private function shouldSkipInferredReturnNode(FunctionLike $functionLike, ?Node $inferredReturnNode): bool
private function shouldSkipInferredReturnNode(FunctionLike $functionLike, Node $inferredReturnNode): bool
{
// nothing to change in PHP code
if ($inferredReturnNode === null) {
return true;
}
// already overridden by previous populateChild() method run
if ($functionLike->returnType === null) {
return false;

View File

@ -26,7 +26,7 @@ final class ConstantStringTypeToCallReflectionResolver implements TypeToCallRefl
*
* @var string
*/
private const STATIC_METHOD_REGEX = '#^([a-zA-Z_\\x7f-\\xff\\\\][a-zA-Z0-9_\\x7f-\\xff\\\\]*)::([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*)\\z#';
private const STATIC_METHOD_REGEX = '#^(?<class>[a-zA-Z_\\x7f-\\xff\\\\][a-zA-Z0-9_\\x7f-\\xff\\\\]*)::(?<method>[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*)\\z#';
/**
* @var ReflectionProvider
@ -63,15 +63,15 @@ final class ConstantStringTypeToCallReflectionResolver implements TypeToCallRefl
return null;
}
if (! $this->reflectionProvider->hasClass($matches[1])) {
if (! $this->reflectionProvider->hasClass($matches['class'])) {
return null;
}
$classReflection = $this->reflectionProvider->getClass($matches[1]);
if (! $classReflection->hasMethod($matches[2])) {
$classReflection = $this->reflectionProvider->getClass($matches['class']);
if (! $classReflection->hasMethod($matches['method'])) {
return null;
}
return $classReflection->getMethod($matches[2], $classMemberAccessAnswerer);
return $classReflection->getMethod($matches['method'], $classMemberAccessAnswerer);
}
}

View File

@ -31,12 +31,8 @@ trait AbstractRectorTrait
use NodeCollectorTrait;
use NotifyingRemovingNodeTrait;
protected function isNonAnonymousClass(?Node $node): bool
protected function isNonAnonymousClass(Node $node): bool
{
if ($node === null) {
return false;
}
if (! $node instanceof Class_) {
return false;
}

View File

@ -192,7 +192,7 @@ trait NameResolverTrait
return $this->isName($node->name, $methodName);
}
protected function isVariableName(?Node $node, string $name): bool
protected function isVariableName(Node $node, string $name): bool
{
if (! $node instanceof Variable) {
return false;

View File

@ -7,6 +7,14 @@ services:
class: Rector\PHPStanExtensions\Rule\KeepRectorNamespaceForRectorRule
tags: [phpstan.rules.rule]
# solve later
# -
# class: Symplify\PHPStanRules\Rules\ForbiddenNullableParameterRule
# tags: [phpstan.rules.rule]
# arguments:
# forbidddenTypes:
# - PhpParser\Node
-
class: Symplify\PHPStanRules\Rules\IfNewTypeThenImplementInterfaceRule
tags: [phpstan.rules.rule]
@ -14,10 +22,128 @@ services:
interfacesByNewTypes:
Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample: Rector\Core\Contract\Rector\ConfigurableRectorInterface
# open in Sypmlify 9.0.20 version
-
class: Symplify\PHPStanRules\Rules\IfImplementsInterfaceThenNewTypeRule
tags: [phpstan.rules.rule]
arguments:
newTypesByInterface:
Rector\Core\Contract\Rector\ConfigurableRectorInterface: Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample
-
class: Symplify\PHPStanRules\Rules\ForbiddenMethodCallOnTypeRule
tags: [phpstan.rules.rule]
arguments:
forbiddenMethodNamesByTypes:
PhpParser\Node:
- 'getDocComment'
- 'getComments'
- 'setDocComment'
-
class: Symplify\PHPStanRules\Rules\OnlyOneClassMethodRule
tags: [phpstan.rules.rule]
arguments:
onlyOneMethodsByType:
Rector\Testing\PHPUnit\AbstractRectorTestCase:
- getRectorClass
- provideConfigFileInfo
- getRectorsWithConfiguration
-
class: Symplify\PHPStanRules\Rules\ForbiddenNodeRule
tags: [phpstan.rules.rule]
arguments:
forbiddenNodes:
- PhpParser\Node\Expr\ErrorSuppress
- PhpParser\Node\Stmt\Switch_
- PhpParser\Node\Expr\Empty_
-
class: Symplify\PHPStanRules\Rules\RequireClassTypeInClassMethodByTypeRule
tags: [phpstan.rules.rule]
arguments:
requiredTypeInMethodByClass:
Rector\Core\Contract\Rector\PhpRectorInterface:
getNodeTypes: 'PhpParser\Node'
-
class: Symplify\PHPStanRules\CognitiveComplexity\Rules\FunctionLikeCognitiveComplexityRule
tags: [phpstan.rules.rule]
arguments:
maxMethodCognitiveComplexity: 9
-
class: Symplify\PHPStanRules\CognitiveComplexity\Rules\ClassLikeCognitiveComplexityRule
tags: [phpstan.rules.rule]
arguments:
maxClassCognitiveComplexity: 50
limitsByTypes:
Rector\Core\Rector\AbstractRector: 40
Symfony\Component\Console\Command\Command: 40
PHPStan\Rule\Rule: 30
# require constant in argument position
-
class: Symplify\PHPStanRules\Rules\RequireMethodCallArgumentConstantRule
tags: [phpstan.rules.rule]
arguments:
constantArgByMethodByType:
Symfony\Component\Console\Command\Command:
addArgument: [0]
addOption: [0]
Symfony\Component\Console\Input\InputInterface:
getOption: [0]
getArgument: [0]
PhpParser\Node:
getAttribute: [0]
hasAttribute: [0]
setAttribute: [0]
-
class: Symplify\PHPStanRules\Rules\SeeAnnotationToTestRule
tags: [phpstan.rules.rule]
arguments:
requiredSeeTypes:
- PHPStan\Rules\Rule
- Rector\Core\Rector\AbstractRector
# this rule prevents bug in phar like these: https://github.com/rectorphp/rector/pull/3692/files
-
class: Symplify\PHPStanRules\Rules\RequireStringArgumentInMethodCallRule
tags: [phpstan.rules.rule]
arguments:
stringArgByMethodByType:
Rector\Core\Rector\AbstractRector:
isObjectType: [1]
-
class: Symplify\PHPStanRules\Rules\ClassNameRespectsParentSuffixRule
tags: [phpstan.rules.rule]
arguments:
parentClasses:
- Rector
-
class: Symplify\PHPStanRules\Rules\PreferredClassRule
tags: [phpstan.rules.rule]
arguments:
oldToPreferredClasses:
# prevent PHPStorm autocomplete mess
'Symfony\Component\DependencyInjection\Variable': 'PhpParser\Node\Expr\Variable'
'phpDocumentor\Reflection\Types\Expression': 'PhpParser\Node\Stmt\Expression'
'phpDocumentor\Reflection\DocBlock\Tags\Param': 'PhpParser\Node\Param'
'phpDocumentor\Reflection\DocBlock\Tags\Return_': 'PhpParser\Node\Stmt\Return_'
'Closure': 'PhpParser\Node\Expr\Closure'
'PHPUnit\TextUI\Configuration\Variable': 'PhpParser\Node\Expr\Variable'
'SebastianBergmann\Type\MixedType': 'PHPStan\Type\MixedType'
'Hoa\Protocol\Node\Node': 'PhpParser\Node'
'Nette\Utils\FileSystem': 'Symplify\SmartFileSystem\SmartFileSystem'
'Symfony\Component\Filesystem\Filesystem': 'Symplify\SmartFileSystem\SmartFileSystem'
# builder typo nodes
PhpParser\Builder\Use_: Rector\Core\PhpParser\Builder\UseBuilder
PhpParser\Builder\Class_: Rector\Core\PhpParser\Builder\ClassBuilder
PhpParser\Builder\Method: Rector\Core\PhpParser\Builder\MethodBuilder
PhpParser\Builder\Namespace_: Rector\Core\PhpParser\Builder\NamespaceBuilder
PhpParser\Builder\Param: Rector\Core\PhpParser\Builder\ParamBuilder
PhpParser\Builder\Property: Rector\Core\PhpParser\Builder\PropertyBuilder
PhpParser\Builder\TraitUse: Rector\Core\PhpParser\Builder\TraitUseBuilder