@@ -131,6 +131,7 @@ public function specifyTypesInCondition(
131131 return new SpecifiedTypes ([], [], false , [], $ rootExpr );
132132 }
133133
134+ // $expr instanceof $class
134135 if ($ expr instanceof Instanceof_) {
135136 $ exprNode = $ expr ->expr ;
136137 if ($ expr ->class instanceof Name) {
@@ -189,56 +190,85 @@ public function specifyTypesInCondition(
189190 if ($ context ->true ()) {
190191 return $ this ->create ($ exprNode , new ObjectWithoutClassType (), $ context , false , $ scope , $ rootExpr );
191192 }
192- } elseif ($ expr instanceof Node \Expr \BinaryOp \Identical) {
193+
194+ return new SpecifiedTypes ([], [], false , [], $ rootExpr );
195+ }
196+
197+ // $left === $right
198+ if ($ expr instanceof Node \Expr \BinaryOp \Identical) {
193199 return $ this ->resolveIdentical ($ expr , $ scope , $ context , $ rootExpr );
200+ }
194201
195- } elseif ($ expr instanceof Node \Expr \BinaryOp \NotIdentical) {
202+ // $left !== $right
203+ if ($ expr instanceof Node \Expr \BinaryOp \NotIdentical) {
196204 return $ this ->specifyTypesInCondition (
197205 $ scope ,
198206 new Node \Expr \BooleanNot (new Node \Expr \BinaryOp \Identical ($ expr ->left , $ expr ->right )),
199207 $ context ,
200208 $ rootExpr ,
201209 );
202- } elseif ($ expr instanceof Expr \Cast \Bool_) {
210+ }
211+
212+ // (bool) $expr
213+ if ($ expr instanceof Expr \Cast \Bool_) {
203214 return $ this ->specifyTypesInCondition (
204215 $ scope ,
205216 new Node \Expr \BinaryOp \Equal ($ expr ->expr , new ConstFetch (new Name \FullyQualified ('true ' ))),
206217 $ context ,
207218 $ rootExpr ,
208219 );
209- } elseif ($ expr instanceof Expr \Cast \String_) {
220+ }
221+
222+ // (string) $expr
223+ if ($ expr instanceof Expr \Cast \String_) {
210224 return $ this ->specifyTypesInCondition (
211225 $ scope ,
212226 new Node \Expr \BinaryOp \NotEqual ($ expr ->expr , new Node \Scalar \String_ ('' )),
213227 $ context ,
214228 $ rootExpr ,
215229 );
216- } elseif ($ expr instanceof Expr \Cast \Int_) {
230+ }
231+
232+ // (int) $expr
233+ if ($ expr instanceof Expr \Cast \Int_) {
217234 return $ this ->specifyTypesInCondition (
218235 $ scope ,
219236 new Node \Expr \BinaryOp \NotEqual ($ expr ->expr , new Node \Scalar \LNumber (0 )),
220237 $ context ,
221238 $ rootExpr ,
222239 );
223- } elseif ($ expr instanceof Expr \Cast \Double) {
240+ }
241+
242+ // (float) $expr
243+ if ($ expr instanceof Expr \Cast \Double) {
224244 return $ this ->specifyTypesInCondition (
225245 $ scope ,
226246 new Node \Expr \BinaryOp \NotEqual ($ expr ->expr , new Node \Scalar \DNumber (0.0 )),
227247 $ context ,
228248 $ rootExpr ,
229249 );
230- } elseif ($ expr instanceof Node \Expr \BinaryOp \Equal) {
250+ }
251+
252+ // $left == $right
253+ if ($ expr instanceof Node \Expr \BinaryOp \Equal) {
231254 return $ this ->resolveEqual ($ expr , $ scope , $ context , $ rootExpr );
232- } elseif ($ expr instanceof Node \Expr \BinaryOp \NotEqual) {
255+ }
256+
257+ // $left != $right
258+ if ($ expr instanceof Node \Expr \BinaryOp \NotEqual) {
233259 return $ this ->specifyTypesInCondition (
234260 $ scope ,
235261 new Node \Expr \BooleanNot (new Node \Expr \BinaryOp \Equal ($ expr ->left , $ expr ->right )),
236262 $ context ,
237263 $ rootExpr ,
238264 );
265+ }
239266
240- } elseif ($ expr instanceof Node \Expr \BinaryOp \Smaller || $ expr instanceof Node \Expr \BinaryOp \SmallerOrEqual) {
241-
267+ // $left < $right
268+ // $left <= $right
269+ if ($ expr instanceof Node \Expr \BinaryOp \Smaller
270+ || $ expr instanceof Node \Expr \BinaryOp \SmallerOrEqual
271+ ) {
242272 if (
243273 $ expr ->left instanceof FuncCall
244274 && count ($ expr ->left ->getArgs ()) >= 1
@@ -482,14 +512,20 @@ public function specifyTypesInCondition(
482512 }
483513
484514 return $ result ;
515+ }
485516
486- } elseif ($ expr instanceof Node \Expr \BinaryOp \Greater) {
517+ // $left > $right
518+ if ($ expr instanceof Node \Expr \BinaryOp \Greater) {
487519 return $ this ->specifyTypesInCondition ($ scope , new Expr \BinaryOp \Smaller ($ expr ->right , $ expr ->left ), $ context , $ rootExpr );
520+ }
488521
489- } elseif ($ expr instanceof Node \Expr \BinaryOp \GreaterOrEqual) {
522+ // $left >= $right
523+ if ($ expr instanceof Node \Expr \BinaryOp \GreaterOrEqual) {
490524 return $ this ->specifyTypesInCondition ($ scope , new Expr \BinaryOp \SmallerOrEqual ($ expr ->right , $ expr ->left ), $ context , $ rootExpr );
525+ }
491526
492- } elseif ($ expr instanceof FuncCall && $ expr ->name instanceof Name) {
527+ // name(...)
528+ if ($ expr instanceof FuncCall && $ expr ->name instanceof Name) {
493529 if ($ this ->reflectionProvider ->hasFunction ($ expr ->name , $ scope )) {
494530 $ functionReflection = $ this ->reflectionProvider ->getFunction ($ expr ->name , $ scope );
495531 foreach ($ this ->getFunctionTypeSpecifyingExtensions () as $ extension ) {
@@ -529,7 +565,10 @@ public function specifyTypesInCondition(
529565 }
530566
531567 return $ this ->handleDefaultTruthyOrFalseyContext ($ context , $ rootExpr , $ expr , $ scope );
532- } elseif ($ expr instanceof MethodCall && $ expr ->name instanceof Node \Identifier) {
568+ }
569+
570+ // $var->name(...)
571+ if ($ expr instanceof MethodCall && $ expr ->name instanceof Node \Identifier) {
533572 $ methodCalledOnType = $ scope ->getType ($ expr ->var );
534573 $ methodReflection = $ scope ->getMethodReflection ($ methodCalledOnType , $ expr ->name ->name );
535574 if ($ methodReflection !== null ) {
@@ -577,7 +616,10 @@ public function specifyTypesInCondition(
577616 }
578617
579618 return $ this ->handleDefaultTruthyOrFalseyContext ($ context , $ rootExpr , $ expr , $ scope );
580- } elseif ($ expr instanceof StaticCall && $ expr ->name instanceof Node \Identifier) {
619+ }
620+
621+ // $class::name(...)
622+ if ($ expr instanceof StaticCall && $ expr ->name instanceof Node \Identifier) {
581623 if ($ expr ->class instanceof Name) {
582624 $ calleeType = $ scope ->resolveTypeByName ($ expr ->class );
583625 } else {
@@ -630,7 +672,14 @@ public function specifyTypesInCondition(
630672 }
631673
632674 return $ this ->handleDefaultTruthyOrFalseyContext ($ context , $ rootExpr , $ expr , $ scope );
633- } elseif ($ expr instanceof BooleanAnd || $ expr instanceof LogicalAnd) {
675+ }
676+
677+ // $left && $right
678+ // $left and $right
679+ if (
680+ $ expr instanceof BooleanAnd
681+ || $ expr instanceof LogicalAnd
682+ ) {
634683 if (!$ scope instanceof MutatingScope) {
635684 throw new ShouldNotHappenException ();
636685 }
@@ -654,7 +703,14 @@ public function specifyTypesInCondition(
654703 }
655704
656705 return $ types ;
657- } elseif ($ expr instanceof BooleanOr || $ expr instanceof LogicalOr) {
706+ }
707+
708+ // $left || $right
709+ // $left or $right
710+ if (
711+ $ expr instanceof BooleanOr
712+ || $ expr instanceof LogicalOr
713+ ) {
658714 if (!$ scope instanceof MutatingScope) {
659715 throw new ShouldNotHappenException ();
660716 }
@@ -678,9 +734,15 @@ public function specifyTypesInCondition(
678734 }
679735
680736 return $ types ;
681- } elseif ($ expr instanceof Node \Expr \BooleanNot && !$ context ->null ()) {
737+ }
738+
739+ // !$expr
740+ if ($ expr instanceof Node \Expr \BooleanNot && !$ context ->null ()) {
682741 return $ this ->specifyTypesInCondition ($ scope , $ expr ->expr , $ context ->negate (), $ rootExpr );
683- } elseif ($ expr instanceof Node \Expr \Assign) {
742+ }
743+
744+ // $var = $expr
745+ if ($ expr instanceof Node \Expr \Assign) {
684746 if (!$ scope instanceof MutatingScope) {
685747 throw new ShouldNotHappenException ();
686748 }
@@ -689,11 +751,10 @@ public function specifyTypesInCondition(
689751 }
690752
691753 return $ this ->specifyTypesInCondition ($ scope ->exitFirstLevelStatements (), $ expr ->var , $ context , $ rootExpr );
692- } elseif (
693- $ expr instanceof Expr \Isset_
694- && count ($ expr ->vars ) > 0
695- && !$ context ->null ()
696- ) {
754+ }
755+
756+ // isset(...$vars)
757+ if ($ expr instanceof Expr \Isset_ && count ($ expr ->vars ) > 0 && !$ context ->null ()) {
697758 // rewrite multi param isset() to and-chained single param isset()
698759 if (count ($ expr ->vars ) > 1 ) {
699760 $ issets = [];
@@ -883,10 +944,10 @@ public function specifyTypesInCondition(
883944 }
884945
885946 return $ types ;
886- } elseif (
887- $ expr instanceof Expr \ BinaryOp \Coalesce
888- && ! $ context -> null ()
889- ) {
947+ }
948+
949+ // $a ?? $b
950+ if ( $ expr instanceof Expr \ BinaryOp \Coalesce && ! $ context -> null () ) {
890951 if (!$ context ->true ()) {
891952 if (!$ scope instanceof MutatingScope) {
892953 throw new ShouldNotHappenException ();
@@ -919,9 +980,11 @@ public function specifyTypesInCondition(
919980 );
920981 }
921982
922- } elseif (
923- $ expr instanceof Expr \Empty_
924- ) {
983+ return new SpecifiedTypes ([], [], false , [], $ rootExpr );
984+ }
985+
986+ // empty($expr)
987+ if ($ expr instanceof Expr \Empty_) {
925988 if (!$ scope instanceof MutatingScope) {
926989 throw new ShouldNotHappenException ();
927990 }
@@ -935,21 +998,25 @@ public function specifyTypesInCondition(
935998 new Expr \BooleanNot (new Expr \Isset_ ([$ expr ->expr ])),
936999 new Expr \BooleanNot ($ expr ->expr ),
9371000 ), $ context , $ rootExpr );
938- } elseif ($ expr instanceof Expr \ErrorSuppress) {
1001+ }
1002+
1003+ // @$a
1004+ if ($ expr instanceof Expr \ErrorSuppress) {
9391005 return $ this ->specifyTypesInCondition ($ scope , $ expr ->expr , $ context , $ rootExpr );
940- } elseif (
941- $ expr instanceof Expr \Ternary
942- && !$ context ->null ()
943- && $ scope ->getType ($ expr ->else )->isFalse ()->yes ()
944- ) {
1006+ }
1007+
1008+ // $cond ? $if : $else
1009+ if ($ expr instanceof Expr \Ternary && !$ context ->null () && $ scope ->getType ($ expr ->else )->isFalse ()->yes ()) {
9451010 $ conditionExpr = $ expr ->cond ;
9461011 if ($ expr ->if !== null ) {
9471012 $ conditionExpr = new BooleanAnd ($ conditionExpr , $ expr ->if );
9481013 }
9491014
9501015 return $ this ->specifyTypesInCondition ($ scope , $ conditionExpr , $ context , $ rootExpr );
1016+ }
9511017
952- } elseif ($ expr instanceof Expr \NullsafePropertyFetch && !$ context ->null ()) {
1018+ // $var?->name(...)
1019+ if ($ expr instanceof Expr \NullsafePropertyFetch && !$ context ->null ()) {
9531020 $ types = $ this ->specifyTypesInCondition (
9541021 $ scope ,
9551022 new BooleanAnd (
@@ -962,7 +1029,10 @@ public function specifyTypesInCondition(
9621029
9631030 $ nullSafeTypes = $ this ->handleDefaultTruthyOrFalseyContext ($ context , $ rootExpr , $ expr , $ scope );
9641031 return $ context ->true () ? $ types ->unionWith ($ nullSafeTypes ) : $ types ->normalize ($ scope )->intersectWith ($ nullSafeTypes ->normalize ($ scope ));
965- } elseif ($ expr instanceof Expr \NullsafeMethodCall && !$ context ->null ()) {
1032+ }
1033+
1034+ // $var?->name(...)
1035+ if ($ expr instanceof Expr \NullsafeMethodCall && !$ context ->null ()) {
9661036 $ types = $ this ->specifyTypesInCondition (
9671037 $ scope ,
9681038 new BooleanAnd (
@@ -975,11 +1045,10 @@ public function specifyTypesInCondition(
9751045
9761046 $ nullSafeTypes = $ this ->handleDefaultTruthyOrFalseyContext ($ context , $ rootExpr , $ expr , $ scope );
9771047 return $ context ->true () ? $ types ->unionWith ($ nullSafeTypes ) : $ types ->normalize ($ scope )->intersectWith ($ nullSafeTypes ->normalize ($ scope ));
978- } elseif (
979- $ expr instanceof Expr \New_
980- && $ expr ->class instanceof Name
981- && $ this ->reflectionProvider ->hasClass ($ expr ->class ->toString ())
982- ) {
1048+ }
1049+
1050+ // new $class(...)
1051+ if ($ expr instanceof Expr \New_ && $ expr ->class instanceof Name && $ this ->reflectionProvider ->hasClass ($ expr ->class ->toString ())) {
9831052 $ classReflection = $ this ->reflectionProvider ->getClass ($ expr ->class ->toString ());
9841053
9851054 if ($ classReflection ->hasConstructor ()) {
@@ -1003,7 +1072,11 @@ public function specifyTypesInCondition(
10031072 }
10041073 }
10051074 }
1006- } elseif (!$ context ->null ()) {
1075+
1076+ return new SpecifiedTypes ([], [], false , [], $ rootExpr );
1077+ }
1078+
1079+ if (!$ context ->null ()) {
10071080 return $ this ->handleDefaultTruthyOrFalseyContext ($ context , $ rootExpr , $ expr , $ scope );
10081081 }
10091082
0 commit comments