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
4 changes: 3 additions & 1 deletion src/Doctrine/DoctrineEntityDocumentAnalyser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Symplify\PHPStanRules\Doctrine;

use PHPStan\BetterReflection\Reflection\Adapter\FakeReflectionAttribute;
use PHPStan\BetterReflection\Reflection\Adapter\ReflectionAttribute;
use PHPStan\PhpDoc\ResolvedPhpDocBlock;
use PHPStan\Reflection\ClassReflection;

Expand Down Expand Up @@ -43,7 +45,7 @@ private static function hasEntityAttribute(ClassReflection $classReflection): bo

return array_any(
$attributeReflections,
static fn ($reflectionAttribute): bool => in_array(
static fn (ReflectionAttribute|FakeReflectionAttribute $reflectionAttribute): bool => in_array(
$reflectionAttribute->getName(),
self::ENTITY_ATTRIBUTES,
true
Expand Down
2 changes: 2 additions & 0 deletions src/Enum/ClassName.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ final class ClassName

public const string CONFIGURABLE_RECTOR = 'Rector\Contract\Rector\ConfigurableRectorInterface';

public const string DEPRECATED_RECTOR = 'Rector\Configuration\Deprecation\Contract\DeprecatedInterface';

public const string RECTOR_ATTRIBUTE_KEY = 'Rector\NodeTypeResolver\Node\AttributeKey';

public const string MOCK_OBJECT_CLASS = 'PHPUnit\Framework\MockObject\MockObject';
Expand Down
6 changes: 3 additions & 3 deletions src/NodeAnalyzer/AttributeFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@

final class AttributeFinder
{
public function hasAttribute(ClassLike | ClassMethod | Property | Param $node, string $desiredAttributeClass): bool
public function hasAttribute(ClassLike|ClassMethod|Property|Param $node, string $desiredAttributeClass): bool
{
return (bool) $this->findAttribute($node, $desiredAttributeClass);
}

/**
* @return Attribute[]
*/
private function findAttributes(ClassMethod | Property | ClassLike | Param $node): array
private function findAttributes(ClassMethod|Property|ClassLike|Param $node): array
{
$attributes = [];

Expand All @@ -33,7 +33,7 @@ private function findAttributes(ClassMethod | Property | ClassLike | Param $node
}

private function findAttribute(
ClassMethod | Property | ClassLike | Param $node,
ClassMethod|Property|ClassLike|Param $node,
string $desiredAttributeClass
): ?Attribute {
$attributes = $this->findAttributes($node);
Expand Down
1 change: 0 additions & 1 deletion src/NodeAnalyzer/EnumAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace Symplify\PHPStanRules\NodeAnalyzer;

use MyCLabs\Enum\Enum;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use PHPStan\Analyser\Scope;
Expand Down
2 changes: 1 addition & 1 deletion src/NodeTraverser/SimpleCallableNodeTraverser.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final class SimpleCallableNodeTraverser
* @param callable(Node $node): (int|Node|null) $callable
* @param Node|Node[]|null $nodes
*/
public function traverseNodesWithCallable(Node | array | null $nodes, callable $callable): void
public function traverseNodesWithCallable(Node|array|null $nodes, callable $callable): void
{
if ($nodes === null) {
return;
Expand Down
6 changes: 3 additions & 3 deletions src/Rules/ClassNameRespectsParentSuffixRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* @implements Rule<InClassNode>
* @see \Symplify\PHPStanRules\Tests\Rules\ClassNameRespectsParentSuffixRule\ClassNameRespectsParentSuffixRuleTest
*/
final class ClassNameRespectsParentSuffixRule implements Rule
final readonly class ClassNameRespectsParentSuffixRule implements Rule
{
public const string ERROR_MESSAGE = 'Class should have suffix "%s" to respect parent type';

Expand All @@ -45,13 +45,13 @@ final class ClassNameRespectsParentSuffixRule implements Rule
/**
* @var string[]
*/
private array $parentClasses = [];
private array $parentClasses;

/**
* @param class-string[] $parentClasses
*/
public function __construct(
private readonly ClassToSuffixResolver $classToSuffixResolver,
private ClassToSuffixResolver $classToSuffixResolver,
array $parentClasses = [],
) {
$this->parentClasses = array_merge($parentClasses, self::DEFAULT_PARENT_CLASSES);
Expand Down
3 changes: 2 additions & 1 deletion src/Rules/Complexity/NoJustPropertyAssignRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ private function isLocalPropertyFetchAssignToVariable(Assign $assign, Scope $sco
}

$exprType = $scope->getType($assign->expr);
return $exprType->isObject()->yes();
return $exprType->isObject()
->yes();
}

private function shouldSkipCurrentClass(Scope $scope): bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ private function resolveEntityClass(MethodCall $methodCall, Scope $scope): ?stri
return null;
}

$firstArgument = $methodCall->getArgs()[0]->value;
$firstArgument = $methodCall->getArgs()[0]
->value;

$entityClassType = $scope->getType($firstArgument);
if (! $entityClassType instanceof ConstantStringType) {
Expand Down
6 changes: 3 additions & 3 deletions src/Rules/ForbiddenNodeRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@
* @see \Symplify\PHPStanRules\Tests\Rules\ForbiddenNodeRule\ForbiddenNodeRuleTest
* @implements Rule<Node>
*/
final class ForbiddenNodeRule implements Rule
final readonly class ForbiddenNodeRule implements Rule
{
public const string ERROR_MESSAGE = '"%s" is forbidden to use';

/**
* @var array<class-string<Node>>
*/
private array $forbiddenNodes = [];
private array $forbiddenNodes;

private readonly Standard $standard;
private Standard $standard;

/**
* @param array<class-string<Node>> $forbiddenNodes
Expand Down
1 change: 0 additions & 1 deletion src/Rules/PreferredClassRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Name;
use PhpParser\Node\Param;
use PHPStan\Analyser\Scope;
use PHPStan\Node\InClassNode;
use PHPStan\Reflection\ClassReflection;
Expand Down
3 changes: 2 additions & 1 deletion src/Rules/Rector/NoClassReflectionStaticReflectionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ public function processNode(Node $node, Scope $scope): array
return [];
}

$argValue = $node->getArgs()[0]->value;
$argValue = $node->getArgs()[0]
->value;
$exprStaticType = $scope->getType($argValue);

if (RectorAllowedAutoloadedTypeAnalyzer::isAllowedType($exprStaticType)) {
Expand Down
3 changes: 2 additions & 1 deletion src/Rules/Rector/NoInstanceOfStaticReflectionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ private function resolveExprStaticType(FuncCall|Instanceof_ $node, Scope $scope)
return null;
}

$typeArgValue = $node->getArgs()[1]->value;
$typeArgValue = $node->getArgs()[1]
->value;
return $scope->getType($typeArgValue);
}

Expand Down
43 changes: 25 additions & 18 deletions src/Rules/Rector/NoIntegerRefactorReturnRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,34 +46,41 @@ public function processNode(Node $node, Scope $scope): array
return [];
}

if (! $node->returnType instanceof UnionType) {
if (! $this->hasIntReturnType($node->returnType)) {
return [];
}

foreach ($node->returnType->types as $type) {
if (! $type instanceof Identifier) {
continue;
}
$constantNames = $this->findUsedNodeVisitorConstantNames($node);

if ($type->name !== 'int') {
continue;
}
$undesiredConstantNames = array_diff($constantNames, ['REMOVE_NODE']);
if ($constantNames !== [] && $undesiredConstantNames === []) {
return [];
}

$constantNames = $this->findUsedNodeVisitorConstantNames($node);
$identifierRuleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)
->identifier(RectorRuleIdentifier::NO_INTEGER_REFACTOR_RETURN)
->build();

$undesiredConstantNames = array_diff($constantNames, ['REMOVE_NODE']);
if ($constantNames !== [] && $undesiredConstantNames === []) {
return [];
}
return [$identifierRuleError];
}

$ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)
->identifier(RectorRuleIdentifier::NO_INTEGER_REFACTOR_RETURN)
->build();
private function hasIntReturnType(?Node $node): bool
{
// bare "int" return type
if ($node instanceof Identifier) {
return $node->name === 'int';
}

return [$ruleError];
// "int" as one of the union members
if ($node instanceof UnionType) {
foreach ($node->types as $type) {
if ($type instanceof Identifier && $type->name === 'int') {
return true;
}
}
}

return [];
return false;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/Rules/Rector/NoLeadingBackslashInNameRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ public function processNode(Node $node, Scope $scope): array
return [];
}

$argValue = $node->getArgs()[0]->value;
$argValue = $node->getArgs()[0]
->value;
$argType = $scope->getType($argValue);

if (! $argType instanceof ConstantStringType) {
Expand Down
5 changes: 5 additions & 0 deletions src/Rules/Rector/PhpUpgradeDowngradeRegisteredInSetRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ private function matchRectorClassName(Scope $scope): ?string
return null;
}

// deprecated Rector rules are not registered in sets
if ($classReflection->is(ClassName::DEPRECATED_RECTOR)) {
return null;
}

return $classReflection->getName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ public function processNode(Node $node, Scope $scope): array

// 1. compare referenced type and constructor type
$classArgumentNamesToTypes = $this->classConstructorTypesResolver->resolveClassConstructorNamesToTypes($node);
$referenceExpr = $referenceFuncCall->getArgs()[0]->value;
$referenceExpr = $referenceFuncCall->getArgs()[0]
->value;

if (isset($classArgumentNamesToTypes[$currentArgumentName])) {
$constructorType = $classArgumentNamesToTypes[$currentArgumentName];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ public function processNode(Node $node, Scope $scope): array
}

$referenceFuncCall = $arrayItem->value;
$referenceExpr = $referenceFuncCall->getArgs()[0]->value;
$referenceExpr = $referenceFuncCall->getArgs()[0]
->value;

if (! $referenceExpr instanceof ClassConstFetch) {
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,10 @@ private function matchTwoArgsOfSameClassConstName(MethodCall $methodCall): ?stri
return null;
}

$serviceName = $methodCall->getArgs()[0]->value;
$serviceType = $methodCall->getArgs()[1]->value;
$serviceName = $methodCall->getArgs()[0]
->value;
$serviceType = $methodCall->getArgs()[1]
->value;

if (! $serviceName instanceof ClassConstFetch) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public function processNode(Node $node, Scope $scope): array

foreach ($excludeMethodCalls as $excludeMethodCall) {
// check all array args
$firstArgValue = $excludeMethodCall->getArgs()[0]->value;
$firstArgValue = $excludeMethodCall->getArgs()[0]
->value;
if (! $firstArgValue instanceof Array_) {
continue;
}
Expand Down
3 changes: 2 additions & 1 deletion src/Rules/Symfony/NoRoutingPrefixRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ private function isAllowedExternalBundleImport(MethodCall $methodCall): bool
return false;
}

$importArgPath = $parentCaller->getArgs()[0]->value;
$importArgPath = $parentCaller->getArgs()[0]
->value;
if (! $importArgPath instanceof String_) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ public static function resolve(Closure $closure, Scope $scope): array
return false;
}

$excludedExpr = $node->getArgs()[0]->value;
$excludedExpr = $node->getArgs()[0]
->value;
if (! $excludedExpr instanceof Array_) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ public static function resolve(Closure $closure): array
return false;
}

$namespaceExpr = $node->getArgs()[0]->value;
$namespaceExpr = $node->getArgs()[0]
->value;
if (! $namespaceExpr instanceof String_) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ public static function resolve(Closure $closure): array
return false;
}

$setServiceExpr = $methodCall->getArgs()[0]->value;
$setServiceExpr = $methodCall->getArgs()[0]
->value;
if (! $setServiceExpr instanceof ClassConstFetch) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/NodeAnalyzer/SymfonyControllerAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static function isControllerActionMethod(ClassMethod $classMethod): bool
return self::hasRouteAnnotationOrAttribute($classMethod);
}

public static function hasRouteAnnotationOrAttribute(ClassLike | ClassMethod $node): bool
public static function hasRouteAnnotationOrAttribute(ClassLike|ClassMethod $node): bool
{
if ($node instanceof ClassMethod && ! $node->isPublic()) {
return false;
Expand Down
9 changes: 6 additions & 3 deletions src/Symfony/NodeFinder/RepeatedServiceAdderCallNameFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ public static function find(MethodCall $methodCall): ?string

foreach ($callMethodCalls as $callMethodCall) {
/** @var String_ $calledMethodNameExpr */
$calledMethodNameExpr = $callMethodCall->getArgs()[0]->value;
$calledMethodNameExpr = $callMethodCall->getArgs()[0]
->value;
$callMethodName = $calledMethodNameExpr->value;

// is passing a service references?
$passedExpr = $callMethodCall->getArgs()[1]->value;
$passedExpr = $callMethodCall->getArgs()[1]
->value;
if (! $passedExpr instanceof Array_) {
continue;
}
Expand Down Expand Up @@ -79,7 +81,8 @@ private static function findCallMethodCalls(MethodCall $methodCall): array
return false;
}

$callNameExpr = $node->getArgs()[0]->value;
$callNameExpr = $node->getArgs()[0]
->value;
return $callNameExpr instanceof String_;
});

Expand Down
3 changes: 2 additions & 1 deletion src/Symfony/Reflection/ClassConstructorTypesResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ private function resolveClassNameFromServicesSetMethodCall(MethodCall $methodCal
continue;
}

$serviceClassOrName = $currentMethodCall->getArgs()[0]->value;
$serviceClassOrName = $currentMethodCall->getArgs()[0]
->value;
if ($serviceClassOrName instanceof ClassConstFetch) {
return NamingHelper::getName($serviceClassOrName->class);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Symplify\PHPStanRules\Tests\Rules\Rector\NoIntegerRefactorReturnRule\Fixture;

use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PhpParser\NodeVisitor;
use Rector\Rector\AbstractRector;

final class AllowBareIntRemoveNode extends AbstractRector
{
public function getNodeTypes(): array
{
return [Class_::class];
}

public function refactor(Node $node): int
{
return NodeVisitor::REMOVE_NODE;
}
}
Loading
Loading