Skip to content

Commit

Permalink
Merge branch refs/heads/1.10.x into 1.11.x
Browse files Browse the repository at this point in the history
  • Loading branch information
phpstan-bot committed Mar 5, 2024
2 parents 8c35702 + 810133d commit 4a35673
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 22 deletions.
10 changes: 3 additions & 7 deletions src/PhpDoc/StubValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ private function getRuleRegistry(Container $container): RuleRegistry
$phpVersion = $container->getByType(PhpVersion::class);
$localTypeAliasesCheck = $container->getByType(LocalTypeAliasesCheck::class);
$phpClassReflectionExtension = $container->getByType(PhpClassReflectionExtension::class);
$genericCallableRuleHelper = $container->getByType(GenericCallableRuleHelper::class);

$rules = [
// level 0
Expand All @@ -182,13 +183,8 @@ private function getRuleRegistry(Container $container): RuleRegistry
new MethodTemplateTypeRule($fileTypeMapper, $templateTypeCheck),
new MethodSignatureVarianceRule($varianceCheck),
new TraitTemplateTypeRule($fileTypeMapper, $templateTypeCheck),
new IncompatiblePhpDocTypeRule(
$fileTypeMapper,
$genericObjectTypeCheck,
$unresolvableTypeHelper,
$container->getByType(GenericCallableRuleHelper::class),
),
new IncompatiblePropertyPhpDocTypeRule($genericObjectTypeCheck, $unresolvableTypeHelper),
new IncompatiblePhpDocTypeRule($fileTypeMapper, $genericObjectTypeCheck, $unresolvableTypeHelper, $genericCallableRuleHelper),
new IncompatiblePropertyPhpDocTypeRule($genericObjectTypeCheck, $unresolvableTypeHelper, $genericCallableRuleHelper),
new InvalidPhpDocTagValueRule(
$container->getByType(Lexer::class),
$container->getByType(PhpDocParser::class),
Expand Down
33 changes: 19 additions & 14 deletions src/Rules/PhpDoc/GenericCallableRuleHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function check(
Scope $scope,
string $location,
Type $callableType,
string $functionName,
?string $functionName,
array $functionTemplateTags,
?ClassReflection $classReflection,
): array
Expand All @@ -64,26 +64,31 @@ public function check(

$templateTags = $type->getTemplateTags();

$functionDescription = sprintf('function %s', $functionName);
$classDescription = null;
if ($classReflection !== null) {
$classDescription = $classReflection->getDisplayName();
$functionDescription = sprintf('method %s::%s', $classDescription, $functionName);
}

foreach (array_keys($functionTemplateTags) as $name) {
if (!isset($templateTags[$name])) {
continue;
if ($functionName !== null) {
$functionDescription = sprintf('function %s', $functionName);
if ($classReflection !== null) {
$functionDescription = sprintf('method %s::%s', $classDescription, $functionName);
}

$errors[] = RuleErrorBuilder::message(sprintf(
'PHPDoc tag %s template %s of %s shadows @template %s for %s.',
$location,
$name,
$typeDescription,
$name,
$functionDescription,
))->build();
foreach (array_keys($functionTemplateTags) as $name) {
if (!isset($templateTags[$name])) {
continue;
}

$errors[] = RuleErrorBuilder::message(sprintf(
'PHPDoc tag %s template %s of %s shadows @template %s for %s.',
$location,
$name,
$typeDescription,
$name,
$functionDescription,
))->build();
}
}

if ($classReflection !== null) {
Expand Down
13 changes: 13 additions & 0 deletions src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class IncompatiblePropertyPhpDocTypeRule implements Rule
public function __construct(
private GenericObjectTypeCheck $genericObjectTypeCheck,
private UnresolvableTypeHelper $unresolvableTypeHelper,
private GenericCallableRuleHelper $genericCallableRuleHelper,
)
{
}
Expand Down Expand Up @@ -93,6 +94,18 @@ public function processNode(Node $node, Scope $scope): array
$className = SprintfHelper::escapeFormatString($classReflection->getDisplayName());

Check failure on line 94 in src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.2, ubuntu-latest)

Method PHPStan\Rules\PhpDoc\IncompatiblePropertyPhpDocTypeRule::processNode() should return list<PHPStan\Rules\IdentifierRuleError> but returns array<PHPStan\Rules\RuleError>.

Check failure on line 94 in src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.2, windows-latest)

Method PHPStan\Rules\PhpDoc\IncompatiblePropertyPhpDocTypeRule::processNode() should return list<PHPStan\Rules\IdentifierRuleError> but returns array<PHPStan\Rules\RuleError>.
$escapedPropertyName = SprintfHelper::escapeFormatString($propertyName);

if ($node->isPromoted() === false) {
$messages = array_merge($messages, $this->genericCallableRuleHelper->check(
$node,
$scope,
'@var',
$phpDocType,
null,
[],
$classReflection,
));
}

$messages = array_merge($messages, $this->genericObjectTypeCheck->check(
$phpDocType,
sprintf(
Expand Down
4 changes: 4 additions & 0 deletions tests/PHPStan/Rules/PhpDoc/IncompatiblePhpDocTypeRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,10 @@ public function testGenericCallables(): void
'PHPDoc tag @return template T of Closure<T of mixed>(T): T shadows @template T for function GenericCallablesIncompatible\shadowsReturnArray.',
191,
],
[
'PHPDoc tag @param for parameter $shadows template T of Closure<T of mixed>(T): T shadows @template T for class GenericCallablesIncompatible\Test3.',
203,
],
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

namespace PHPStan\Rules\PhpDoc;

use PHPStan\Rules\ClassCaseSensitivityCheck;
use PHPStan\Rules\ClassForbiddenNameCheck;
use PHPStan\Rules\ClassNameCheck;
use PHPStan\Rules\Generics\GenericObjectTypeCheck;
use PHPStan\Rules\Generics\TemplateTypeCheck;
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;

Expand All @@ -14,9 +18,24 @@ class IncompatiblePropertyPhpDocTypeRuleTest extends RuleTestCase

protected function getRule(): Rule
{
$reflectionProvider = $this->createReflectionProvider();
$typeAliasResolver = $this->createTypeAliasResolver(['TypeAlias' => 'int'], $reflectionProvider);

return new IncompatiblePropertyPhpDocTypeRule(
new GenericObjectTypeCheck(),
new UnresolvableTypeHelper(),
new GenericCallableRuleHelper(
new TemplateTypeCheck(
$reflectionProvider,
new ClassNameCheck(
new ClassCaseSensitivityCheck($reflectionProvider, true),
new ClassForbiddenNameCheck(),
),
new GenericObjectTypeCheck(),
$typeAliasResolver,
true,
),
),
);
}

Expand Down Expand Up @@ -150,4 +169,30 @@ public function testBug7240(): void
$this->analyse([__DIR__ . '/data/bug-7240.php'], []);
}

public function testGenericCallables(): void
{
$this->analyse([__DIR__ . '/data/generic-callable-properties.php'], [
[
'PHPDoc tag @var template T of Closure<T of mixed>(T): T shadows @template T for class GenericCallableProperties\Test.',
16,
],
[
'PHPDoc tag @var template of Closure<stdClass of mixed>(stdClass): stdClass cannot have existing class stdClass as its name.',
21,
],
[
'PHPDoc tag @var template of callable<TypeAlias of mixed>(TypeAlias): TypeAlias cannot have existing type alias TypeAlias as its name.',
26,
],
[
'PHPDoc tag @var template TNull of callable<TNull of null>(TNull): TNull with bound type null is not supported.',
31,
],
[
'PHPDoc tag @var template TInvalid of callable<TInvalid of GenericCallableProperties\Invalid>(TInvalid): TInvalid has invalid bound type GenericCallableProperties\Invalid.',
36,
],
]);
}

}
42 changes: 42 additions & 0 deletions tests/PHPStan/Rules/PhpDoc/data/generic-callable-properties.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php declare(strict_types=1); // lint >= 8.0

namespace GenericCallableProperties;

use Closure;
use stdClass;

/**
* @template T
*/
class Test
{
/**
* @var Closure<T>(T): T
*/
private Closure $shadows;

/**
* @var Closure<stdClass>(stdClass): stdClass
*/
private Closure $existingClass;

/**
* @var callable<TypeAlias>(TypeAlias): TypeAlias
*/
private $typeAlias;

/**
* @var callable<TNull of null>(TNull): TNull
*/
private $unsupported;

/**
* @var callable<TInvalid of Invalid>(TInvalid): TInvalid
*/
private $invalid;

/**
* @param Closure<T>(T): T $notReported
*/
public function __construct(private Closure $notReported) {}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?php declare(strict_types=1);
<?php declare(strict_types=1); // lint > 8.0

namespace GenericCallablesIncompatible;

Expand Down Expand Up @@ -191,3 +191,14 @@ function shadowsParamOutArray(array &$existingClasses): void
function shadowsReturnArray(): array
{
}

/**
* @template T
*/
class Test3
{
/**
* @param Closure<T>(T): T $shadows
*/
public function __construct(private Closure $shadows) {}
}

0 comments on commit 4a35673

Please sign in to comment.