Skip to content

Commit 711c66b

Browse files
Fix usage of context->truthy
1 parent 9507055 commit 711c66b

17 files changed

+152
-21
lines changed

src/Type/Php/ArrayKeyExistsFunctionTypeSpecifyingExtension.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function specifyTypes(
6161
if (!$keyType instanceof ConstantIntegerType
6262
&& !$keyType instanceof ConstantStringType
6363
&& !$arrayType->isIterableAtLeastOnce()->no()) {
64-
if ($context->truthy()) {
64+
if ($context->true()) {
6565
$arrayKeyType = $arrayType->getIterableKeyType();
6666
if ($keyType->isString()->yes()) {
6767
$arrayKeyType = $arrayKeyType->toString();
@@ -95,7 +95,7 @@ public function specifyTypes(
9595
return new SpecifiedTypes();
9696
}
9797

98-
if ($context->truthy()) {
98+
if ($context->true()) {
9999
$type = TypeCombinator::intersect(
100100
new ArrayType(new MixedType(), new MixedType()),
101101
new HasOffsetType($keyType),

src/Type/Php/ClassExistsFunctionTypeSpecifyingExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public function isFunctionSupported(
3535
'interface_exists',
3636
'trait_exists',
3737
'enum_exists',
38-
], true) && isset($node->getArgs()[0]) && $context->truthy();
38+
], true) && isset($node->getArgs()[0]) && $context->true();
3939
}
4040

4141
public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes

src/Type/Php/DefinedConstantTypeSpecifyingExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public function isFunctionSupported(
3535
{
3636
return $functionReflection->getName() === 'defined'
3737
&& count($node->getArgs()) >= 1
38-
&& $context->truthy();
38+
&& $context->true();
3939
}
4040

4141
public function specifyTypes(

src/Type/Php/FunctionExistsFunctionTypeSpecifyingExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public function isFunctionSupported(
2929
TypeSpecifierContext $context,
3030
): bool
3131
{
32-
return $functionReflection->getName() === 'function_exists' && isset($node->getArgs()[0]) && $context->truthy();
32+
return $functionReflection->getName() === 'function_exists' && isset($node->getArgs()[0]) && $context->true();
3333
}
3434

3535
public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes

src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,14 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n
5252
$specifiedTypes = new SpecifiedTypes();
5353

5454
if (
55-
$context->truthy()
56-
|| count(TypeUtils::getConstantScalars($arrayValueType)) > 0
57-
|| count(TypeUtils::getEnumCaseObjects($arrayValueType)) > 0
55+
$context->true()
56+
|| (
57+
$context->false()
58+
&& (
59+
count(TypeUtils::getConstantScalars($arrayValueType)) > 0
60+
|| count(TypeUtils::getEnumCaseObjects($arrayValueType)) > 0
61+
)
62+
)
5863
) {
5964
$specifiedTypes = $this->typeSpecifier->create(
6065
$node->getArgs()[0]->value,
@@ -66,11 +71,16 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n
6671
}
6772

6873
if (
69-
$context->truthy()
70-
|| count(TypeUtils::getConstantScalars($needleType)) > 0
71-
|| count(TypeUtils::getEnumCaseObjects($needleType)) > 0
74+
$context->true()
75+
|| (
76+
$context->false()
77+
&& (
78+
count(TypeUtils::getConstantScalars($needleType)) > 0
79+
|| count(TypeUtils::getEnumCaseObjects($arrayValueType)) > 0
80+
)
81+
)
7282
) {
73-
if ($context->truthy()) {
83+
if ($context->true()) {
7484
$arrayValueType = TypeCombinator::union($arrayValueType, $needleType);
7585
} else {
7686
$arrayValueType = TypeCombinator::remove($arrayValueType, $needleType);
@@ -85,7 +95,7 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n
8595
));
8696
}
8797

88-
if ($context->truthy() && $arrayType->isArray()->yes()) {
98+
if ($context->true() && $arrayType->isArray()->yes()) {
8999
$specifiedTypes = $specifiedTypes->unionWith($this->typeSpecifier->create(
90100
$node->getArgs()[1]->value,
91101
TypeCombinator::intersect($arrayType, new NonEmptyArrayType()),

src/Type/Php/IsAFunctionTypeSpecifyingExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n
3939
}
4040
$classType = $scope->getType($node->getArgs()[1]->value);
4141

42-
if (!$classType instanceof ConstantStringType && !$context->truthy()) {
42+
if (!$classType instanceof ConstantStringType && !$context->true()) {
4343
return new SpecifiedTypes([], []);
4444
}
4545

src/Type/Php/IsSubclassOfFunctionTypeSpecifyingExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function isFunctionSupported(FunctionReflection $functionReflection, Func
3434

3535
public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes
3636
{
37-
if (!$context->truthy() || count($node->getArgs()) < 2) {
37+
if (!$context->true() || count($node->getArgs()) < 2) {
3838
return new SpecifiedTypes();
3939
}
4040

src/Type/Php/MethodExistsTypeSpecifyingExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public function isFunctionSupported(
3535
): bool
3636
{
3737
return $functionReflection->getName() === 'method_exists'
38-
&& $context->truthy()
38+
&& $context->true()
3939
&& count($node->getArgs()) >= 2;
4040
}
4141

src/Type/Php/PropertyExistsTypeSpecifyingExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function isFunctionSupported(
4040
): bool
4141
{
4242
return $functionReflection->getName() === 'property_exists'
43-
&& $context->truthy()
43+
&& $context->true()
4444
&& count($node->getArgs()) >= 2;
4545
}
4646

src/Type/Php/StrContainingTypeSpecifyingExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void
5151
public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context): bool
5252
{
5353
return array_key_exists(strtolower($functionReflection->getName()), $this->strContainingFunctions)
54-
&& $context->truthy();
54+
&& $context->true();
5555
}
5656

5757
public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,6 +1199,7 @@ public function dataFileAsserts(): iterable
11991199
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8752.php');
12001200
yield from $this->gatherAssertTypes(__DIR__ . '/data/mysql-stmt.php');
12011201
yield from $this->gatherAssertTypes(__DIR__ . '/data/list-shapes.php');
1202+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-3013.php');
12021203
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7607.php');
12031204
yield from $this->gatherAssertTypes(__DIR__ . '/data/ibm_db2.php');
12041205
yield from $this->gatherAssertTypes(__DIR__ . '/data/benevolent-union-math.php');

tests/PHPStan/Analyser/data/bug-3009.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ public function createRedirectRequest(string $redirectUri): ?string
1515
return null;
1616
}
1717

18-
assertType('array{scheme?: string, host?: string, port?: int<0, 65535>, user?: string, pass?: string, path?: string, query?: string, fragment?: string}', $redirectUrlParts);
18+
assertType('array{scheme?: string, port?: int<0, 65535>, user?: string, pass?: string, path?: string, query?: string, fragment?: string}', $redirectUrlParts);
1919

2020
if (true === array_key_exists('query', $redirectUrlParts)) {
21-
assertType('array{scheme?: string, host?: string, port?: int<0, 65535>, user?: string, pass?: string, path?: string, query: string, fragment?: string}', $redirectUrlParts);
21+
assertType('array{scheme?: string, port?: int<0, 65535>, user?: string, pass?: string, path?: string, query: string, fragment?: string}', $redirectUrlParts);
2222
$redirectServer['QUERY_STRING'] = $redirectUrlParts['query'];
2323
}
2424

25-
assertType('array{scheme?: string, host?: string, port?: int<0, 65535>, user?: string, pass?: string, path?: string, query?: string, fragment?: string}', $redirectUrlParts);
25+
assertType('array{scheme?: string, port?: int<0, 65535>, user?: string, pass?: string, path?: string, query?: string, fragment?: string}', $redirectUrlParts);
2626

2727
return 'foo';
2828
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug3013;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class HelloWorld
8+
{
9+
public function test()
10+
{
11+
// Foo can be empty array, or list of ints
12+
$foo = array_map('intval', $_GET['foobar']);
13+
assertType('array<int>', $foo);
14+
15+
$bar = $this->intOrNull();
16+
assertType('int|null', $bar);
17+
18+
if (in_array($bar, $foo, true)) {
19+
assertType('non-empty-array<int>', $foo);
20+
assertType('int', $bar);
21+
return;
22+
}
23+
assertType('array<int>', $foo);
24+
assertType('int|null', $bar);
25+
26+
if (in_array($bar, $foo, true) === true) {
27+
assertType('int', $bar);
28+
return;
29+
}
30+
assertType('array<int>', $foo);
31+
assertType('int|null', $bar);
32+
}
33+
34+
35+
public function intOrNull(): ?int
36+
{
37+
return rand() === 2 ? null : rand();
38+
}
39+
40+
/**
41+
* @param array{0: 1, 1?: 2} $foo
42+
*/
43+
public function testArrayKeyExists($foo): void
44+
{
45+
assertType("array{0: 1, 1?: 2}", $foo);
46+
47+
$bar = 1;
48+
assertType("1", $bar);
49+
50+
if (array_key_exists($bar, $foo) === true) {
51+
assertType("array{1, 2}", $foo);
52+
assertType("1", $bar);
53+
return;
54+
}
55+
56+
assertType("array{1}", $foo);
57+
assertType("1", $bar);
58+
}
59+
}

tests/PHPStan/Rules/Classes/ClassConstantRuleTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,26 @@ public function testClassConstFetchDefined(): void
373373
'Access to undefined constant ClassConstFetchDefined\Foo::TEST.',
374374
48,
375375
],
376+
[
377+
'Access to undefined constant ClassConstFetchDefined\Foo::TEST.',
378+
52,
379+
],
380+
[
381+
'Access to undefined constant ClassConstFetchDefined\Foo::TEST.',
382+
54,
383+
],
384+
[
385+
'Access to undefined constant ClassConstFetchDefined\Foo::TEST.',
386+
56,
387+
],
388+
[
389+
'Access to undefined constant Foo::TEST.',
390+
57,
391+
],
392+
[
393+
'Access to undefined constant ClassConstFetchDefined\Foo::TEST.',
394+
58,
395+
],
376396
]);
377397
}
378398

tests/PHPStan/Rules/Classes/data/class-const-fetch-defined.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,15 @@ public static function doFoo()
4747
\Foo::TEST;
4848
\ClassConstFetchDefined\Foo::TEST;
4949
}
50+
51+
if (defined('Foo::TEST') === true) {
52+
Foo::TEST;
53+
\Foo::TEST;
54+
\ClassConstFetchDefined\Foo::TEST;
55+
} else {
56+
Foo::TEST;
57+
\Foo::TEST;
58+
\ClassConstFetchDefined\Foo::TEST;
59+
}
5060
}
5161
}

tests/PHPStan/Rules/Comparison/UnreachableTernaryElseBranchRuleTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,10 @@ public function testBug3019(): void
9999
$this->analyse([__DIR__ . '/../../Analyser/data/bug-3019.php'], []);
100100
}
101101

102+
public function testBug7686(): void
103+
{
104+
$this->treatPhpDocTypesAsCertain = true;
105+
$this->analyse([__DIR__ . '/data/bug-7686.php'], []);
106+
}
107+
102108
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug7686;
4+
5+
class Foo
6+
{
7+
/**
8+
* @param array<array{name: string, type: string}> $input
9+
* @return array<'return'|int, string>
10+
*/
11+
public static function test(array $input): array
12+
{
13+
$output = [];
14+
foreach($input as $match) {
15+
if (array_key_exists($match['name'], $output) == false) {
16+
$output[$match['name']] = '';
17+
}
18+
if (($match['type'] === '') || (in_array($match['type'], explode('|', $output[$match['name']]), true) === true)) {
19+
continue;
20+
}
21+
$output[$match['name']] = ($output[$match['name']] === '' ? $match['type'] : $output[$match['name']] . '|' . $match['type']);
22+
}
23+
return $output;
24+
}
25+
}

0 commit comments

Comments
 (0)