Skip to content

Commit 8585e73

Browse files
uekannuekann
authored andcommitted
Implement of type specifacation for array's key
1 parent a22f582 commit 8585e73

File tree

2 files changed

+63
-11
lines changed

2 files changed

+63
-11
lines changed

src/Type/Php/ArrayAllFunctionTypeSpecifyingExtension.php

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,49 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n
3939

4040
$array = $args[0]->value;
4141
$callable = $args[1]->value;
42+
43+
4244
if ($callable instanceof Expr\ArrowFunction && $callable->expr instanceof Expr\FuncCall) {
43-
$specifiedTypesInCallable = $this->typeSpecifier->specifyTypesInCondition($scope, $callable->expr, $context)->getSureTypes();
44-
$callableParm = $callable->params[0];
45-
if (!$callableParm instanceof Expr\Variable || !key_exists("$" . $callableParm->name, $specifiedTypesInCallable)) {
46-
return new SpecifiedTypes();
45+
46+
$callableParms = $callable->params;
47+
$specifiedTypesInFuncCall = $this->typeSpecifier->specifyTypesInCondition($scope, $callable->expr, $context)->getSureTypes();
48+
49+
if(count($callableParms) >= 1 && $callableParms[0] instanceof Expr\Variable) {
50+
51+
$callableParmValueName = $callableParms[0]->name;
52+
$specifiedTypeOfValue = array_find(
53+
$specifiedTypesInFuncCall,
54+
fn($specifiedType) => $specifiedType[0] instanceof Expr\Variable && $specifiedType[0]->name === $callableParmValueName
55+
);
56+
57+
if(isset($specifiedTypeOfValue)) {
58+
$valueType = $specifiedTypeOfValue[1];
59+
}
60+
61+
}
62+
63+
if(count($callableParms) >= 2 && $callableParms[1] instanceof Expr\Variable) {
64+
65+
$callableParmKeyName = $callableParms[1]->name;
66+
$specifiedTypeOfKey = array_find(
67+
$specifiedTypesInFuncCall,
68+
fn($specifiedType) => $specifiedType[0] instanceof Expr\Variable && $specifiedType[0]->name === $callableParmKeyName
69+
);
70+
71+
if(isset($specifiedTypeOfKey)) {
72+
$keyType = $specifiedTypeOfKey[1];
73+
}
74+
75+
}
76+
77+
if(isset($keyType) || isset($valueType)) {
78+
return $this->typeSpecifier->create(
79+
$array,
80+
new ArrayType($keyType ?? new MixedType(), $valueType ?? new MixedType()),
81+
$context,
82+
$scope
83+
);
4784
}
48-
$ItemType = $specifiedTypesInCallable["$" . $callableParm->name][1];
49-
return $this->typeSpecifier->create(
50-
$array,
51-
new ArrayType(new MixedType(), $ItemType),
52-
$context,
53-
$scope
54-
);
5585
}
5686

5787
return new SpecifiedTypes();

tests/PHPStan/Analyser/TypeSpecifierTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use PhpParser\Node\Name;
1818
use PhpParser\Node\Scalar\LNumber;
1919
use PhpParser\Node\Scalar\String_;
20+
use PhpParser\Node\VariadicPlaceholder;
2021
use PhpParser\Node\VarLikeIdentifier;
2122
use PhpParser\PrettyPrinter\Standard;
2223
use PHPStan\Node\Expr\AlwaysRememberedExpr;
@@ -1342,6 +1343,27 @@ public static function dataCondition(): iterable
13421343
],
13431344
[]
13441345
],
1346+
[
1347+
new FuncCall(
1348+
new Name("array_all"),
1349+
[
1350+
new Arg(new Variable("array")),
1351+
new Arg(
1352+
new Expr\ArrowFunction(
1353+
[
1354+
'expr' => new FuncCall(new Name("is_string"), [new Arg(new Variable("key"))]),
1355+
'params' => [new Variable("value"), new Variable("key")],
1356+
],
1357+
[]
1358+
)
1359+
)
1360+
]
1361+
),
1362+
[
1363+
'$array' => 'array<string, mixed>'
1364+
],
1365+
[]
1366+
],
13451367
[
13461368
new FuncCall(
13471369
new Name("array_all"),

0 commit comments

Comments
 (0)