Skip to content

Commit 581f51a

Browse files
TomasVotrubaondrejmirtes
authored andcommitted
return mixed type
1 parent 6d4e3b3 commit 581f51a

File tree

4 files changed

+31
-40
lines changed

4 files changed

+31
-40
lines changed

src/Type/Php/JsonThrowOnErrorDynamicReturnTypeExtension.php

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,24 @@
1616
use PHPStan\Reflection\ParametersAcceptorSelector;
1717
use PHPStan\Reflection\ReflectionProvider;
1818
<<<<<<< HEAD
19+
<<<<<<< HEAD
1920
use PHPStan\Type\BitwiseFlagHelper;
2021
use PHPStan\Type\Constant\ConstantBooleanType;
2122
=======
2223
use PHPStan\Type\ArrayType;
2324
use PHPStan\Type\BooleanType;
25+
=======
26+
>>>>>>> return mixed type
2427
use PHPStan\Type\Constant\ConstantBooleanType;
2528
use PHPStan\Type\Constant\ConstantIntegerType;
2629
use PHPStan\Type\Constant\ConstantStringType;
2730
use PHPStan\Type\ConstantTypeHelper;
2831
>>>>>>> Extend JsonThrowOnErrorDynamicReturnTypeExtension to detect knonw type from contssant string value
2932
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
30-
use PHPStan\Type\FloatType;
31-
use PHPStan\Type\IntegerType;
3233
use PHPStan\Type\MixedType;
3334
use PHPStan\Type\ObjectType;
34-
use PHPStan\Type\StringType;
3535
use PHPStan\Type\Type;
3636
use PHPStan\Type\TypeCombinator;
37-
use PHPStan\Type\UnionType;
3837
use stdClass;
3938
use function json_decode;
4039

@@ -77,11 +76,7 @@ public function getTypeFromFunctionCall(
7776

7877
// narrow type for json_decode()
7978
if ($functionReflection->getName() === 'json_decode') {
80-
$jsonDecodeNarrowedType = $this->narrowTypeForJsonDecode($functionCall, $scope);
81-
// improve type
82-
if (! $jsonDecodeNarrowedType instanceof MixedType) {
83-
$defaultReturnType = $jsonDecodeNarrowedType;
84-
}
79+
$defaultReturnType = $this->narrowTypeForJsonDecode($functionCall, $scope);
8580
}
8681

8782
if (!isset($functionCall->getArgs()[$argumentPosition])) {
@@ -105,57 +100,34 @@ private function narrowTypeForJsonDecode(FuncCall $funcCall, Scope $scope): Type
105100
$firstValueType = $scope->getType($firstArgValue);
106101

107102
if ($firstValueType instanceof ConstantStringType) {
108-
$resolvedType = $this->resolveConstantStringType($firstValueType, $isForceArray);
109-
} else {
110-
$resolvedType = new MixedType();
111-
}
112-
113-
// prefer specific type
114-
if (! $resolvedType instanceof MixedType) {
115-
return $resolvedType;
103+
return $this->resolveConstantStringType($firstValueType, $isForceArray);
116104
}
117105

118106
// fallback type
119107
if ($isForceArray) {
120-
return new UnionType([
121-
new ArrayType(new MixedType(), new MixedType()),
122-
new StringType(),
123-
new FloatType(),
124-
new IntegerType(),
125-
new BooleanType(),
126-
]);
108+
return new MixedType(true, new ObjectType(stdClass::class));
127109
}
128110

129-
// scalar types with stdClass
130-
return new UnionType([
131-
new ObjectType(stdClass::class),
132-
new StringType(),
133-
new FloatType(),
134-
new IntegerType(),
135-
new BooleanType(),
136-
]);
111+
return new MixedType(true);
137112
}
138113

139114
/**
140115
* Is "json_decode(..., true)"?
141-
* @param Arg[] $args
142116
*/
143117
private function isForceArray(FuncCall $funcCall): bool
144118
{
145119
$args = $funcCall->getArgs();
146120

147-
if (!isset($args[1])) {
121+
if (! isset($args[1])) {
148122
return false;
149123
}
150124

151125
$secondArgValue = $args[1]->value;
152-
if ($secondArgValue instanceof ConstFetch) {
153-
if ($secondArgValue->name->toLowerString() === 'true') {
154-
return true;
155-
}
126+
if (! $secondArgValue instanceof ConstFetch) {
127+
return false;
156128
}
157129

158-
return false;
130+
return $secondArgValue->name->toLowerString() === 'true';
159131
}
160132

161133
private function resolveConstantStringType(ConstantStringType $constantStringType, bool $isForceArray): Type

tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8699,10 +8699,11 @@ public function dataPhp73Functions(): array
86998699
'json_encode($mixed, $integer | JSON_THROW_ON_ERROR | JSON_NUMERIC_CHECK)',
87008700
],
87018701
[
8702-
'bool|float|int|stdClass|string',
8702+
'mixed',
87038703
'json_decode($mixed)',
87048704
],
87058705
[
8706+
<<<<<<< HEAD
87068707
<<<<<<< HEAD
87078708
'mixed',
87088709
'json_decode($mixed, false, 512, JSON_THROW_ON_ERROR | JSON_NUMERIC_CHECK)',
@@ -8716,6 +8717,13 @@ public function dataPhp73Functions(): array
87168717
[
87178718
'float|int|stdClass|string|true',
87188719
>>>>>>> update type in LegacyNodeScopeResolverTest
8720+
=======
8721+
'mixed~false',
8722+
'json_decode($mixed, false, 512, JSON_THROW_ON_ERROR | JSON_NUMERIC_CHECK)',
8723+
],
8724+
[
8725+
'mixed~false',
8726+
>>>>>>> return mixed type
87198727
'json_decode($mixed, false, 512, $integer | JSON_THROW_ON_ERROR | JSON_NUMERIC_CHECK)',
87208728
],
87218729
[

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,9 @@
2121

2222
$value = json_decode('[1, 2, 3]');
2323
assertType('array{1, 2, 3}', $value);
24+
25+
26+
function ($mixed) {
27+
$value = json_decode($mixed);
28+
assertType('mixed', $value);
29+
};

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,8 @@
2121

2222
$value = json_decode('[1, 2, 3]', true);
2323
assertType('array{1, 2, 3}', $value);
24+
25+
function ($mixed) {
26+
$value = json_decode($mixed, true);
27+
assertType('mixed~stdClass', $value);
28+
};

0 commit comments

Comments
 (0)