Skip to content

Commit 4e5020d

Browse files
authored
json_decode with force array flag: subtract all objects, not just stdClass
1 parent 149a1e7 commit 4e5020d

File tree

3 files changed

+10
-11
lines changed

3 files changed

+10
-11
lines changed

src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@
1414
use PHPStan\Type\ConstantScalarType;
1515
use PHPStan\Type\ConstantTypeHelper;
1616
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
17-
use PHPStan\Type\ObjectType;
17+
use PHPStan\Type\ObjectWithoutClassType;
1818
use PHPStan\Type\Type;
1919
use PHPStan\Type\TypeCombinator;
20-
use stdClass;
2120
use function is_bool;
2221
use function json_decode;
2322

@@ -76,18 +75,18 @@ public function getTypeFromFunctionCall(
7675
private function narrowTypeForJsonDecode(FuncCall $funcCall, Scope $scope, Type $fallbackType): Type
7776
{
7877
$args = $funcCall->getArgs();
79-
$isArrayWithoutStdClass = $this->isForceArrayWithoutStdClass($funcCall, $scope);
78+
$isForceArray = $this->isForceArray($funcCall, $scope);
8079
if (!isset($args[0])) {
8180
return $fallbackType;
8281
}
8382

8483
$firstValueType = $scope->getType($args[0]->value);
8584
if ($firstValueType instanceof ConstantStringType) {
86-
return $this->resolveConstantStringType($firstValueType, $isArrayWithoutStdClass);
85+
return $this->resolveConstantStringType($firstValueType, $isForceArray);
8786
}
8887

89-
if ($isArrayWithoutStdClass) {
90-
return TypeCombinator::remove($fallbackType, new ObjectType(stdClass::class));
88+
if ($isForceArray) {
89+
return TypeCombinator::remove($fallbackType, new ObjectWithoutClassType());
9190
}
9291

9392
return $fallbackType;
@@ -96,7 +95,7 @@ private function narrowTypeForJsonDecode(FuncCall $funcCall, Scope $scope, Type
9695
/**
9796
* Is "json_decode(..., true)"?
9897
*/
99-
private function isForceArrayWithoutStdClass(FuncCall $funcCall, Scope $scope): bool
98+
private function isForceArray(FuncCall $funcCall, Scope $scope): bool
10099
{
101100
$args = $funcCall->getArgs();
102101
if (!isset($args[1])) {

tests/PHPStan/Analyser/data/json-decode/json_object_as_array.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,19 @@
77
// @see https://3v4l.org/YFlHF
88
function ($mixed) {
99
$value = json_decode($mixed, null, 512, JSON_OBJECT_AS_ARRAY);
10-
assertType('mixed~stdClass', $value);
10+
assertType('mixed~object', $value);
1111
};
1212

1313
function ($mixed) {
1414
$flagsAsVariable = JSON_OBJECT_AS_ARRAY;
1515

1616
$value = json_decode($mixed, null, 512, $flagsAsVariable);
17-
assertType('mixed~stdClass', $value);
17+
assertType('mixed~object', $value);
1818
};
1919

2020
function ($mixed) {
2121
$value = json_decode($mixed, null, 512, JSON_OBJECT_AS_ARRAY | JSON_BIGINT_AS_STRING);
22-
assertType('mixed~stdClass', $value);
22+
assertType('mixed~object', $value);
2323
};
2424

2525
function ($mixed) {

tests/PHPStan/Analyser/data/json-decode/narrow_type_with_force_array.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@
2424

2525
function ($mixed) {
2626
$value = json_decode($mixed, true);
27-
assertType('mixed~stdClass', $value);
27+
assertType('mixed~object', $value);
2828
};

0 commit comments

Comments
 (0)