22
33namespace PHPStan \Type \Php ;
44
5+ use PhpParser \Node \Expr \BinaryOp \Smaller ;
56use PhpParser \Node \Expr \FuncCall ;
7+ use PhpParser \Node \Expr \Ternary ;
68use PHPStan \Analyser \Scope ;
79use PHPStan \Reflection \FunctionReflection ;
810use PHPStan \Reflection \ParametersAcceptorSelector ;
@@ -64,6 +66,31 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
6466 return new ErrorType ();
6567 }
6668
69+ // rewrite min($x, $y) as $x < $y ? $x : $y
70+ // we don't handle arrays, which have different semantics
71+ $ functionName = $ functionReflection ->getName ();
72+ $ args = $ functionCall ->args ;
73+ if (count ($ functionCall ->args ) === 2 ) {
74+ $ argType0 = $ scope ->getType ($ args [0 ]->value );
75+ $ argType1 = $ scope ->getType ($ args [1 ]->value );
76+
77+ if ($ argType0 ->isArray ()->no () && $ argType1 ->isArray ()->no ()) {
78+ if ($ functionName === 'min ' ) {
79+ return $ scope ->getType (new Ternary (
80+ new Smaller ($ args [0 ]->value , $ args [1 ]->value ),
81+ $ args [0 ]->value ,
82+ $ args [1 ]->value
83+ ));
84+ } elseif ($ functionName === 'max ' ) {
85+ return $ scope ->getType (new Ternary (
86+ new Smaller ($ args [0 ]->value , $ args [1 ]->value ),
87+ $ args [1 ]->value ,
88+ $ args [0 ]->value
89+ ));
90+ }
91+ }
92+ }
93+
6794 $ argumentTypes = [];
6895 foreach ($ functionCall ->args as $ arg ) {
6996 $ argType = $ scope ->getType ($ arg ->value );
@@ -83,7 +110,7 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
83110 }
84111
85112 return $ this ->processType (
86- $ functionReflection -> getName () ,
113+ $ functionName ,
87114 $ argumentTypes
88115 );
89116 }
0 commit comments