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

wurstscript / WurstScript / 268

29 Sep 2025 10:56AM UTC coverage: 64.762% (+2.5%) from 62.222%
268

Pull #1096

circleci

Frotty
Merge branch 'perf-improvements' of https://github.com/wurstscript/WurstScript into perf-improvements
Pull Request #1096: Perf improvements

18180 of 28072 relevant lines covered (64.76%)

0.65 hits per line

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

84.71
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

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

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

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

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

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

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

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

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

104
    }
1✔
105

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

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

123
    }
1✔
124

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

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

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

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

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

264
    }
1✔
265

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

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

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

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

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

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

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

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

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

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

601
}
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

© 2025 Coveralls, Inc