52
52
import org .codehaus .groovy .ast .expr .AttributeExpression ;
53
53
import org .codehaus .groovy .ast .expr .BinaryExpression ;
54
54
import org .codehaus .groovy .ast .expr .BitwiseNegationExpression ;
55
+ import org .codehaus .groovy .ast .expr .BooleanExpression ;
55
56
import org .codehaus .groovy .ast .expr .CastExpression ;
56
57
import org .codehaus .groovy .ast .expr .ClassExpression ;
57
58
import org .codehaus .groovy .ast .expr .ClosureExpression ;
185
186
import static org .codehaus .groovy .ast .tools .GeneralUtils .castX ;
186
187
import static org .codehaus .groovy .ast .tools .GeneralUtils .constX ;
187
188
import static org .codehaus .groovy .ast .tools .GeneralUtils .getSetterName ;
189
+ import static org .codehaus .groovy .ast .tools .GeneralUtils .ifElseS ;
188
190
import static org .codehaus .groovy .ast .tools .GeneralUtils .isOrImplements ;
189
191
import static org .codehaus .groovy .ast .tools .GeneralUtils .localVarX ;
190
192
import static org .codehaus .groovy .ast .tools .GeneralUtils .thisPropX ;
219
221
import static org .codehaus .groovy .syntax .Types .KEYWORD_IN ;
220
222
import static org .codehaus .groovy .syntax .Types .KEYWORD_INSTANCEOF ;
221
223
import static org .codehaus .groovy .syntax .Types .LEFT_SQUARE_BRACKET ;
224
+ import static org .codehaus .groovy .syntax .Types .LOGICAL_OR ;
222
225
import static org .codehaus .groovy .syntax .Types .MINUS_MINUS ;
223
226
import static org .codehaus .groovy .syntax .Types .MOD ;
224
227
import static org .codehaus .groovy .syntax .Types .MOD_EQUAL ;
@@ -3793,21 +3796,8 @@ protected void typeCheckClosureCall(final Expression callArguments, final ClassN
3793
3796
@ Override
3794
3797
public void visitIfElse (final IfStatement ifElse ) {
3795
3798
Map <VariableExpression , List <ClassNode >> oldTracker = pushAssignmentTracking ();
3796
-
3797
3799
try {
3798
- // create a new temporary element in the if-then-else type info
3799
- typeCheckingContext .pushTemporaryTypeInfo ();
3800
- visitStatement (ifElse );
3801
- ifElse .getBooleanExpression ().visit (this );
3802
- ifElse .getIfBlock ().visit (this );
3803
-
3804
- // pop if-then-else temporary type info
3805
- typeCheckingContext .popTemporaryTypeInfo ();
3806
-
3807
- // GROOVY-6099: restore assignment info as before the if branch
3808
- restoreTypeBeforeConditional ();
3809
-
3810
- ifElse .getElseBlock ().visit (this );
3800
+ visitIfElseMaybeOrBranches (ifElse , true );
3811
3801
} finally {
3812
3802
popAssignmentTracking (oldTracker );
3813
3803
}
@@ -3822,6 +3812,52 @@ public void visitIfElse(final IfStatement ifElse) {
3822
3812
}
3823
3813
}
3824
3814
3815
+ private void visitIfElseMaybeOrBranches (IfStatement ifElse , boolean topLevel ) {
3816
+ BooleanExpression condition = ifElse .getBooleanExpression ();
3817
+ BinaryExpression lor = null ;
3818
+ if (condition .getExpression () instanceof BinaryExpression ) {
3819
+ lor = (BinaryExpression ) condition .getExpression ();
3820
+ if (lor .getOperation ().getType () != LOGICAL_OR ) {
3821
+ lor = null ;
3822
+ }
3823
+ }
3824
+ // for logical OR, any one branch may be true branch, so traverse separately
3825
+ if (lor != null ) {
3826
+ IfStatement left = ifElseS (lor .getLeftExpression (), ifElse .getIfBlock (), ifElse .getElseBlock ());
3827
+ // left.setSourcePosition(ifElse);
3828
+ typeCheckingContext .pushTemporaryTypeInfo ();
3829
+ visitIfElseMaybeOrBranches (left , false );
3830
+ typeCheckingContext .popTemporaryTypeInfo ();
3831
+ restoreTypeBeforeConditional ();
3832
+ IfStatement right = ifElseS (lor .getRightExpression (), ifElse .getIfBlock (), ifElse .getElseBlock ());
3833
+ // right.setSourcePosition(ifElse);
3834
+ typeCheckingContext .pushTemporaryTypeInfo ();
3835
+ visitIfElseMaybeOrBranches (right , false );
3836
+ typeCheckingContext .popTemporaryTypeInfo ();
3837
+ restoreTypeBeforeConditional ();
3838
+ }
3839
+ if (topLevel || lor == null ) {
3840
+ // do it all again to get correct union type for casting (hush warnings?)
3841
+ visitIfElseBranches (ifElse );
3842
+ }
3843
+ }
3844
+
3845
+ private void visitIfElseBranches (IfStatement ifElse ) {
3846
+ // create a new temporary element in the if-then-else type info
3847
+ typeCheckingContext .pushTemporaryTypeInfo ();
3848
+ visitStatement (ifElse );
3849
+ ifElse .getBooleanExpression ().visit (this );
3850
+ ifElse .getIfBlock ().visit (this );
3851
+
3852
+ // pop if-then-else temporary type info
3853
+ typeCheckingContext .popTemporaryTypeInfo ();
3854
+
3855
+ // GROOVY-6099: restore assignment info as before the if branch
3856
+ restoreTypeBeforeConditional ();
3857
+
3858
+ ifElse .getElseBlock ().visit (this );
3859
+ }
3860
+
3825
3861
protected void visitInstanceofNot (final BinaryExpression be ) {
3826
3862
BlockStatement currentBlock = typeCheckingContext .enclosingBlocks .getFirst ();
3827
3863
assert currentBlock != null ;
0 commit comments