Skip to content
Open
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
1 change: 1 addition & 0 deletions conf/bleedingEdge.neon
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ parameters:
internalTag: true
newStaticInAbstractClassStaticMethod: true
checkExtensionsForComparisonOperators: true
checkGenericIterableClasses: true
reportTooWideBool: true
rawMessageInBaseline: true
reportNestedTooWideType: false # tmp
Expand Down
1 change: 1 addition & 0 deletions conf/config.neon
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ parameters:
internalTag: false
newStaticInAbstractClassStaticMethod: false
checkExtensionsForComparisonOperators: false
checkGenericIterableClasses: false
reportTooWideBool: false
rawMessageInBaseline: false
reportNestedTooWideType: false
Expand Down
1 change: 1 addition & 0 deletions conf/parametersSchema.neon
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ parametersSchema:
internalTag: bool()
newStaticInAbstractClassStaticMethod: bool()
checkExtensionsForComparisonOperators: bool()
checkGenericIterableClasses: bool()
reportTooWideBool: bool()
rawMessageInBaseline: bool()
reportNestedTooWideType: bool()
Expand Down
1 change: 1 addition & 0 deletions src/Analyser/Generator/NodeHandler/StmtsHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ private function getNextUnreachableStatements(array $nodes, bool $earlyBinding):
/**
* @param Node\Stmt[] $nextStmts
* @param (callable(Node, Scope, callable(Node, Scope): void): void)|null $alternativeNodeCallback
* @return Generator<int, NodeCallbackRequest>
*/
private function processUnreachableStatement(array $nextStmts, GeneratorScope $scope, ?callable $alternativeNodeCallback): Generator
{
Expand Down
7 changes: 6 additions & 1 deletion src/Rules/MissingTypehintCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public function __construct(
private bool $checkMissingCallableSignature,
#[AutowiredParameter(ref: '%featureToggles.skipCheckGenericClasses%')]
private array $skipCheckGenericClasses,
#[AutowiredParameter(ref: '%featureToggles.checkGenericIterableClasses%')]
private bool $checkGenericIterableClasses,
)
{
}
Expand Down Expand Up @@ -118,7 +120,10 @@ public function getNonGenericObjectTypesWithGenericClass(Type $type): array
if ($classReflection === null) {
return $type;
}
if (in_array($classReflection->getName(), self::ITERABLE_GENERIC_CLASS_NAMES, true)) {
if (
!$this->checkGenericIterableClasses &&
in_array($classReflection->getName(), self::ITERABLE_GENERIC_CLASS_NAMES, true)
) {
// checked by getIterableTypesWithMissingValueTypehint() already
return $type;
}
Expand Down
2 changes: 1 addition & 1 deletion stubs/PDOStatement.stub
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class PDOStatement implements Traversable, IteratorAggregate
public function getColumnMeta(int $column) {}

/**
* @return Iterator
* @return Iterator<mixed, array<int|string, mixed>>
*/
public function getIterator() {}
}
6 changes: 6 additions & 0 deletions stubs/runtime/ReflectionAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,16 @@ public function isRepeated(): bool
{
}

/**
* @return array<array-key, mixed>;
*/
public function getArguments(): array
{
}

/**
* @return self
*/
public function newInstance(): object
{
}
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/nsrt/bug-8886.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ function testPDOStatementGetIterator(): void {
$pdo = new PDO('sqlite::memory:');
$stmt = $pdo->query('SELECT 1');

assertType('Iterator', $stmt->getIterator());
assertType('Iterator<mixed, array<int|string, mixed>>', $stmt->getIterator());
}
2 changes: 1 addition & 1 deletion tests/PHPStan/Rules/Classes/LocalTypeAliasesRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ protected function getRule(): Rule
['GlobalTypeAlias' => 'int|string'],
self::createReflectionProvider(),
$container->getByType(TypeNodeResolver::class),
new MissingTypehintCheck(true, []),
new MissingTypehintCheck(true, [], true),
new ClassNameCheck(
new ClassCaseSensitivityCheck($reflectionProvider, true),
new ClassForbiddenNameCheck($container),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ protected function getRule(): Rule
['GlobalTypeAlias' => 'int|string'],
self::createReflectionProvider(),
$container->getByType(TypeNodeResolver::class),
new MissingTypehintCheck(true, []),
new MissingTypehintCheck(true, [], true),
new ClassNameCheck(
new ClassCaseSensitivityCheck($reflectionProvider, true),
new ClassForbiddenNameCheck($container),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ protected function getRule(): Rule
['GlobalTypeAlias' => 'int|string'],
self::createReflectionProvider(),
$container->getByType(TypeNodeResolver::class),
new MissingTypehintCheck(true, []),
new MissingTypehintCheck(true, [], true),
new ClassNameCheck(
new ClassCaseSensitivityCheck($reflectionProvider, true),
new ClassForbiddenNameCheck($container),
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Rules/Classes/MethodTagRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected function getRule(): TRule
$container,
),
new GenericObjectTypeCheck(),
new MissingTypehintCheck(true, []),
new MissingTypehintCheck(true, [], true),
new UnresolvableTypeHelper(),
true,
true,
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Rules/Classes/MethodTagTraitRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected function getRule(): TRule
$container,
),
new GenericObjectTypeCheck(),
new MissingTypehintCheck(true, []),
new MissingTypehintCheck(true, [], true),
new UnresolvableTypeHelper(),
true,
true,
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Rules/Classes/MethodTagTraitUseRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ protected function getRule(): TRule
$container,
),
new GenericObjectTypeCheck(),
new MissingTypehintCheck(true, []),
new MissingTypehintCheck(true, [], true),
new UnresolvableTypeHelper(),
true,
true,
Expand Down
6 changes: 5 additions & 1 deletion tests/PHPStan/Rules/Classes/MixinRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ protected function getRule(): Rule
$container,
),
new GenericObjectTypeCheck(),
new MissingTypehintCheck(true, []),
new MissingTypehintCheck(true, [], true),
new UnresolvableTypeHelper(),
true,
true,
Expand Down Expand Up @@ -69,6 +69,10 @@ public function testRule(): void
'PHPDoc tag @mixin contains generic class ReflectionClass but does not specify its types: T',
50,
],
[
'PHPDoc tag @mixin contains generic interface Iterator but does not specify its types: TKey, TValue',
50,
],
[
'PHPDoc tag @mixin contains unknown class MixinRule\UnknownestClass.',
50,
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Rules/Classes/MixinTraitRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected function getRule(): Rule
$container,
),
new GenericObjectTypeCheck(),
new MissingTypehintCheck(true, []),
new MissingTypehintCheck(true, [], true),
new UnresolvableTypeHelper(),
true,
true,
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Rules/Classes/MixinTraitUseRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected function getRule(): Rule
$container,
),
new GenericObjectTypeCheck(),
new MissingTypehintCheck(true, []),
new MissingTypehintCheck(true, [], true),
new UnresolvableTypeHelper(),
true,
true,
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Rules/Classes/PropertyTagRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected function getRule(): TRule
$container,
),
new GenericObjectTypeCheck(),
new MissingTypehintCheck(true, []),
new MissingTypehintCheck(true, [], true),
new UnresolvableTypeHelper(),
true,
true,
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Rules/Classes/PropertyTagTraitRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected function getRule(): TRule
$container,
),
new GenericObjectTypeCheck(),
new MissingTypehintCheck(true, []),
new MissingTypehintCheck(true, [], true),
new UnresolvableTypeHelper(),
true,
true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected function getRule(): TRule
$container,
),
new GenericObjectTypeCheck(),
new MissingTypehintCheck(true, []),
new MissingTypehintCheck(true, [], true),
new UnresolvableTypeHelper(),
true,
true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class MissingClassConstantTypehintRuleTest extends RuleTestCase

protected function getRule(): Rule
{
return new MissingClassConstantTypehintRule(new MissingTypehintCheck(true, []));
return new MissingClassConstantTypehintRule(new MissingTypehintCheck(true, [], true));
}

public function testRule(): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class MissingFunctionParameterTypehintRuleTest extends RuleTestCase

protected function getRule(): Rule
{
return new MissingFunctionParameterTypehintRule(new MissingTypehintCheck(true, []));
return new MissingFunctionParameterTypehintRule(new MissingTypehintCheck(true, [], true));
}

public function testRule(): void
Expand Down Expand Up @@ -72,9 +72,8 @@ public function testRule(): void
MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP,
],
[
'Function MissingFunctionParameterTypehint\missingTraversableTypehintPhpDoc() has parameter $traversable with no value type specified in iterable type Traversable.',
156,
MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP,
'Function MissingFunctionParameterTypehint\missingTraversableTypehint() has parameter $traversable with generic interface Traversable but does not specify its types: TKey, TValue',
148,
],
[
'Function MissingFunctionParameterTypehint\missingCallableSignature() has parameter $cb with no signature specified for callable.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class MissingFunctionReturnTypehintRuleTest extends RuleTestCase

protected function getRule(): Rule
{
return new MissingFunctionReturnTypehintRule(new MissingTypehintCheck(true, []));
return new MissingFunctionReturnTypehintRule(new MissingTypehintCheck(true, [], true));
}

public function testRule(): void
Expand Down Expand Up @@ -58,6 +58,31 @@ public function testRule(): void
'Function MissingFunctionReturnTypehint\callableNestedNoPrototype() return type has no signature specified for callable.',
141,
],
[
'Function MissingFunctionReturnTypehint\returnsGeneratorOfIntegersNoPrototype() return type with generic class Generator does not specify its types: TKey, TValue, TSend, TReturn',
152,
],
[
'Function MissingFunctionReturnTypehint\returnsGeneratorOfIntegersByStringNoPrototype() return type with generic class Generator does not specify its types: TKey, TValue, TSend, TReturn',
169,
],
[
'Function MissingFunctionReturnTypehint\returnsIteratorNoPrototype() return type with generic interface Iterator does not specify its types: TKey, TValue',
186,
],
[
'Function MissingFunctionReturnTypehint\returnsIteratorAggregateNoPrototype() return type with generic interface IteratorAggregate does not specify its types: TKey, TValue',
199,
],
[
'Function MissingFunctionReturnTypehint\returnsTraversableNoPrototype() return type has no value type specified in iterable type Traversable.',
212,
MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP,
],
[
'Function MissingFunctionReturnTypehint\returnsTraversableNoPrototype() return type with generic interface Traversable does not specify its types: TKey, TValue',
212,
],
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ function unionTypeWithUnknownArrayValueTypehint($a)
}

/**
* @param iterable<int>&\Traversable $a
* @param iterable<int>&\Traversable<array-key,int> $a
*/
function iterableIntersectionTypehint($a)
{

}

/**
* @param iterable<mixed>&\Traversable $a
* @param iterable<mixed>&\Traversable<array-key,mixed> $a
*/
function iterableIntersectionTypehint2($a)
{
Expand Down Expand Up @@ -151,7 +151,7 @@ function missingTraversableTypehint(\Traversable $traversable)
}

/**
* @param \Traversable $traversable
* @param \Traversable<array-key, mixed> $traversable
*/
function missingTraversableTypehintPhpDoc($traversable)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,77 @@ function callableNestedNoPrototype() : callable{
function callableNestedWithPrototype() : callable{

}

function returnsGeneratorOfIntegersNoPrototype(): \Generator
{
yield 1;
yield 2;
yield 3;
}

/**
* @return \Generator<int, int>
*/
function returnsGeneratorOfIntegersWithPrototype(): \Generator
{
yield 1;
yield 2;
yield 3;
}

function returnsGeneratorOfIntegersByStringNoPrototype(): \Generator
{
yield '1' => 1;
yield '2' => 2;
yield '3' => 3;
}

/**
* @return \Generator<string, int>
*/
function returnsGeneratorOfIntegersByStringWithPrototype(): \Generator
{
yield '1' => 1;
yield '2' => 2;
yield '3' => 3;
}

function returnsIteratorNoPrototype(): \Iterator
{
yield 'test';
}

/**
* @return \Iterator<array-key,string>
*/
function returnsIteratorWithPrototype(): \Iterator
{
yield 'test';
}

function returnsIteratorAggregateNoPrototype(): \IteratorAggregate
{
return new \ArrayObject([]);
}

/**
* @return \IteratorAggregate<array-key,string>
*/
function returnsIteratorAggregateWithPrototype(): \IteratorAggregate
{
return new \ArrayObject([]);
}

function returnsTraversableNoPrototype(): \Traversable
{
yield 'test';
}

/**
* @return \Traversable<array-key,string>
*/
function returnsTraversableWithPrototype(): \Traversable
{
yield 'test';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class MissingMethodParameterTypehintRuleTest extends RuleTestCase

protected function getRule(): Rule
{
return new MissingMethodParameterTypehintRule(new MissingTypehintCheck(true, []));
return new MissingMethodParameterTypehintRule(new MissingTypehintCheck(true, [], true));
}

public function testRule(): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class MissingMethodReturnTypehintRuleTest extends RuleTestCase

protected function getRule(): Rule
{
return new MissingMethodReturnTypehintRule(new MissingTypehintCheck(true, []));
return new MissingMethodReturnTypehintRule(new MissingTypehintCheck(true, [], true));
}

public function testRule(): void
Expand Down
Loading
Loading