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
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ final class IntersectionTypeUnresolvedPropertyPrototypeReflection implements Unr
* @param UnresolvedPropertyPrototypeReflection[] $propertyPrototypes
*/
public function __construct(
private string $propertyName,
private array $propertyPrototypes,
)
{
Expand All @@ -30,7 +29,7 @@ public function doNotResolveTemplateTypeMapToBounds(): UnresolvedPropertyPrototy
return $this->cachedDoNotResolveTemplateTypeMapToBounds;
}

return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self($this->propertyName, array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->doNotResolveTemplateTypeMapToBounds(), $this->propertyPrototypes));
return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self(array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->doNotResolveTemplateTypeMapToBounds(), $this->propertyPrototypes));
}

public function getNakedProperty(): ExtendedPropertyReflection
Expand All @@ -50,7 +49,7 @@ public function getTransformedProperty(): ExtendedPropertyReflection

public function withFechedOnType(Type $type): UnresolvedPropertyPrototypeReflection
{
return new self($this->propertyName, array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->withFechedOnType($type), $this->propertyPrototypes));
return new self(array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->withFechedOnType($type), $this->propertyPrototypes));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ final class UnionTypeUnresolvedPropertyPrototypeReflection implements Unresolved
* @param UnresolvedPropertyPrototypeReflection[] $propertyPrototypes
*/
public function __construct(
private string $propertyName,
private array $propertyPrototypes,
)
{
Expand All @@ -29,7 +28,7 @@ public function doNotResolveTemplateTypeMapToBounds(): UnresolvedPropertyPrototy
if ($this->cachedDoNotResolveTemplateTypeMapToBounds !== null) {
return $this->cachedDoNotResolveTemplateTypeMapToBounds;
}
return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self($this->propertyName, array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->doNotResolveTemplateTypeMapToBounds(), $this->propertyPrototypes));
return $this->cachedDoNotResolveTemplateTypeMapToBounds = new self(array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->doNotResolveTemplateTypeMapToBounds(), $this->propertyPrototypes));
}

public function getNakedProperty(): ExtendedPropertyReflection
Expand All @@ -50,7 +49,7 @@ public function getTransformedProperty(): ExtendedPropertyReflection

public function withFechedOnType(Type $type): UnresolvedPropertyPrototypeReflection
{
return new self($this->propertyName, array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->withFechedOnType($type), $this->propertyPrototypes));
return new self(array_map(static fn (UnresolvedPropertyPrototypeReflection $prototype): UnresolvedPropertyPrototypeReflection => $prototype->withFechedOnType($type), $this->propertyPrototypes));
}

}
6 changes: 0 additions & 6 deletions src/Rules/Comparison/ImpossibleCheckTypeHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,10 @@
final class ImpossibleCheckTypeHelper
{

/**
* @param string[] $universalObjectCratesClasses
*/
public function __construct(
private ReflectionProvider $reflectionProvider,
private TypeSpecifier $typeSpecifier,
#[AutowiredParameter]
private array $universalObjectCratesClasses,
#[AutowiredParameter]
private bool $treatPhpDocTypesAsCertain,
)
{
Expand Down Expand Up @@ -417,7 +412,6 @@ public function doNotTreatPhpDocTypesAsCertain(): self
return new self(
$this->reflectionProvider,
$this->typeSpecifier,
$this->universalObjectCratesClasses,
false,
);
}
Expand Down
56 changes: 56 additions & 0 deletions src/Rules/DeadCode/UnusedPrivatePropertyRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
use PHPStan\DependencyInjection\AutowiredParameter;
use PHPStan\DependencyInjection\RegisteredRule;
use PHPStan\Node\ClassPropertiesNode;
use PHPStan\Node\ClassPropertyNode;
use PHPStan\Node\Property\PropertyRead;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection;
use PHPStan\Rules\Properties\ReadWritePropertiesExtensionProvider;
use PHPStan\Rules\Rule;
Expand Down Expand Up @@ -120,6 +122,7 @@ public function processNode(Node $node, Scope $scope): array
'node' => $property,
'onlyReadable' => $property->isReadable() && !$property->isWritable(),
'onlyWritable' => $property->isWritable() && !$property->isReadable(),
'hasTrueRead' => $alwaysRead,
];
}

Expand Down Expand Up @@ -194,6 +197,7 @@ public function processNode(Node $node, Scope $scope): array
if (!$classType->isSuperTypeOf($fetchedOnType)->no()) {
if ($usage instanceof PropertyRead) {
$properties[$propertyName]['read'] = true;
$properties[$propertyName]['hasTrueRead'] = true;
} else {
$properties[$propertyName]['written'] = true;
}
Expand All @@ -204,6 +208,7 @@ public function processNode(Node $node, Scope $scope): array
if (!$classType->isSuperTypeOf($fetchedOnType)->no()) {
if ($usage instanceof PropertyRead) {
$properties[$propertyName]['read'] = true;
$properties[$propertyName]['hasTrueRead'] = true;
} else {
$properties[$propertyName]['written'] = true;
}
Expand All @@ -213,12 +218,25 @@ public function processNode(Node $node, Scope $scope): array

if ($usage instanceof PropertyRead) {
$properties[$propertyName]['read'] = true;
if (!$this->isPropertySelfWrite($usageScope, $propertyName, $propertyNode, $classReflection->getName())) {
$properties[$propertyName]['hasTrueRead'] = true;
}
} else {
$properties[$propertyName]['written'] = true;
}
}
}

foreach ($properties as $propertyName => $data) {
if (!$data['read'] || $data['hasTrueRead']) {
continue;
}
if (!$data['node']->isPromoted()) {
continue;
}
$properties[$propertyName]['read'] = false;
}

[$uninitializedProperties] = $node->getUninitializedProperties($scope, []);

$errors = [];
Expand Down Expand Up @@ -270,4 +288,42 @@ public function processNode(Node $node, Scope $scope): array
return $errors;
}

private function isPropertySelfWrite(
Scope $usageScope,
string $propertyName,
ClassPropertyNode $propertyNode,
string $className,
): bool
{
if (!$propertyNode->isPromoted()) {
return false;
}

$callStack = $usageScope->getFunctionCallStackWithParameters();
if ($callStack === []) {
return false;
}

$lastCall = $callStack[count($callStack) - 1];
[$calleeReflection, $parameterReflection] = $lastCall;

if (!$calleeReflection instanceof MethodReflection) {
return false;
}

if ($calleeReflection->getName() !== '__construct') {
return false;
}

if ($calleeReflection->getDeclaringClass()->getName() !== $className) {
return false;
}

if ($parameterReflection === null) {
return false;
}

return $parameterReflection->getName() === $propertyName;
}

}
6 changes: 3 additions & 3 deletions src/Type/IntersectionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
return $propertyPrototypes[0];
}

return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes);
return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes);
}

public function hasInstanceProperty(string $propertyName): TrinaryLogic
Expand Down Expand Up @@ -648,7 +648,7 @@ public function getUnresolvedInstancePropertyPrototype(string $propertyName, Cla
return $propertyPrototypes[0];
}

return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes);
return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes);
}

public function hasStaticProperty(string $propertyName): TrinaryLogic
Expand Down Expand Up @@ -681,7 +681,7 @@ public function getUnresolvedStaticPropertyPrototype(string $propertyName, Class
return $propertyPrototypes[0];
}

return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes);
return new IntersectionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes);
}

public function canCallMethods(): TrinaryLogic
Expand Down
4 changes: 2 additions & 2 deletions src/Type/ObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
return $properties[0];
}

return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyName, $properties);
return new UnionTypeUnresolvedPropertyPrototypeReflection($properties);
}
}
}
Expand Down Expand Up @@ -320,7 +320,7 @@ public function getUnresolvedInstancePropertyPrototype(string $propertyName, Cla
return $properties[0];
}

return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyName, $properties);
return new UnionTypeUnresolvedPropertyPrototypeReflection($properties);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,10 @@ final class TypeSpecifyingFunctionsDynamicReturnTypeExtension implements Dynamic

private ?ImpossibleCheckTypeHelper $helper = null;

/**
* @param string[] $universalObjectCratesClasses
*/
public function __construct(
private ReflectionProvider $reflectionProvider,
#[AutowiredParameter]
private bool $treatPhpDocTypesAsCertain,
#[AutowiredParameter]
private array $universalObjectCratesClasses,
)
{
}
Expand Down Expand Up @@ -76,7 +71,7 @@ public function getTypeFromFunctionCall(

private function getHelper(): ImpossibleCheckTypeHelper
{
return $this->helper ??= new ImpossibleCheckTypeHelper($this->reflectionProvider, $this->typeSpecifier, $this->universalObjectCratesClasses, $this->treatPhpDocTypesAsCertain);
return $this->helper ??= new ImpossibleCheckTypeHelper($this->reflectionProvider, $this->typeSpecifier, $this->treatPhpDocTypesAsCertain);
}

}
6 changes: 3 additions & 3 deletions src/Type/UnionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ public function getUnresolvedPropertyPrototype(string $propertyName, ClassMember
return $propertyPrototypes[0];
}

return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes);
return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes);
}

public function hasInstanceProperty(string $propertyName): TrinaryLogic
Expand Down Expand Up @@ -554,7 +554,7 @@ public function getUnresolvedInstancePropertyPrototype(string $propertyName, Cla
return $propertyPrototypes[0];
}

return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes);
return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes);
}

public function hasStaticProperty(string $propertyName): TrinaryLogic
Expand Down Expand Up @@ -587,7 +587,7 @@ public function getUnresolvedStaticPropertyPrototype(string $propertyName, Class
return $propertyPrototypes[0];
}

return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyName, $propertyPrototypes);
return new UnionTypeUnresolvedPropertyPrototypeReflection($propertyPrototypes);
}

public function canCallMethods(): TrinaryLogic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ protected function getRule(): Rule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[],
$this->treatPhpDocTypesAsCertain,
),
$this->treatPhpDocTypesAsCertain,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ protected function getRule(): Rule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[],
$this->treatPhpDocTypesAsCertain,
),
$this->treatPhpDocTypesAsCertain,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ protected function getRule(): Rule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[],
$this->treatPhpDocTypesAsCertain,
),
$this->treatPhpDocTypesAsCertain,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ protected function getRule(): Rule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[],
$this->shouldTreatPhpDocTypesAsCertain(),
),
$this->shouldTreatPhpDocTypesAsCertain(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ protected function getRule(): Rule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[],
$this->treatPhpDocTypesAsCertain,
),
$this->treatPhpDocTypesAsCertain,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ protected function getRule(): Rule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[],
$this->treatPhpDocTypesAsCertain,
),
$this->treatPhpDocTypesAsCertain,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use PHPStan\Testing\RuleTestCase;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\RequiresPhp;
use stdClass;
use function array_filter;
use function array_map;
use function array_values;
Expand All @@ -28,7 +27,6 @@ protected function getRule(): Rule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[stdClass::class],
$this->treatPhpDocTypesAsCertain,
),
new PossiblyImpureTipHelper(true),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public function getRule(): Rule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[],
true,
),
new PossiblyImpureTipHelper(true),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public function getRule(): Rule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[],
true,
),
new PossiblyImpureTipHelper(true),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ public function getRule(): Rule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[],
$this->treatPhpDocTypesAsCertain,
),
new PossiblyImpureTipHelper(true),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ public function getRule(): Rule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[],
$this->treatPhpDocTypesAsCertain,
),
new PossiblyImpureTipHelper(true),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ protected function getRule(): TRule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[],
$this->shouldTreatPhpDocTypesAsCertain(),
),
$this->shouldTreatPhpDocTypesAsCertain(),
Expand Down
1 change: 0 additions & 1 deletion tests/PHPStan/Rules/Comparison/MatchExpressionRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ protected function getRule(): Rule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[],
$this->treatPhpDocTypesAsCertain,
),
$this->treatPhpDocTypesAsCertain,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ protected function getRule(): Rule
new ImpossibleCheckTypeHelper(
self::createReflectionProvider(),
$this->getTypeSpecifier(),
[],
$this->treatPhpDocTypesAsCertain,
),
$this->treatPhpDocTypesAsCertain,
Expand Down
Loading
Loading