Skip to content

Commit

Permalink
No longer verify types, when TypeSpecifyingExtension uses $overwrite=…
Browse files Browse the repository at this point in the history
…true
  • Loading branch information
staabm committed Feb 11, 2022
1 parent 4f72fdc commit 425dee7
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/Rules/Comparison/ImpossibleCheckTypeHelper.php
Expand Up @@ -158,6 +158,12 @@ public function findSpecifiedType(
}

$specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($scope, $node, TypeSpecifierContext::createTruthy());

// don't validate types on overwrite
if ($specifiedTypes->shouldOverwrite()) {
return null;
}

$sureTypes = $specifiedTypes->getSureTypes();
$sureNotTypes = $specifiedTypes->getSureNotTypes();

Expand Down
@@ -0,0 +1,40 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Comparison;

use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;

/**
* @extends RuleTestCase<ImpossibleCheckTypeMethodCallRule>
*/
class ImpossibleCheckTypeGenericOverwriteRuleTest extends RuleTestCase
{

public function getRule(): Rule
{
return new ImpossibleCheckTypeMethodCallRule(
new ImpossibleCheckTypeHelper(
$this->createReflectionProvider(),
$this->getTypeSpecifier(),
[],
true,
),
true,
true,
);
}

public function testNoReportedErrorOnOverwrite(): void
{
$this->analyse([__DIR__ . '/data/generic-type-override.php'], []);
}

public static function getAdditionalConfigFiles(): array
{
return [
__DIR__ . '/impossible-check-type-generic-overwrite.neon',
];
}

}
@@ -0,0 +1,58 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Comparison;

use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Analyser\SpecifiedTypes;
use PHPStan\Analyser\TypeSpecifier;
use PHPStan\Analyser\TypeSpecifierAwareExtension;
use PHPStan\Analyser\TypeSpecifierContext;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Type\MethodTypeSpecifyingExtension;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Generic\GenericObjectType;

class GenericTypeOverride implements MethodTypeSpecifyingExtension, TypeSpecifierAwareExtension
{

/** @var TypeSpecifier */
private $typeSpecifier;

public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void
{
$this->typeSpecifier = $typeSpecifier;
}

public function getClass(): string
{
return \GenericTypeOverride\Foo::class;
}

public function isMethodSupported(
MethodReflection $methodReflection,
MethodCall $node,
TypeSpecifierContext $context
): bool
{
return $methodReflection->getName() === 'setFetchMode';
}

public function specifyTypes(
MethodReflection $methodReflection,
MethodCall $node,
Scope $scope,
TypeSpecifierContext $context
): SpecifiedTypes
{
$newType = new GenericObjectType(\GenericTypeOverride\Foo::class, [new ObjectType(\GenericTypeOverride\Bar::class)]);

return $this->typeSpecifier->create(
$node->var,
$newType,
TypeSpecifierContext::createTruthy(),
true
);
}

}
39 changes: 39 additions & 0 deletions tests/PHPStan/Rules/Comparison/data/generic-type-override.php
@@ -0,0 +1,39 @@
<?php

namespace GenericTypeOverride;

use function PHPStan\Testing\assertType;

class Test {
public function doFoo() {
$foo = $this->createGenericFoo();
assertType('Foo<int>', $foo);

// $foo generic will be overridden via MethodTypeSpecifyingExtension
$foo->setFetchMode();
assertType('Foo<Bar>', $foo);
}

/**
* @return Foo<int>
*/
public function createGenericFoo() {

}
}


/**
* @template T
*/
class Foo
{
public function setFetchMode() {

}
}


class Bar
{
}
@@ -0,0 +1,5 @@
services:
-
class: PHPStan\Rules\Comparison\GenericTypeOverride
tags:
- phpstan.typeSpecifier.methodTypeSpecifyingExtension

0 comments on commit 425dee7

Please sign in to comment.