2
2
3
3
namespace PHPStan \Type \Php ;
4
4
5
- use PhpParser \ConstExprEvaluationException ;
6
- use PhpParser \ConstExprEvaluator ;
7
- use PhpParser \Node \Expr ;
8
- use PhpParser \Node \Expr \ConstFetch ;
9
5
use PhpParser \Node \Expr \FuncCall ;
10
6
use PhpParser \Node \Name \FullyQualified ;
11
7
use PHPStan \Analyser \Scope ;
14
10
use PHPStan \Reflection \ReflectionProvider ;
15
11
use PHPStan \Type \BitwiseFlagHelper ;
16
12
use PHPStan \Type \Constant \ConstantBooleanType ;
17
- use PHPStan \Type \Constant \ConstantIntegerType ;
18
13
use PHPStan \Type \Constant \ConstantStringType ;
14
+ use PHPStan \Type \ConstantScalarType ;
19
15
use PHPStan \Type \ConstantTypeHelper ;
20
16
use PHPStan \Type \DynamicFunctionReturnTypeExtension ;
21
17
use PHPStan \Type \MixedType ;
22
18
use PHPStan \Type \ObjectType ;
23
19
use PHPStan \Type \Type ;
24
20
use PHPStan \Type \TypeCombinator ;
25
21
use stdClass ;
26
- use function constant ;
27
22
use function is_bool ;
28
23
use function json_decode ;
29
24
30
25
class JsonThrowOnErrorDynamicReturnTypeExtension implements DynamicFunctionReturnTypeExtension
31
26
{
32
27
33
- private const UNABLE_TO_RESOLVE = '__UNABLE_TO_RESOLVE__ ' ;
34
-
35
- private ConstExprEvaluator $ constExprEvaluator ;
36
-
37
28
/** @var array<string, int> */
38
29
private array $ argumentPositions = [
39
30
'json_encode ' => 1 ,
@@ -45,13 +36,6 @@ public function __construct(
45
36
private BitwiseFlagHelper $ bitwiseFlagAnalyser ,
46
37
)
47
38
{
48
- $ this ->constExprEvaluator = new ConstExprEvaluator (static function (Expr $ expr ) {
49
- if ($ expr instanceof ConstFetch) {
50
- return constant ($ expr ->name ->toString ());
51
- }
52
-
53
- return null ;
54
- });
55
39
}
56
40
57
41
public function isFunctionSupported (
@@ -116,32 +100,23 @@ private function narrowTypeForJsonDecode(FuncCall $funcCall, Scope $scope): Type
116
100
private function isForceArrayWithoutStdClass (FuncCall $ funcCall , Scope $ scope ): bool
117
101
{
118
102
$ args = $ funcCall ->getArgs ();
103
+ if (!isset ($ args [1 ])) {
104
+ return false ;
105
+ }
119
106
120
- if (isset ($ args [1 ])) {
121
- $ secondArgValue = $ this ->resolveMaskValue ($ args [1 ]->value , $ scope );
122
- if ($ secondArgValue === self ::UNABLE_TO_RESOLVE ) {
123
- return false ;
124
- }
125
-
126
- if (is_bool ($ secondArgValue )) {
127
- return $ secondArgValue ;
128
- }
129
-
130
- // depends on used constants
131
- if ($ secondArgValue === null ) {
132
- if (! isset ($ args [3 ])) {
133
- return false ;
134
- }
135
-
136
- // @see https://www.php.net/manual/en/json.constants.php#constant.json-object-as-array
137
- $ thirdArgValue = $ args [3 ]->value ;
138
- if ($ this ->bitwiseFlagAnalyser ->bitwiseOrContainsConstant ($ thirdArgValue , $ scope , 'JSON_OBJECT_AS_ARRAY ' )->yes ()) {
139
- return true ;
140
- }
141
- }
107
+ $ secondArgType = $ scope ->getType ($ args [1 ]->value );
108
+ $ secondArgValue = $ secondArgType instanceof ConstantScalarType ? $ secondArgType ->getValue () : null ;
109
+
110
+ if (is_bool ($ secondArgValue )) {
111
+ return $ secondArgValue ;
112
+ }
113
+
114
+ if ($ secondArgValue !== null || !isset ($ args [3 ])) {
115
+ return false ;
142
116
}
143
117
144
- return false ;
118
+ // depends on used constants, @see https://www.php.net/manual/en/json.constants.php#constant.json-object-as-array
119
+ return $ this ->bitwiseFlagAnalyser ->bitwiseOrContainsConstant ($ args [3 ]->value , $ scope , 'JSON_OBJECT_AS_ARRAY ' )->yes ();
145
120
}
146
121
147
122
private function resolveConstantStringType (ConstantStringType $ constantStringType , bool $ isForceArray ): Type
@@ -151,23 +126,4 @@ private function resolveConstantStringType(ConstantStringType $constantStringTyp
151
126
return ConstantTypeHelper::getTypeFromValue ($ decodedValue );
152
127
}
153
128
154
- /**
155
- * @return mixed
156
- */
157
- private function resolveMaskValue (Expr $ expr , Scope $ scope )
158
- {
159
- $ thirdArgValueType = $ scope ->getType ($ expr );
160
- if ($ thirdArgValueType instanceof ConstantIntegerType) {
161
- return $ thirdArgValueType ->getValue ();
162
- }
163
-
164
- // fallback to value resolver
165
- try {
166
- return $ this ->constExprEvaluator ->evaluateSilently ($ expr );
167
- } catch (ConstExprEvaluationException ) {
168
- // unable to resolve
169
- return self ::UNABLE_TO_RESOLVE ;
170
- }
171
- }
172
-
173
129
}
0 commit comments