-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
switch
statement decompilation to when
- Loading branch information
Showing
5 changed files
with
255 additions
and
0 deletions.
There are no files selected for viewing
22 changes: 22 additions & 0 deletions
22
plugins/kotlin/src/main/java/org/vineflower/kotlin/expr/KSwitchHeadExprent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package org.vineflower.kotlin.expr; | ||
|
||
import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; | ||
import org.jetbrains.java.decompiler.modules.decompiler.exps.SwitchHeadExprent; | ||
import org.jetbrains.java.decompiler.util.TextBuffer; | ||
|
||
public class KSwitchHeadExprent extends SwitchHeadExprent implements KExprent { | ||
public KSwitchHeadExprent(SwitchHeadExprent ex) { | ||
super(ex.getValue(), ex.bytecode); | ||
setCaseValues(ex.getCaseValues()); | ||
} | ||
|
||
@Override | ||
public TextBuffer toJava(int indent) { | ||
TextBuffer buf = new TextBuffer(); | ||
|
||
buf.append(getValue().toJava(indent)).enclose("when (", ")"); | ||
buf.addStartBytecodeMapping(bytecode); | ||
|
||
return buf; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
177 changes: 177 additions & 0 deletions
177
plugins/kotlin/src/main/java/org/vineflower/kotlin/stat/KSwitchStatement.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
package org.vineflower.kotlin.stat; | ||
|
||
import org.jetbrains.java.decompiler.main.DecompilerContext; | ||
import org.jetbrains.java.decompiler.main.collectors.ImportCollector; | ||
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; | ||
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; | ||
import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; | ||
import org.jetbrains.java.decompiler.modules.decompiler.exps.ConstExprent; | ||
import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; | ||
import org.jetbrains.java.decompiler.modules.decompiler.exps.FieldExprent; | ||
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement; | ||
import org.jetbrains.java.decompiler.modules.decompiler.stats.SwitchStatement; | ||
import org.jetbrains.java.decompiler.struct.gen.VarType; | ||
import org.jetbrains.java.decompiler.util.TextBuffer; | ||
import org.vineflower.kotlin.util.KExprProcessor; | ||
|
||
import java.util.List; | ||
|
||
public class KSwitchStatement extends SwitchStatement { | ||
public KSwitchStatement(SwitchStatement statement) { | ||
super(); | ||
|
||
getCaseStatements().addAll(statement.getCaseStatements()); | ||
getCaseEdges().addAll(statement.getCaseEdges()); | ||
getCaseValues().addAll(statement.getCaseValues()); | ||
getCaseGuards().addAll(statement.getCaseGuards()); | ||
//TODO: check if scoped case statements are needed? | ||
getHeadexprentList().remove(0); // remove added null | ||
getHeadexprentList().addAll(statement.getHeadexprentList()); | ||
|
||
setFirst(statement.getFirst()); | ||
setPhantom(statement.isPhantom()); // Only type of statement that can be phantom | ||
stats.addAllWithKey(statement.getStats(), statement.getStats().getLstKeys()); | ||
parent = statement.getParent(); | ||
first = statement.getFirst(); | ||
exprents = statement.getExprents(); | ||
labelEdges.addAll(statement.getLabelEdges()); | ||
varDefinitions.addAll(statement.getVarDefinitions()); | ||
post = statement.getPost(); | ||
lastBasicType = statement.getLastBasicType(); | ||
|
||
isMonitorEnter = statement.isMonitorEnter(); | ||
containsMonitorExit = statement.containsMonitorExit(); | ||
isLastAthrow = statement.containsMonitorExitOrAthrow() && !containsMonitorExit; | ||
|
||
continueSet = statement.getContinueSet(); | ||
|
||
// Set up default edge | ||
initSimpleCopy(); | ||
} | ||
|
||
@Override | ||
public TextBuffer toJava(int indent) { | ||
TextBuffer buf = new TextBuffer(); | ||
buf.append(ExprProcessor.listToJava(varDefinitions, indent)); | ||
|
||
if (isLabeled()) { | ||
buf.appendIndent(indent++) | ||
.append("run label") | ||
.append(id) | ||
.append("@{") | ||
.appendLineSeparator(); | ||
} | ||
|
||
buf.appendIndent(indent).append(first.toJava()); | ||
|
||
boolean showIfHidden = DecompilerContext.getOption(IFernflowerPreferences.SHOW_HIDDEN_STATEMENTS); | ||
|
||
if (isPhantom()) { | ||
if (!showIfHidden) { | ||
return buf; | ||
} else { | ||
buf.appendIndent(indent) | ||
.append("/*") | ||
.appendLineSeparator(); | ||
} | ||
} | ||
|
||
buf.append(getHeadexprent().toJava(indent)) | ||
.append(" {") | ||
.appendLineSeparator(); | ||
|
||
VarType switchType = getHeadexprent().getExprType(); | ||
|
||
for (int i = 0; i < getCaseStatements().size(); i++) { | ||
Statement stat = getCaseStatements().get(i); | ||
List<StatEdge> edges = getCaseEdges().get(i); | ||
List<Exprent> values = getCaseValues().get(i); | ||
// Exprent guard = getCaseGuards().size() > i ? getCaseGuards().get(i) : null; | ||
|
||
boolean anyNonDefault = false; | ||
for (int j = 0; j < edges.size(); j++) { | ||
if (edges.get(j) == getDefaultEdge()) { | ||
continue; // Default / "else" edges must show up alone | ||
} | ||
|
||
anyNonDefault = true; | ||
|
||
Exprent value = values.get(j); | ||
|
||
if (j == 0) { | ||
buf.appendIndent(indent + 1); | ||
} else { | ||
buf.append(", "); | ||
} | ||
|
||
if (value instanceof ConstExprent && !VarType.VARTYPE_NULL.equals(value.getExprType())) { | ||
ConstExprent constValue = (ConstExprent) value.copy(); | ||
constValue.setConstType(switchType); | ||
} | ||
|
||
if (value instanceof FieldExprent field && field.isStatic()) { // enum | ||
ImportCollector importCollector = DecompilerContext.getImportCollector(); | ||
buf.appendClass(importCollector.getShortName(field.getClassname()), false, field.getClassname()) | ||
.append('.') | ||
.appendField(field.getName(), false, field.getClassname(), field.getName(), field.getDescriptor()); | ||
} else { | ||
buf.append(value.toJava(indent)); | ||
} | ||
} | ||
|
||
TextBuffer body = KExprProcessor.jmpWrapper(stat, indent + 2, true); | ||
|
||
if (anyNonDefault) { | ||
buf.append(" -> "); | ||
if (body.countLines() > 1) { | ||
buf.append("{") | ||
.appendLineSeparator() | ||
.append(body) | ||
.appendIndent(indent + 1) | ||
.append("}") | ||
.appendLineSeparator(); | ||
} else { | ||
int indentSize = ((String) DecompilerContext.getProperty(IFernflowerPreferences.INDENT_STRING)).length(); | ||
body.setStart(indentSize * (indent + 2)); | ||
buf.append(body); | ||
} | ||
} | ||
|
||
if (edges.contains(getDefaultEdge())) { | ||
buf.appendIndent(indent + 1) | ||
.append("else -> "); | ||
|
||
if (body.countLines() > 1) { | ||
buf.append("{") | ||
.appendLineSeparator() | ||
.append(body) | ||
.appendIndent(indent + 1) | ||
.append("}") | ||
.appendLineSeparator(); | ||
} else { | ||
int indentSize = ((String) DecompilerContext.getProperty(IFernflowerPreferences.INDENT_STRING)).length(); | ||
body.setStart(indentSize * (indent + 2)); | ||
buf.append(body); | ||
} | ||
} | ||
} | ||
|
||
buf.appendIndent(indent) | ||
.append("}") | ||
.appendLineSeparator(); | ||
|
||
if (isLabeled()) { | ||
buf.appendIndent(--indent) | ||
.append("}") | ||
.appendLineSeparator(); | ||
} | ||
|
||
if (isPhantom()) { | ||
buf.appendIndent(indent) | ||
.append("*/") | ||
.appendLineSeparator(); | ||
} | ||
|
||
return buf; | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
plugins/kotlin/src/main/java/org/vineflower/kotlin/util/KExprProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package org.vineflower.kotlin.util; | ||
|
||
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; | ||
import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; | ||
import org.jetbrains.java.decompiler.modules.decompiler.stats.DummyExitStatement; | ||
import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement; | ||
import org.jetbrains.java.decompiler.util.TextBuffer; | ||
|
||
import java.util.List; | ||
|
||
public class KExprProcessor { | ||
public static TextBuffer jmpWrapper(Statement stat, int indent, boolean isSwitch) { | ||
TextBuffer buf = stat.toJava(indent); | ||
|
||
List<StatEdge> successors = stat.getSuccessorEdges(Statement.STATEDGE_DIRECT_ALL); | ||
if (successors.size() == 1) { | ||
StatEdge edge = successors.get(0); | ||
if (edge.getType() != StatEdge.TYPE_REGULAR && edge.explicit && !(edge.getDestination() instanceof DummyExitStatement)) { | ||
TextBuffer innerBuf = new TextBuffer(); | ||
innerBuf.appendIndent(indent); | ||
|
||
switch (edge.getType()) { | ||
case StatEdge.TYPE_BREAK -> { | ||
ExprProcessor.addDeletedGotoInstructionMapping(stat, buf); | ||
if (!isSwitch || edge.labeled) { | ||
innerBuf.append("break"); | ||
} | ||
} | ||
case StatEdge.TYPE_CONTINUE -> { | ||
ExprProcessor.addDeletedGotoInstructionMapping(stat, buf); | ||
innerBuf.append("continue"); | ||
} | ||
} | ||
|
||
if (edge.labeled) { | ||
innerBuf.append("@label").append(edge.closure.id); | ||
} | ||
|
||
if (!innerBuf.containsOnlyWhitespaces()) { | ||
buf.append(innerBuf).appendLineSeparator(); | ||
} else { | ||
innerBuf.convertToStringAndAllowDataDiscard(); | ||
} | ||
} | ||
} | ||
|
||
return buf; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters