in legacy/java/piranha/src/main/java/com/uber/piranha/XPFlagCleaner.java [1397:1523]
public Description matchIf(IfTree ifTree, VisitorState visitorState) {
if (shouldSkip(visitorState)) return Description.NO_MATCH;
if (overLaps(ifTree, visitorState)) {
return Description.NO_MATCH;
}
// Ignore if this is part of an else-if clause, we will process it all at once
// when we get to the topmost if.
Tree parentTree = visitorState.getPath().getParentPath().getLeaf();
if (parentTree.getKind().equals(Kind.IF)) {
Tree parentElseChild = ((IfTree) parentTree).getElseStatement();
if (parentElseChild != null && parentElseChild.equals(ifTree)) {
return Description.NO_MATCH;
}
}
ParenthesizedTree parenTree = (ParenthesizedTree) ifTree.getCondition();
Value x = evalExpr(parenTree.getExpression(), visitorState);
boolean update = false;
String replacementString = EMPTY;
String replacementPrefix = EMPTY;
boolean lastStmtIsReturn = false;
Set<StatementTree> removedBranches = new LinkedHashSet<StatementTree>();
// This code simplifies a nested if {...} (else if {...})* (else {...})? three all at once
IfTree subIfTree = ifTree;
boolean recurse;
do {
recurse = false;
StatementTree elseStatement = subIfTree.getElseStatement();
if (x.equals(Value.TRUE)) {
update = true;
if (elseStatement != null) {
removedBranches.add(elseStatement);
}
replacementString = visitorState.getSourceForNode(subIfTree.getThenStatement());
lastStmtIsReturn = endsWithReturn(ifTree.getThenStatement());
} else if (x.equals(Value.FALSE)) {
update = true;
if (elseStatement != null) {
removedBranches.add(subIfTree.getThenStatement());
replacementString = visitorState.getSourceForNode(elseStatement);
if (elseStatement.getKind().equals(Kind.IF)) {
// Keep going, in case we can eliminate more of the branches of the
// nested if.
recurse = true;
subIfTree = (IfTree) elseStatement;
ParenthesizedTree pT = (ParenthesizedTree) subIfTree.getCondition();
x = evalExpr(pT, visitorState);
} else {
lastStmtIsReturn = endsWithReturn(subIfTree.getElseStatement());
}
}
} else {
// The condition doesn't simplify to a constant, but the condition to some nested "else if"
// might.
if (elseStatement != null && elseStatement.getKind().equals(Kind.IF)) {
// Copy the initial if condition (don't mark as needing update yet)
replacementPrefix +=
"if " + visitorState.getSourceForNode(subIfTree.getCondition()) + " ";
replacementPrefix +=
visitorState.getSourceForNode(subIfTree.getThenStatement()) + " else ";
// Then recurse on the else case
recurse = true;
subIfTree = (IfTree) elseStatement;
ParenthesizedTree pT = (ParenthesizedTree) subIfTree.getCondition();
x = evalExpr(pT, visitorState);
}
}
} while (recurse);
if (update) {
if (!replacementPrefix.equals(EMPTY)) {
replacementString = replacementPrefix + replacementString;
} else {
replacementString = stripBraces(replacementString);
}
Description.Builder builder = buildDescription(ifTree);
// We use SuggestedFix.Builder to AND-compose fixes. Note that calling
// Description.Builder.addFix(...) multiple times is interpreted as OR-composing
// multiple candidate fixes (i.e. "Fix by doing A or B or C" where we want
// "Fix by doing A and B and C")
SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
if (lastStmtIsReturn) {
// find the parent, and if it's a BlockTree, replace the if statement and delete any
// subsequent statements
Tree parent = visitorState.getPath().getParentPath().getLeaf();
// note that parent may not be a block, e.g., if we have a parent if statement with no
// braces for the body
if (parent instanceof BlockTree) {
BlockTree block = (BlockTree) parent;
boolean foundIf = false;
for (StatementTree stmt : block.getStatements()) {
if (foundIf) {
// We are past the if statement, so everything after this will be deleted,
// decrement all usage counts accordingly
decrementAllSymbolUsages(stmt, visitorState, fixBuilder);
fixBuilder.delete(stmt);
} else if (!stmt.equals(ifTree)) {
// preceding statement, keep it
continue;
} else {
// we reached the if
for (StatementTree removedBranch : removedBranches) {
decrementAllSymbolUsages(removedBranch, visitorState, fixBuilder);
}
decrementAllSymbolUsages(ifTree.getCondition(), visitorState, fixBuilder);
fixBuilder.replace(ifTree, replacementString);
// elide the remaining statements
foundIf = true;
}
}
// Usage counts already decremented above.
endPos = visitorState.getEndPosition(block);
return builder.addFix(fixBuilder.build()).build();
}
}
fixBuilder.replace(ifTree, replacementString);
for (StatementTree removedBranch : removedBranches) {
decrementAllSymbolUsages(removedBranch, visitorState, fixBuilder);
}
decrementAllSymbolUsages(ifTree.getCondition(), visitorState, fixBuilder);
endPos = visitorState.getEndPosition(ifTree);
return builder.addFix(fixBuilder.build()).build();
}
return Description.NO_MATCH;
}