• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wurstscript / WurstScript / 254

24 Jun 2025 03:56PM UTC coverage: 62.245% (-0.03%) from 62.277%
254

push

circleci

Frotty
Ignore defunct test

17265 of 27737 relevant lines covered (62.25%)

0.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.41
de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/optimizer/SimpleRewrites.java
1
package de.peeeq.wurstscript.intermediatelang.optimizer;
2

3
import de.peeeq.wurstscript.WLogger;
4
import de.peeeq.wurstscript.WurstOperator;
5
import de.peeeq.wurstscript.jassIm.*;
6
import de.peeeq.wurstscript.translation.imoptimizer.OptimizerPass;
7
import de.peeeq.wurstscript.translation.imtranslation.ImHelper;
8
import de.peeeq.wurstscript.translation.imtranslation.ImTranslator;
9
import de.peeeq.wurstscript.types.TypesHelper;
10

11
import java.text.DecimalFormat;
12
import java.text.DecimalFormatSymbols;
13
import java.util.Iterator;
14
import java.util.List;
15
import java.util.Locale;
16

17
public class SimpleRewrites implements OptimizerPass {
1✔
18
    private SideEffectAnalyzer sideEffectAnalysis;
19
    private int totalRewrites = 0;
1✔
20
    private final boolean showRewrites = false;
1✔
21

22
    @Override
23
    public int optimize(ImTranslator trans) {
24
        ImProg prog = trans.getImProg();
1✔
25
        this.sideEffectAnalysis = new SideEffectAnalyzer(prog);
1✔
26
        totalRewrites = 0;
1✔
27
        optimizeElement(prog);
1✔
28
        // we need to flatten the program, because we introduced new
29
        // StatementExprs
30
        prog.flatten(trans);
1✔
31
        removeUnreachableCode(prog);
1✔
32
        return totalRewrites;
1✔
33
    }
34

35
    @Override
36
    public String getName() {
37
        return "Simple Rewrites";
1✔
38
    }
39

40
    private void removeUnreachableCode(ImProg prog) {
41
        prog.accept(new ImProg.DefaultVisitor() {
1✔
42
            @Override
43
            public void visit(ImStmts stmts) {
44
                super.visit(stmts);
1✔
45
                removeUnreachableCode(stmts);
1✔
46
            }
1✔
47
        });
48
    }
1✔
49

50
    private void removeUnreachableCode(ImStmts stmts) {
51
        Iterator<ImStmt> it = stmts.iterator();
1✔
52
        boolean reachable = true;
1✔
53
        while (it.hasNext()) {
1✔
54
            ImStmt s = it.next();
1✔
55
            if (reachable) {
1✔
56
                if (s instanceof ImReturn) {
1✔
57
                    reachable = false;
1✔
58
                } else if (s instanceof ImExitwhen) {
1✔
59
                    ImExitwhen imExitwhen = (ImExitwhen) s;
1✔
60
                    ImExpr expr = imExitwhen.getCondition();
1✔
61
                    if (expr instanceof ImBoolVal) {
1✔
62
                        boolean b = ((ImBoolVal) expr).getValB();
1✔
63
                        if (b) {
1✔
64
                            // found "exitwhen true"
65
                            reachable = false;
1✔
66
                        }
67
                    }
68
                }
1✔
69
            } else {
70
                totalRewrites++;
1✔
71
                it.remove();
1✔
72
            }
73
        }
1✔
74
    }
1✔
75

76
    /**
77
     * Recursively optimizes the element
78
     */
79
    private void optimizeElement(Element elem) {
80
        // optimize children:
81
        for (int i = 0; i < elem.size(); i++) {
1✔
82
            optimizeElement(elem.get(i));
1✔
83
            if (i > 0) {
1✔
84
                Element lookback = elem.get(i - 1);
1✔
85
                if (elem.get(i) instanceof ImExitwhen && lookback instanceof ImExitwhen) {
1✔
86
                    optimizeConsecutiveExitWhen((ImExitwhen) lookback, (ImExitwhen) elem.get(i));
1✔
87
                }
88

89
                if (elem.get(i) instanceof ImSet && lookback instanceof ImSet) {
1✔
90
                    optimizeConsecutiveSet((ImSet) lookback, (ImSet) elem.get(i));
1✔
91
                }
92
            }
93
        }
94
        if (elem instanceof ImOperatorCall) {
1✔
95
            ImOperatorCall opc = (ImOperatorCall) elem;
1✔
96
            optimizeOpCall(opc);
1✔
97
        } else if (elem instanceof ImIf) {
1✔
98
            ImIf imIf = (ImIf) elem;
1✔
99
            optimizeIf(imIf);
1✔
100
        } else if (elem instanceof ImExitwhen) {
1✔
101
            ImExitwhen imExitwhen = (ImExitwhen) elem;
1✔
102
            optimizeExitwhen(imExitwhen);
1✔
103
        }
104

105
    }
1✔
106

107
    private void optimizeConsecutiveExitWhen(ImExitwhen lookback, ImExitwhen element) {
108
        element.getCondition().setParent(null);
1✔
109
        lookback.setCondition(JassIm.ImOperatorCall(WurstOperator.OR, JassIm.ImExprs(lookback.getCondition().copy(), element.getCondition())));
1✔
110
        element.replaceBy(ImHelper.nullExpr());
1✔
111
        totalRewrites++;
1✔
112
    }
1✔
113

114
    private void optimizeExitwhen(ImExitwhen imExitwhen) {
115
        ImExpr expr = imExitwhen.getCondition();
1✔
116
        if (expr instanceof ImBoolVal) {
1✔
117
            boolean b = ((ImBoolVal) expr).getValB();
1✔
118
            if (!b) {
1✔
119
                imExitwhen.replaceBy(ImHelper.nullExpr());
1✔
120
                totalRewrites++;
1✔
121
            }
122
        }
123

124
    }
1✔
125

126
    /**
127
     * Rewrites if statements that only contain an exitwhen statement
128
     * so that the if's condition is combined with the exitwhen
129
     * <p>
130
     * if expr1
131
     * exitwhen expr2
132
     * <p>
133
     * to:
134
     * <p>
135
     * exitwhen expr1 and expr2
136
     */
137
    private void optimizeIfExitwhen(ImIf imIf) {
138
        ImExitwhen imStmt = (ImExitwhen) imIf.getThenBlock().get(0);
1✔
139
        imStmt.getCondition().setParent(null);
1✔
140
        imIf.getCondition().setParent(null);
1✔
141

142
        imStmt.setCondition((JassIm.ImOperatorCall(WurstOperator.AND, JassIm.ImExprs(imIf.getCondition(), imStmt.getCondition()))));
1✔
143
        imStmt.setParent(null);
1✔
144
        imIf.replaceBy(imStmt);
1✔
145
        totalRewrites++;
1✔
146
    }
1✔
147

148
    private void optimizeOpCall(ImOperatorCall opc) {
149
        // Binary
150
        boolean wasViable = true;
1✔
151
        if (opc.getArguments().size() > 1) {
1✔
152
            ImExpr left = opc.getArguments().get(0);
1✔
153
            ImExpr right = opc.getArguments().get(1);
1✔
154
            if (left instanceof ImBoolVal && right instanceof ImBoolVal) {
1✔
155
                boolean b1 = ((ImBoolVal) left).getValB();
1✔
156
                boolean b2 = ((ImBoolVal) right).getValB();
1✔
157
                boolean result;
158
                switch (opc.getOp()) {
1✔
159
                    case OR:
160
                        result = b1 || b2;
1✔
161
                        break;
1✔
162
                    case AND:
163
                        result = b1 && b2;
1✔
164
                        break;
1✔
165
                    case EQ:
166
                        result = b1 == b2;
×
167
                        break;
×
168
                    case NOTEQ:
169
                        result = b1 != b2;
×
170
                        break;
×
171
                    default:
172
                        result = false;
×
173
                        break;
174
                }
175
                opc.replaceBy(JassIm.ImBoolVal(result));
1✔
176
            } else if (left instanceof ImBoolVal) {
1✔
177
                boolean b1 = ((ImBoolVal) left).getValB();
1✔
178
                wasViable = replaceBoolTerm(opc, right, b1);
1✔
179
            } else if (right instanceof ImBoolVal) {
1✔
180
                boolean b2 = ((ImBoolVal) right).getValB();
1✔
181
                wasViable = replaceBoolTerm(opc, left, b2);
1✔
182
            } else if (left instanceof ImIntVal && right instanceof ImIntVal) {
1✔
183
                wasViable = optimizeIntInt(opc, wasViable, (ImIntVal) left, (ImIntVal) right);
1✔
184
            } else if (left instanceof ImRealVal && right instanceof ImRealVal) {
1✔
185
                wasViable = optimizeRealReal(opc, wasViable, (ImRealVal) left, (ImRealVal) right);
1✔
186
            } else if (right instanceof ImStringVal) {
1✔
187
                if (left instanceof ImStringVal) {
1✔
188
                    wasViable = optimizeStringString(opc, (ImStringVal) left, (ImStringVal) right);
1✔
189
                } else if (((ImStringVal) right).getValS().equalsIgnoreCase("") && opc.getOp() == WurstOperator.PLUS) {
1✔
190
                    left.setParent(null);
×
191
                    opc.replaceBy(left);
×
192
                    wasViable = true;
×
193
                } else {
194
                    wasViable = false;
1✔
195
                }
196
            } else {
197
                wasViable = false;
1✔
198
            }
199
        }
1✔
200

201
        // Unary
202
        else {
203
            ImExpr expr = opc.getArguments().get(0);
1✔
204
            if (opc.getOp() == WurstOperator.UNARY_MINUS && expr instanceof ImIntVal) {
1✔
205
                ImIntVal imIntVal = (ImIntVal) expr;
1✔
206
                if (imIntVal.getValI() <= 0) {
1✔
207
                    int inverseVal = imIntVal.getValI() * -1;
×
208
                    ImIntVal newVal = JassIm.ImIntVal(inverseVal);
×
209
                    opc.replaceBy(newVal);
×
210
                }
211
                wasViable = false;
1✔
212
            } else if (expr instanceof ImBoolVal) {
1✔
213
                boolean b1 = ((ImBoolVal) expr).getValB();
1✔
214
                boolean result;
215
                switch (opc.getOp()) {
1✔
216
                    case NOT:
217
                        result = !b1;
1✔
218
                        break;
1✔
219
                    default:
220
                        result = false;
×
221
                        break;
222
                }
223
                opc.replaceBy(JassIm.ImBoolVal(result));
1✔
224
            } else if (opc.getOp() == WurstOperator.NOT && expr instanceof ImOperatorCall) {
1✔
225
                // optimize negation of some operators
226
                ImOperatorCall inner = (ImOperatorCall) expr;
1✔
227
                switch (inner.getOp()) {
1✔
228
                    case NOT:
229
                        opc.replaceBy(inner.getArguments().remove(0));
1✔
230
                        break;
1✔
231
                    case EQ:
232
                    case NOTEQ:
233
                    case LESS:
234
                    case LESS_EQ:
235
                    case GREATER:
236
                    case GREATER_EQ:
237
                        opc.replaceBy(JassIm.ImOperatorCall(oppositeOperator(inner.getOp()), JassIm.ImExprs(inner.getArguments().removeAll())));
1✔
238
                        break;
1✔
239
                    case OR:
240
                    case AND:
241
                        // DeMorgan not(a and b) => not a or not b; not(a or b) => not a and not b
242
                        List<ImExpr> args = inner.getArguments().removeAll();
1✔
243
                        ImExprs imExprs = JassIm.ImExprs();
1✔
244
                        args.forEach((e) ->
1✔
245
                                imExprs.add(JassIm.ImOperatorCall(WurstOperator.NOT, JassIm.ImExprs(e.copy()))));
1✔
246

247
                        ImOperatorCall opCall = JassIm.ImOperatorCall(oppositeOperator(inner.getOp()), imExprs);
1✔
248
                        opc.replaceBy(opCall);
1✔
249
                        break;
1✔
250
                    default:
251
                        wasViable = false;
×
252
                        break;
253
                }
254
            } else {
1✔
255
                wasViable = false;
1✔
256
            }
257
        }
258
        if (wasViable) {
1✔
259
            totalRewrites++;
1✔
260
            if (showRewrites) {
261
                WLogger.info("opcall rewrite: " + opc);
262
            }
263
        }
264

265
    }
1✔
266

267
    private boolean optimizeStringString(ImOperatorCall opc, ImStringVal left, ImStringVal right) {
268
        String f1 = left.getValS();
1✔
269
        String f2 = right.getValS();
1✔
270
        switch (opc.getOp()) {
1✔
271
            case PLUS:
272
                opc.replaceBy(JassIm.ImStringVal(f1 + f2));
1✔
273
                return true;
1✔
274
            default:
275
                break;
276
        }
277
        return false;
1✔
278
    }
279

280
    private boolean optimizeRealReal(ImOperatorCall opc, boolean wasViable, ImRealVal left, ImRealVal right) {
281
        float f1 = Float.parseFloat(left.getValR());
1✔
282
        float f2 = Float.parseFloat(right.getValR());
1✔
283
        boolean isConditional = false;
1✔
284
        boolean isArithmetic = false;
1✔
285
        boolean result = false;
1✔
286
        float resultVal = 0;
1✔
287
        switch (opc.getOp()) {
1✔
288
            case GREATER:
289
                result = f1 > f2;
×
290
                isConditional = true;
×
291
                break;
×
292
            case GREATER_EQ:
293
                result = f1 >= f2;
×
294
                isConditional = true;
×
295
                break;
×
296
            case LESS:
297
                result = f1 < f2;
×
298
                isConditional = true;
×
299
                break;
×
300
            case LESS_EQ:
301
                result = f1 <= f2;
×
302
                isConditional = true;
×
303
                break;
×
304
            case EQ:
305
                result = f1 == f2;
1✔
306
                isConditional = true;
1✔
307
                break;
1✔
308
            case NOTEQ:
309
                result = f1 != f2;
×
310
                isConditional = true;
×
311
                break;
×
312
            case PLUS:
313
                resultVal = f1 + f2;
1✔
314
                isArithmetic = true;
1✔
315
                break;
1✔
316
            case MINUS:
317
                resultVal = f1 - f2;
1✔
318
                isArithmetic = true;
1✔
319
                break;
1✔
320
            case MULT:
321
                resultVal = f1 * f2;
1✔
322
                isArithmetic = true;
1✔
323
                break;
1✔
324
            case MOD_REAL:
325
                if (f2 != 0) {
1✔
326
                    resultVal = f1 % f2;
1✔
327
                    isArithmetic = true;
1✔
328
                }
329
                break;
330
            case DIV_INT:
331
                if (f2 != 0) {
×
332
                    resultVal = f1 / f2;
×
333
                    isArithmetic = true;
×
334
                }
335
                break;
336
            case DIV_REAL:
337
                if (f2 != 0) {
1✔
338
                    resultVal = f1 / f2;
1✔
339
                    isArithmetic = true;
1✔
340
                }
341
                break;
342
            default:
343
                result = false;
×
344
                isConditional = false;
×
345
                isArithmetic = false;
×
346
                break;
347
        }
348
        if (isConditional) {
1✔
349
            opc.replaceBy(JassIm.ImBoolVal(result));
1✔
350
        } else if (isArithmetic) {
1✔
351
            // convert result to string, using 4 decimal digits
352
            String s = floatToStringWithDecimalDigits(resultVal, 4);
1✔
353
            // String s = new BigDecimal(resultVal).toPlainString();
354
            // check if the string representation is exact
355
            if (Float.parseFloat(s) == resultVal) {
1✔
356
                opc.replaceBy(JassIm.ImRealVal(s));
1✔
357
            } else {
358
                s = floatToStringWithDecimalDigits(resultVal, 9);
1✔
359
                if (Float.parseFloat(s) == resultVal) {
1✔
360
                    opc.replaceBy(JassIm.ImRealVal(s));
1✔
361
                } else {
362
                    wasViable = false;
×
363
                }
364
            }
365
        } else {
1✔
366
            wasViable = false;
×
367
        }
368
        return wasViable;
1✔
369
    }
370

371
    private boolean optimizeIntInt(ImOperatorCall opc, boolean wasViable, ImIntVal left, ImIntVal right) {
372
        int i1 = left.getValI();
1✔
373
        int i2 = right.getValI();
1✔
374
        boolean isConditional = false;
1✔
375
        boolean isArithmetic = false;
1✔
376
        boolean result = false;
1✔
377
        int resultVal = 0;
1✔
378
        switch (opc.getOp()) {
1✔
379
            case GREATER:
380
                result = i1 > i2;
1✔
381
                isConditional = true;
1✔
382
                break;
1✔
383
            case GREATER_EQ:
384
                result = i1 >= i2;
1✔
385
                isConditional = true;
1✔
386
                break;
1✔
387
            case LESS:
388
                result = i1 < i2;
1✔
389
                isConditional = true;
1✔
390
                break;
1✔
391
            case LESS_EQ:
392
                result = i1 <= i2;
1✔
393
                isConditional = true;
1✔
394
                break;
1✔
395
            case EQ:
396
                result = i1 == i2;
1✔
397
                isConditional = true;
1✔
398
                break;
1✔
399
            case NOTEQ:
400
                result = i1 != i2;
1✔
401
                isConditional = true;
1✔
402
                break;
1✔
403
            case PLUS:
404
                resultVal = i1 + i2;
1✔
405
                isArithmetic = true;
1✔
406
                break;
1✔
407
            case MINUS:
408
                resultVal = i1 - i2;
1✔
409
                isArithmetic = true;
1✔
410
                break;
1✔
411
            case MULT:
412
                resultVal = i1 * i2;
1✔
413
                isArithmetic = true;
1✔
414
                break;
1✔
415
            case MOD_INT:
416
                if (i2 != 0) {
1✔
417
                    resultVal = i1 % i2;
1✔
418
                    isArithmetic = true;
1✔
419
                }
420
                break;
421
            case MOD_REAL:
422
                float f1 = i1;
×
423
                float f2 = i2;
×
424
                if (f2 != 0) {
×
425
                    float resultF = f1 % f2;
×
426
                    opc.replaceBy(JassIm.ImRealVal(String.valueOf(resultF)));
×
427
                }
×
428
                break;
429
            case DIV_INT:
430
                if (i2 != 0) {
1✔
431
                    resultVal = i1 / i2;
1✔
432
                    isArithmetic = true;
1✔
433
                }
434
                break;
435
            case DIV_REAL:
436
                float f3 = i1;
×
437
                float f4 = i2;
×
438
                if (f4 != 0) {
×
439
                    float resultF = f3 / f4;
×
440
                    opc.replaceBy(JassIm.ImRealVal(String.valueOf(resultF)));
×
441
                }
×
442
                break;
443
            default:
444
                result = false;
×
445
                isConditional = false;
×
446
                isArithmetic = false;
×
447
                break;
448
        }
449
        if (isConditional) {
1✔
450
            opc.replaceBy(JassIm.ImBoolVal(result));
1✔
451
        } else if (isArithmetic) {
1✔
452
            opc.replaceBy(JassIm.ImIntVal(resultVal));
1✔
453
        } else {
454
            wasViable = false;
1✔
455
        }
456
        return wasViable;
1✔
457
    }
458

459
    private boolean replaceBoolTerm(ImOperatorCall opc, ImExpr expr, boolean b2) {
460
        switch (opc.getOp()) {
1✔
461
            case OR:
462
                if (b2) {
1✔
463
                    opc.replaceBy(JassIm.ImBoolVal(true));
1✔
464
                } else {
465
                    expr.setParent(null);
1✔
466
                    opc.replaceBy(expr);
1✔
467
                }
468
                break;
1✔
469
            case AND:
470
                if (b2) {
1✔
471
                    expr.setParent(null);
1✔
472
                    opc.replaceBy(expr);
1✔
473
                } else {
474
                    opc.replaceBy(JassIm.ImBoolVal(false));
1✔
475
                }
476
                break;
1✔
477
            default:
478
                return false;
×
479
        }
480
        return true;
1✔
481
    }
482

483
    /**
484
     * returns the opposite of an operator
485
     */
486
    private WurstOperator oppositeOperator(WurstOperator op) {
487
        switch (op) {
1✔
488
            case EQ:
489
                return WurstOperator.NOTEQ;
1✔
490
            case GREATER:
491
                return WurstOperator.LESS_EQ;
1✔
492
            case GREATER_EQ:
493
                return WurstOperator.LESS;
1✔
494
            case LESS:
495
                return WurstOperator.GREATER_EQ;
1✔
496
            case LESS_EQ:
497
                return WurstOperator.GREATER;
1✔
498
            case NOTEQ:
499
                return WurstOperator.EQ;
1✔
500
            case AND:
501
                return WurstOperator.OR;
1✔
502
            case OR:
503
                return WurstOperator.AND;
1✔
504
            default:
505
                throw new Error("operator " + op + " does not have an opposite.");
×
506
        }
507
    }
508

509
    private static String floatToStringWithDecimalDigits(float resultVal, int digits) {
510
        DecimalFormat format = new DecimalFormat();
1✔
511
        // use a fixed locale, so that it does not randomly replace a dot by
512
        // comma on German PCs
513
        // hope this works
514
        format.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
1✔
515
        format.setMinimumIntegerDigits(1);
1✔
516
        format.setMaximumFractionDigits(digits);
1✔
517
        format.setMinimumFractionDigits(1);
1✔
518
        format.setGroupingUsed(false);
1✔
519
        String s = format.format(resultVal);
1✔
520
        return s;
1✔
521
    }
522

523
    private void optimizeIf(ImIf imIf) {
524
        if (imIf.getThenBlock().isEmpty() && imIf.getElseBlock().isEmpty()) {
1✔
525
            totalRewrites++;
1✔
526
            imIf.replaceBy(imIf.getCondition().copy());
1✔
527
        } else if (imIf.getCondition() instanceof ImBoolVal) {
1✔
528
            ImBoolVal boolVal = (ImBoolVal) imIf.getCondition();
1✔
529
            if (boolVal.getValB()) {
1✔
530
                // we have something like 'if true ...'
531
                // replace the if statement with the then-block
532
                // we have to use ImStatementExpr to get multiple statements
533
                // into one statement as needed
534
                // for the replaceBy function
535
                // we need to copy the thenBlock because otherwise it would have
536
                // two parents (we have not removed it from the old if-block)
537
                imIf.replaceBy(ImHelper.statementExprVoid(imIf.getThenBlock().copy()));
1✔
538
                totalRewrites++;
1✔
539
            } else {
540
                if (!imIf.getElseBlock().isEmpty()) {
1✔
541
                    imIf.replaceBy(ImHelper.statementExprVoid(imIf.getElseBlock().copy()));
1✔
542
                    totalRewrites++;
1✔
543
                } else {
544
                    imIf.replaceBy(ImHelper.nullExpr());
1✔
545
                    totalRewrites++;
1✔
546
                }
547
            }
548
        } else if (imIf.getElseBlock().isEmpty() && imIf.getThenBlock().size() == 1 && imIf.getThenBlock().get(0) instanceof ImExitwhen) {
1✔
549
            optimizeIfExitwhen(imIf);
1✔
550
        }
551
    }
1✔
552

553
    /**
554
     * Optimizes
555
     * <p>
556
     * set x = expr1
557
     * set x = x ⊕ expr2
558
     * <p>
559
     * into:
560
     * <p>
561
     * set x  = expr1 ⊕ expr2
562
     * <p>
563
     * like code that is created by the branch merger
564
     */
565
    private void optimizeConsecutiveSet(ImSet imSet1, ImSet imSet2) {
566
        ImVar leftVar1;
567
        if (imSet1.getLeft() instanceof ImVarAccess) {
1✔
568
            leftVar1 = ((ImVarAccess) imSet1.getLeft()).getVar();
1✔
569
        } else {
570
            return;
1✔
571
        }
572
        ImVar leftVar2;
573
        if (imSet2.getLeft() instanceof ImVarAccess) {
1✔
574
            leftVar2 = ((ImVarAccess) imSet2.getLeft()).getVar();
1✔
575
        } else {
576
            return;
1✔
577
        }
578

579
        ImExpr rightExpr1 = imSet1.getRight();
1✔
580
        ImExpr rightExpr2 = imSet2.getRight();
1✔
581

582
        if (leftVar1 == leftVar2) {
1✔
583
            if (rightExpr2 instanceof ImOperatorCall) {
1✔
584
                ImOperatorCall rightOpCall2 = (ImOperatorCall) rightExpr2;
1✔
585
                if (rightOpCall2.getArguments().size() == 2) {
1✔
586
                    if (rightOpCall2.getArguments().get(0) instanceof ImVarAccess) {
1✔
587
                        ImVarAccess imVarAccess2 = (ImVarAccess) rightOpCall2.getArguments().get(0);
1✔
588
                        if (imVarAccess2.getVar() == leftVar2) {
1✔
589
                            if (sideEffectAnalysis.cannotUseVar(rightOpCall2.getArguments().get(1), leftVar1)) {
1✔
590
                                rightExpr1.setParent(null);
1✔
591
                                imVarAccess2.replaceBy(rightExpr1);
1✔
592
                                imSet1.replaceBy(ImHelper.nullExpr());
1✔
593
                                totalRewrites++;
1✔
594
                            }
595
                        }
596
                    }
597
                }
598
            }
599
        }
600
    }
1✔
601

602
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc