diff --git a/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/src/org/jetbrains/java/decompiler/main/ClassWriter.java index 18d3fe7..ea78c72 100644 --- a/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -814,7 +814,7 @@ public class ClassWriter { try { tracer.incrementCurrentSourceLine(buffer.count(lineSeparator, start_index_method)); - String code = root.toJava(indent + 1, tracer); + TextBuffer code = root.toJava(indent + 1, tracer); hideMethod = (clinit || dinit || hideConstructor(wrapper, init, throwsExceptions, paramCount)) && code.length() == 0; diff --git a/src/org/jetbrains/java/decompiler/main/TextBuffer.java b/src/org/jetbrains/java/decompiler/main/TextBuffer.java index a803a1e..45d29c3 100644 --- a/src/org/jetbrains/java/decompiler/main/TextBuffer.java +++ b/src/org/jetbrains/java/decompiler/main/TextBuffer.java @@ -17,10 +17,7 @@ package org.jetbrains.java.decompiler.main; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.*; /** * Allows to connect text with resulting lines @@ -32,7 +29,6 @@ public class TextBuffer { private final String myIndent = (String)DecompilerContext.getProperty(IFernflowerPreferences.INDENT_STRING); private final StringBuilder myStringBuilder; private Map myLineToOffsetMapping = null; - private boolean myTrackLines = true; public TextBuffer() { myStringBuilder = new StringBuilder(); @@ -42,12 +38,12 @@ public class TextBuffer { myStringBuilder = new StringBuilder(size); } - public void setTrackLines(boolean trackLines) { - myTrackLines = false; + public TextBuffer(String text) { + myStringBuilder = new StringBuilder(text); } public void setCurrentLine(int line) { - if (myTrackLines && line >= 0) { + if (line >= 0) { checkMapCreated(); myLineToOffsetMapping.put(line, myStringBuilder.length()+1); } @@ -75,6 +71,26 @@ public class TextBuffer { return this; } + public TextBuffer prepend(String s) { + insert(0, s); + return this; + } + + public TextBuffer enclose(String left, String right) { + prepend(left); + append(right); + return this; + } + + public boolean containsOnlyWhitespaces() { + for (int i = 0; i < myStringBuilder.length(); i++) { + if (myStringBuilder.charAt(i) != ' ') { + return false; + } + } + return true; + } + @Override public String toString() { String original = myStringBuilder.toString(); @@ -117,9 +133,10 @@ public class TextBuffer { private void appendLines(StringBuilder res, String[] srcLines, int from, int to, int requiredLineNumber) { if (to - from > requiredLineNumber) { + List strings = compactLines(Arrays.asList(srcLines).subList(from, to) ,requiredLineNumber); int separatorsRequired = requiredLineNumber - 1; - for (int i = from; i < to; i++) { - res.append(srcLines[i]); + for (String s : strings) { + res.append(s); if (separatorsRequired-- > 0) { res.append(myLineSeparator); } @@ -144,8 +161,23 @@ public class TextBuffer { return myStringBuilder.substring(start); } + public TextBuffer setStart(int position) { + myStringBuilder.delete(0, position); + shiftMapping(0, -position); + return this; + } + public void setLength(int position) { myStringBuilder.setLength(position); + if (myLineToOffsetMapping != null) { + HashMap newMap = new HashMap(); + for (Map.Entry entry : myLineToOffsetMapping.entrySet()) { + if (entry.getValue() <= position) { + newMap.put(entry.getKey(), entry.getValue()); + } + } + myLineToOffsetMapping = newMap; + } } public TextBuffer append(TextBuffer buffer) { @@ -161,11 +193,17 @@ public class TextBuffer { private void shiftMapping(int startOffset, int shiftOffset) { if (myLineToOffsetMapping != null) { + HashMap newMap = new HashMap(); for (Map.Entry entry : myLineToOffsetMapping.entrySet()) { - if (entry.getValue() >= startOffset) { - myLineToOffsetMapping.put(entry.getKey(), entry.getValue() + shiftOffset); + int newValue = entry.getValue(); + if (newValue >= startOffset) { + newValue += shiftOffset; + } + if (newValue >= 0) { + newMap.put(entry.getKey(), newValue); } } + myLineToOffsetMapping = newMap; } } @@ -189,4 +227,34 @@ public class TextBuffer { } return count; } + + private static List compactLines(List srcLines, int requiredLineNumber) { + if (srcLines.size() < 2 || srcLines.size() <= requiredLineNumber) { + return srcLines; + } + List res = new LinkedList(srcLines); + // first join lines with a single { or } + for (int i = res.size()-1; i > 0 ; i--) { + String s = res.get(i); + if (s.trim().equals("{") || s.trim().equals("}")) { + res.set(i-1, res.get(i-1).concat(s)); + res.remove(i); + } + if (res.size() <= requiredLineNumber) { + return res; + } + } + // now join empty lines + for (int i = res.size()-1; i > 0 ; i--) { + String s = res.get(i); + if (s.trim().isEmpty()) { + res.set(i-1, res.get(i-1).concat(s)); + res.remove(i); + } + if (res.size() <= requiredLineNumber) { + return res; + } + } + return res; + } } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java index e283fdf..610b5bd 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java @@ -756,8 +756,8 @@ public class ExprProcessor implements CodeConstants { .isClassdef())); } - public static String jmpWrapper(Statement stat, int indent, boolean semicolon, BytecodeMappingTracer tracer) { - StringBuilder buf = new StringBuilder(stat.toJava(indent, tracer)); + public static TextBuffer jmpWrapper(Statement stat, int indent, boolean semicolon, BytecodeMappingTracer tracer) { + TextBuffer buf = stat.toJava(indent, tracer); String new_line_separator = DecompilerContext.getNewLineSeparator(); @@ -776,7 +776,7 @@ public class ExprProcessor implements CodeConstants { } if (edge.labeled) { - buf.append(" label").append(edge.closure.id); + buf.append(" label").append(edge.closure.id.toString()); } buf.append(";").append(new_line_separator); tracer.incrementCurrentSourceLine(); @@ -788,7 +788,7 @@ public class ExprProcessor implements CodeConstants { tracer.incrementCurrentSourceLine(); } - return buf.toString(); + return buf; } public static String buildJavaClassName(String name) { @@ -805,18 +805,18 @@ public class ExprProcessor implements CodeConstants { return res; } - public static String listToJava(List lst, int indent, BytecodeMappingTracer tracer) { + public static TextBuffer listToJava(List lst, int indent, BytecodeMappingTracer tracer) { if (lst == null || lst.isEmpty()) { - return ""; + return new TextBuffer(); } String indstr = InterpreterUtil.getIndentString(indent); String new_line_separator = DecompilerContext.getNewLineSeparator(); - StringBuilder buf = new StringBuilder(); + TextBuffer buf = new TextBuffer(); for (Exprent expr : lst) { - String content = expr.toJava(indent, tracer); + TextBuffer content = expr.toJava(indent, tracer); if (content.length() > 0) { if (expr.type != Exprent.EXPRENT_VAR || !((VarExprent)expr).isClassdef()) { buf.append(indstr); @@ -833,7 +833,7 @@ public class ExprProcessor implements CodeConstants { } } - return buf.toString(); + return buf; } public static ConstExprent getDefaultArrayValue(VarType arrtype) { @@ -873,7 +873,7 @@ public class ExprProcessor implements CodeConstants { boolean ret = false; VarType rightType = exprent.getExprType(); - String res = exprent.toJava(indent, tracer); + TextBuffer res = exprent.toJava(indent, tracer); boolean cast = !leftType.isSuperset(rightType) && (rightType.equals(VarType.VARTYPE_OBJECT) || leftType.type != CodeConstants.TYPE_OBJECT); @@ -889,10 +889,10 @@ public class ExprProcessor implements CodeConstants { if (cast) { if (exprent.getPrecedence() >= FunctionExprent.getPrecedence(FunctionExprent.FUNCTION_CAST)) { - res = "(" + res + ")"; + res.enclose("(", ")"); } - res = "(" + getCastTypeName(leftType) + ")" + res; + res.prepend("(" + getCastTypeName(leftType) + ")"); ret = true; } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AnnotationExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AnnotationExprent.java index ed3b6a4..c914a6f 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AnnotationExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AnnotationExprent.java @@ -16,6 +16,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.util.InterpreterUtil; @@ -47,11 +48,11 @@ public class AnnotationExprent extends Exprent { } @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { String new_line_separator = DecompilerContext.getNewLineSeparator(); - StringBuilder buffer = new StringBuilder(); + TextBuffer buffer = new TextBuffer(); String indstr = InterpreterUtil.getIndentString(indent); buffer.append(indstr); @@ -82,7 +83,7 @@ public class AnnotationExprent extends Exprent { buffer.append(")"); } - return buffer.toString(); + return buffer; } public int getAnnotationType() { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ArrayExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ArrayExprent.java index 2e81f15..1ab6861 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ArrayExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ArrayExprent.java @@ -15,6 +15,7 @@ */ package org.jetbrains.java.decompiler.modules.decompiler.exps; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; @@ -81,11 +82,11 @@ public class ArrayExprent extends Exprent { @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { - String res = array.toJava(indent, tracer); + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { + TextBuffer res = array.toJava(indent, tracer); if (array.getPrecedence() > getPrecedence()) { // array precedence equals 0 - res = "(" + res + ")"; + res.enclose("(", ")"); } VarType arrtype = array.getExprType(); @@ -93,12 +94,12 @@ public class ArrayExprent extends Exprent { VarType objarr = VarType.VARTYPE_OBJECT.copy(); objarr.arraydim = 1; // type family does not change - res = "((" + ExprProcessor.getCastTypeName(objarr) + ")" + res + ")"; + res.enclose("((" + ExprProcessor.getCastTypeName(objarr) + ")", ")"); } tracer.addMapping(bytecode); - return res + "[" + index.toJava(indent, tracer) + "]"; + return res.append("[").append(index.toJava(indent, tracer)).append("]"); } public boolean equals(Object o) { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssertExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssertExprent.java index f4f24ef..0cbbb3f 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssertExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssertExprent.java @@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps; import java.util.List; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; public class AssertExprent extends Exprent { @@ -32,9 +33,9 @@ public class AssertExprent extends Exprent { } @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { - StringBuilder buffer = new StringBuilder(); + TextBuffer buffer = new TextBuffer(); buffer.append("assert "); @@ -52,6 +53,6 @@ public class AssertExprent extends Exprent { buffer.append(parameters.get(1).toJava(indent, tracer)); } - return buffer.toString(); + return buffer; } } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java index 9553f3f..593cbce 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java @@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; @@ -105,7 +106,7 @@ public class AssignmentExprent extends Exprent { } @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { VarType leftType = left.getExprType(); VarType rightType = right.getExprType(); @@ -127,10 +128,10 @@ public class AssignmentExprent extends Exprent { } if (hiddenField) { - return ""; + return new TextBuffer(); } - StringBuilder buffer = new StringBuilder(); + TextBuffer buffer = new TextBuffer(); if (fieldInClassInit) { buffer.append(((FieldExprent)left).getName()); @@ -139,23 +140,23 @@ public class AssignmentExprent extends Exprent { buffer.append(left.toJava(indent, tracer)); } - String res = right.toJava(indent, tracer); + TextBuffer res = right.toJava(indent, tracer); if (condtype == CONDITION_NONE && !leftType.isSuperset(rightType) && (rightType.equals(VarType.VARTYPE_OBJECT) || leftType.type != CodeConstants.TYPE_OBJECT)) { if (right.getPrecedence() >= FunctionExprent.getPrecedence(FunctionExprent.FUNCTION_CAST)) { - res = "(" + res + ")"; + res.enclose("(", ")"); } - res = "(" + ExprProcessor.getCastTypeName(leftType) + ")" + res; + res.prepend("(" + ExprProcessor.getCastTypeName(leftType) + ")"); } buffer.append(condtype == CONDITION_NONE ? " = " : funceq[condtype]).append(res); tracer.addMapping(bytecode); - return buffer.toString(); + return buffer; } public boolean equals(Object o) { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java index 46e8938..f47d5ef 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java @@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; @@ -108,19 +109,19 @@ public class ConstExprent extends Exprent { } @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { boolean literal = DecompilerContext.getOption(IFernflowerPreferences.LITERALS_AS_IS); boolean ascii = DecompilerContext.getOption(IFernflowerPreferences.ASCII_STRING_CHARACTERS); tracer.addMapping(bytecode); if (consttype.type != CodeConstants.TYPE_NULL && value == null) { - return ExprProcessor.getCastTypeName(consttype); + return new TextBuffer(ExprProcessor.getCastTypeName(consttype)); } else { switch (consttype.type) { case CodeConstants.TYPE_BOOLEAN: - return Boolean.toString(((Integer)value).intValue() != 0); + return new TextBuffer(Boolean.toString(((Integer)value).intValue() != 0)); case CodeConstants.TYPE_CHAR: Integer val = (Integer)value; String ret = escapes.get(val); @@ -133,7 +134,7 @@ public class ConstExprent extends Exprent { ret = InterpreterUtil.charToUnicodeLiteral(c); } } - return "\'" + ret + "\'"; + return new TextBuffer(ret).enclose("\'", "\'"); case CodeConstants.TYPE_BYTE: case CodeConstants.TYPE_BYTECHAR: case CodeConstants.TYPE_SHORT: @@ -143,7 +144,7 @@ public class ConstExprent extends Exprent { String intfield; if (literal) { - return value.toString(); + return new TextBuffer(value.toString()); } else if (ival == Integer.MAX_VALUE) { intfield = "MAX_VALUE"; @@ -152,7 +153,7 @@ public class ConstExprent extends Exprent { intfield = "MIN_VALUE"; } else { - return value.toString(); + return new TextBuffer(value.toString()); } return new FieldExprent(intfield, "java/lang/Integer", true, null, FieldDescriptor.INTEGER_DESCRIPTOR).toJava(0, tracer); case CodeConstants.TYPE_LONG: @@ -160,7 +161,7 @@ public class ConstExprent extends Exprent { String longfield; if (literal) { - return value.toString() + "L"; + return new TextBuffer(value.toString()).append("L"); } else if (lval == Long.MAX_VALUE) { longfield = "MAX_VALUE"; @@ -169,7 +170,7 @@ public class ConstExprent extends Exprent { longfield = "MIN_VALUE"; } else { - return value.toString() + "L"; + return new TextBuffer(value.toString()).append("L"); } return new FieldExprent(longfield, "java/lang/Long", true, null, FieldDescriptor.LONG_DESCRIPTOR).toJava(0, tracer); case CodeConstants.TYPE_DOUBLE: @@ -178,16 +179,16 @@ public class ConstExprent extends Exprent { String doublefield; if (literal) { if (Double.isNaN(dval)) { - return "0.0D / 0.0"; + return new TextBuffer("0.0D / 0.0"); } else if (dval == Double.POSITIVE_INFINITY) { - return "1.0D / 0.0"; + return new TextBuffer("1.0D / 0.0"); } else if (dval == Double.NEGATIVE_INFINITY) { - return "-1.0D / 0.0"; + return new TextBuffer("-1.0D / 0.0"); } else { - return value.toString() + "D"; + return new TextBuffer(value.toString()).append("D"); } } else if (Double.isNaN(dval)) { @@ -206,7 +207,7 @@ public class ConstExprent extends Exprent { doublefield = "MIN_VALUE"; } else { - return value.toString() + "D"; + return new TextBuffer(value.toString()).append("D"); } return new FieldExprent(doublefield, "java/lang/Double", true, null, FieldDescriptor.DOUBLE_DESCRIPTOR).toJava(0, tracer); case CodeConstants.TYPE_FLOAT: @@ -215,16 +216,16 @@ public class ConstExprent extends Exprent { String floatfield; if (literal) { if (Double.isNaN(fval)) { - return "0.0F / 0.0"; + return new TextBuffer("0.0F / 0.0"); } else if (fval == Double.POSITIVE_INFINITY) { - return "1.0F / 0.0"; + return new TextBuffer("1.0F / 0.0"); } else if (fval == Double.NEGATIVE_INFINITY) { - return "-1.0F / 0.0"; + return new TextBuffer("-1.0F / 0.0"); } else { - return value.toString() + "F"; + return new TextBuffer(value.toString()).append("F"); } } else if (Float.isNaN(fval)) { @@ -243,14 +244,14 @@ public class ConstExprent extends Exprent { floatfield = "MIN_VALUE"; } else { - return value.toString() + "F"; + return new TextBuffer(value.toString()).append("F"); } return new FieldExprent(floatfield, "java/lang/Float", true, null, FieldDescriptor.FLOAT_DESCRIPTOR).toJava(0, tracer); case CodeConstants.TYPE_NULL: - return "null"; + return new TextBuffer("null"); case CodeConstants.TYPE_OBJECT: if (consttype.equals(VarType.VARTYPE_STRING)) { - return "\"" + convertStringToJava(value.toString(), ascii) + "\""; + return new TextBuffer(convertStringToJava(value.toString(), ascii)).enclose("\"", "\""); } else if (consttype.equals(VarType.VARTYPE_CLASS)) { String strval = value.toString(); @@ -263,7 +264,7 @@ public class ConstExprent extends Exprent { classtype = new VarType(strval, true); } - return ExprProcessor.getCastTypeName(classtype) + ".class"; + return new TextBuffer(ExprProcessor.getCastTypeName(classtype)).append(".class"); } } } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ExitExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ExitExprent.java index e54b365..96f23d8 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ExitExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/ExitExprent.java @@ -77,7 +77,7 @@ public class ExitExprent extends Exprent { } @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { tracer.addMapping(bytecode); @@ -89,7 +89,7 @@ public class ExitExprent extends Exprent { ExprProcessor.getCastedExprent(value, rettype, buffer, indent, false, tracer); } - return "return" + buffer.toString(); + return buffer.prepend("return"); } else { @@ -119,12 +119,12 @@ public class ExitExprent extends Exprent { TextBuffer buffer = new TextBuffer(); ExprProcessor.getCastedExprent(value, exctype, buffer, indent, false, tracer); - return "throw " + buffer.toString(); + return buffer.prepend("throw "); } } } - return "throw " + value.toJava(indent, tracer); + return value.toJava(indent, tracer).prepend("throw "); } } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/Exprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/Exprent.java index 5c8d6be..2bacb19 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/Exprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/Exprent.java @@ -16,6 +16,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; @@ -128,7 +129,7 @@ public class Exprent { throw new RuntimeException("not implemented"); } - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { throw new RuntimeException("not implemented"); } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java index e51615d..c1cb439 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java @@ -96,8 +96,8 @@ public class FieldExprent extends Exprent { } @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { - StringBuilder buf = new StringBuilder(); + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { + TextBuffer buf = new TextBuffer(); if (isStatic) { @@ -162,7 +162,7 @@ public class FieldExprent extends Exprent { tracer.addMapping(bytecode); - return buf.toString(); + return buf; } public boolean equals(Object o) { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java index a527918..828f5c8 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java @@ -16,6 +16,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.exps; import org.jetbrains.java.decompiler.code.CodeConstants; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; @@ -448,87 +449,87 @@ public class FunctionExprent extends Exprent { } @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { tracer.addMapping(bytecode); if (functype <= FUNCTION_USHR) { - return wrapOperandString(lstOperands.get(0), false, indent, tracer) + operators[functype] + - wrapOperandString(lstOperands.get(1), true, indent, tracer); + return wrapOperandString(lstOperands.get(0), false, indent, tracer) + .append(operators[functype]) + .append(wrapOperandString(lstOperands.get(1), true, indent, tracer)); } if (functype >= FUNCTION_EQ) { - return wrapOperandString(lstOperands.get(0), false, indent, tracer) + operators[functype - FUNCTION_EQ + 11] + - wrapOperandString(lstOperands.get(1), true, indent, tracer); + return wrapOperandString(lstOperands.get(0), false, indent, tracer) + .append(operators[functype - FUNCTION_EQ + 11]) + .append(wrapOperandString(lstOperands.get(1), true, indent, tracer)); } switch (functype) { case FUNCTION_BITNOT: - return "~" + wrapOperandString(lstOperands.get(0), true, indent, tracer); + return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("~"); case FUNCTION_BOOLNOT: - return "!" + wrapOperandString(lstOperands.get(0), true, indent, tracer); + return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("!"); case FUNCTION_NEG: - return "-" + wrapOperandString(lstOperands.get(0), true, indent, tracer); + return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("-"); case FUNCTION_CAST: - return "(" + lstOperands.get(1).toJava(indent, tracer) + ")" + wrapOperandString(lstOperands.get(0), true, indent, tracer); + return lstOperands.get(1).toJava(indent, tracer).enclose("(", ")").append(wrapOperandString(lstOperands.get(0), true, indent, tracer)); case FUNCTION_ARRAYLENGTH: Exprent arr = lstOperands.get(0); - String res = wrapOperandString(arr, false, indent, tracer); + TextBuffer res = wrapOperandString(arr, false, indent, tracer); if (arr.getExprType().arraydim == 0) { VarType objarr = VarType.VARTYPE_OBJECT.copy(); objarr.arraydim = 1; // type family does not change - res = "((" + ExprProcessor.getCastTypeName(objarr) + ")" + res + ")"; + res.enclose("((" + ExprProcessor.getCastTypeName(objarr) + ")", ")"); } - return res + ".length"; + return res.append(".length"); case FUNCTION_IIF: - return wrapOperandString(lstOperands.get(0), true, indent, tracer) + "?" + wrapOperandString(lstOperands.get(1), true, indent, tracer) + ":" + - wrapOperandString(lstOperands.get(2), true, indent, tracer); + return wrapOperandString(lstOperands.get(0), true, indent, tracer) + .append("?") + .append(wrapOperandString(lstOperands.get(1), true, indent, tracer)) + .append(":") + .append(wrapOperandString(lstOperands.get(2), true, indent, tracer)); case FUNCTION_IPP: - return wrapOperandString(lstOperands.get(0), true, indent, tracer) + "++"; + return wrapOperandString(lstOperands.get(0), true, indent, tracer).append("++"); case FUNCTION_PPI: - return "++" + wrapOperandString(lstOperands.get(0), true, indent, tracer); + return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("++"); case FUNCTION_IMM: - return wrapOperandString(lstOperands.get(0), true, indent, tracer) + "--"; + return wrapOperandString(lstOperands.get(0), true, indent, tracer).append("--"); case FUNCTION_MMI: - return "--" + wrapOperandString(lstOperands.get(0), true, indent, tracer); + return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("--"); case FUNCTION_INSTANCEOF: - return wrapOperandString(lstOperands.get(0), true, indent, tracer) + " instanceof " + wrapOperandString(lstOperands.get(1), true, indent, tracer); + return wrapOperandString(lstOperands.get(0), true, indent, tracer).append(" instanceof ").append(wrapOperandString(lstOperands.get(1), true, indent, tracer)); case FUNCTION_LCMP: // shouldn't appear in the final code - return "__lcmp__(" + - wrapOperandString(lstOperands.get(0), true, indent, tracer) + - "," + - wrapOperandString(lstOperands.get(1), true, indent, tracer) + - ")"; + return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("__lcmp__(") + .append(",") + .append(wrapOperandString(lstOperands.get(1), true, indent, tracer)) + .append(")"); case FUNCTION_FCMPL: // shouldn't appear in the final code - return "__fcmpl__(" + - wrapOperandString(lstOperands.get(0), true, indent, tracer) + - "," + - wrapOperandString(lstOperands.get(1), true, indent, tracer) + - ")"; + return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("__fcmpl__(") + .append(",") + .append(wrapOperandString(lstOperands.get(1), true, indent, tracer)) + .append(")"); case FUNCTION_FCMPG: // shouldn't appear in the final code - return "__fcmpg__(" + - wrapOperandString(lstOperands.get(0), true, indent, tracer) + - "," + - wrapOperandString(lstOperands.get(1), true, indent, tracer) + - ")"; + return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("__fcmpg__(") + .append(",") + .append(wrapOperandString(lstOperands.get(1), true, indent, tracer)) + .append(")"); case FUNCTION_DCMPL: // shouldn't appear in the final code - return "__dcmpl__(" + - wrapOperandString(lstOperands.get(0), true, indent, tracer) + - "," + - wrapOperandString(lstOperands.get(1), true, indent, tracer) + - ")"; + return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("__dcmpl__(") + .append(",") + .append(wrapOperandString(lstOperands.get(1), true, indent, tracer)) + .append(")"); case FUNCTION_DCMPG: // shouldn't appear in the final code - return "__dcmpg__(" + - wrapOperandString(lstOperands.get(0), true, indent, tracer) + - "," + - wrapOperandString(lstOperands.get(1), true, indent, tracer) + - ")"; + return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("__dcmpg__(") + .append(",") + .append(wrapOperandString(lstOperands.get(1), true, indent, tracer)) + .append(")"); } if (functype <= FUNCTION_I2S) { - return "(" + ExprProcessor.getTypeName(types[functype - FUNCTION_I2L]) + ")" + wrapOperandString(lstOperands.get(0), true, indent, tracer); + return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("(" + ExprProcessor.getTypeName(types[functype - FUNCTION_I2L]) + ")"); } // return ""; @@ -547,7 +548,7 @@ public class FunctionExprent extends Exprent { return types[functype - FUNCTION_I2L]; } - private String wrapOperandString(Exprent expr, boolean eq, int indent, BytecodeMappingTracer tracer) { + private TextBuffer wrapOperandString(Exprent expr, boolean eq, int indent, BytecodeMappingTracer tracer) { int myprec = getPrecedence(); int exprprec = expr.getPrecedence(); @@ -563,10 +564,10 @@ public class FunctionExprent extends Exprent { } } - String res = expr.toJava(indent, tracer); + TextBuffer res = expr.toJava(indent, tracer); if (parentheses) { - res = "(" + res + ")"; + res.enclose("(", ")"); } return res; diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/IfExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/IfExprent.java index 32cc19d..f0dec34 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/IfExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/IfExprent.java @@ -15,6 +15,7 @@ */ package org.jetbrains.java.decompiler.modules.decompiler.exps; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.util.InterpreterUtil; @@ -113,9 +114,9 @@ public class IfExprent extends Exprent { } @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { tracer.addMapping(bytecode); - return "if(" + condition.toJava(indent, tracer) + ")"; + return condition.toJava(indent, tracer).enclose("if(", ")"); } public boolean equals(Object o) { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java index 92d549e..16c2ab8 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java @@ -189,8 +189,8 @@ public class InvocationExprent extends Exprent { } @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { - StringBuilder buf = new StringBuilder(""); + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { + TextBuffer buf = new TextBuffer(); String super_qualifier = null; boolean isInstanceThis = false; @@ -276,7 +276,7 @@ public class InvocationExprent extends Exprent { buf.append("super"); } else { - String res = instance.toJava(indent, tracer); + TextBuffer res = instance.toJava(indent, tracer); VarType rightType = instance.getExprType(); VarType leftType = new VarType(CodeConstants.TYPE_OBJECT, 0, classname); @@ -285,7 +285,7 @@ public class InvocationExprent extends Exprent { buf.append("((").append(ExprProcessor.getCastTypeName(leftType)).append(")"); if (instance.getPrecedence() >= FunctionExprent.getPrecedence(FunctionExprent.FUNCTION_CAST)) { - res = "(" + res + ")"; + res.enclose("(", ")"); } buf.append(res).append(")"); } @@ -302,7 +302,7 @@ public class InvocationExprent extends Exprent { switch (functype) { case TYP_GENERAL: if (VarExprent.VAR_NAMELESS_ENCLOSURE.equals(buf.toString())) { - buf = new StringBuilder(""); + buf = new TextBuffer(); } if (buf.length() > 0) { @@ -370,7 +370,7 @@ public class InvocationExprent extends Exprent { } buf.append(")"); - return buf.toString(); + return buf; } private Set getAmbiguousParameters() { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/MonitorExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/MonitorExprent.java index 091d424..af7943d 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/MonitorExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/MonitorExprent.java @@ -15,6 +15,7 @@ */ package org.jetbrains.java.decompiler.modules.decompiler.exps; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.util.InterpreterUtil; @@ -51,15 +52,15 @@ public class MonitorExprent extends Exprent { } @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { tracer.addMapping(bytecode); if (montype == MONITOR_ENTER) { - return "synchronized(" + value.toJava(indent, tracer) + ")"; + return value.toJava(indent, tracer).enclose("synchronized(", ")"); } else { - return ""; + return new TextBuffer(); } } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java index 7537d2b..4fa62c6 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java @@ -172,7 +172,7 @@ public class NewExprent extends Exprent { } @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { TextBuffer buf = new TextBuffer(); if (anonymous) { @@ -247,10 +247,10 @@ public class NewExprent extends Exprent { typename = typename.substring(typename.lastIndexOf('.') + 1); } } - buf.insert(0, "new " + typename); + buf.prepend("new " + typename); if (enclosing != null) { - buf.insert(0, enclosing + "."); + buf.prepend(enclosing + "."); } } @@ -268,10 +268,7 @@ public class NewExprent extends Exprent { new ClassWriter().classLambdaToJava(child, buf, methodObject, indent); } else { - // do not track lines in sub classes for now - buf.setTrackLines(false); new ClassWriter().classToJava(child, buf, indent); - buf.setTrackLines(true); } } else if (directArrayInit) { @@ -349,10 +346,10 @@ public class NewExprent extends Exprent { typename = typename.substring(typename.lastIndexOf('.') + 1); } } - buf.insert(0, "new " + typename); + buf.prepend("new " + typename); if (enclosing != null) { - buf.insert(0, enclosing + "."); + buf.prepend(enclosing + "."); } } } @@ -361,7 +358,11 @@ public class NewExprent extends Exprent { if (lstArrayElements.isEmpty()) { for (int i = 0; i < newtype.arraydim; i++) { - buf.append("[").append(i < lstDims.size() ? lstDims.get(i).toJava(indent, tracer) : "").append("]"); + buf.append("["); + if (i < lstDims.size()) { + buf.append(lstDims.get(i).toJava(indent, tracer)); + } + buf.append("]"); } } else { @@ -386,7 +387,7 @@ public class NewExprent extends Exprent { } } } - return buf.toString(); + return buf; } private static String getQualifiedNewInstance(String classname, List lstParams, int indent, BytecodeMappingTracer tracer) { @@ -414,7 +415,7 @@ public class NewExprent extends Exprent { } if (isQualifiedNew) { - return enclosing.toJava(indent, tracer); + return enclosing.toJava(indent, tracer).toString(); } } } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/SwitchExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/SwitchExprent.java index 4784eb1..74b195d 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/SwitchExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/SwitchExprent.java @@ -15,6 +15,7 @@ */ package org.jetbrains.java.decompiler.modules.decompiler.exps; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.struct.gen.VarType; @@ -83,9 +84,9 @@ public class SwitchExprent extends Exprent { } @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { tracer.addMapping(bytecode); - return "switch(" + value.toJava(indent, tracer) + ")"; + return value.toJava(indent, tracer).enclose("switch(", ")"); } public boolean equals(Object o) { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java index 16e6c64..d5b8b27 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java @@ -83,7 +83,7 @@ public class VarExprent extends Exprent { } @Override - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { TextBuffer buffer = new TextBuffer(); tracer.addMapping(bytecode); @@ -107,7 +107,7 @@ public class VarExprent extends Exprent { buffer.append(name == null ? ("var" + index + (version == 0 ? "" : "_" + version)) : name); } - return buffer.toString(); + return buffer; } public boolean equals(Object o) { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/BasicBlockStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/BasicBlockStatement.java index 1ff1b2b..048d245 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/BasicBlockStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/BasicBlockStatement.java @@ -20,6 +20,7 @@ import org.jetbrains.java.decompiler.code.Instruction; import org.jetbrains.java.decompiler.code.SimpleInstructionSequence; import org.jetbrains.java.decompiler.code.cfg.BasicBlock; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; @@ -66,9 +67,8 @@ public class BasicBlockStatement extends Statement { // public methods // ***************************************************************************** - public String toJava(int indent, BytecodeMappingTracer tracer) { - return ExprProcessor.listToJava(varDefinitions, indent, tracer) + - ExprProcessor.listToJava(exprents, indent, tracer); + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { + return ExprProcessor.listToJava(varDefinitions, indent, tracer).append(ExprProcessor.listToJava(exprents, indent, tracer)); } public Statement getSimpleCopy() { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java index f22d1b1..2e4ab82 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java @@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.stats; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.modules.decompiler.DecHelper; @@ -111,28 +112,27 @@ public class CatchAllStatement extends Statement { return null; } - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { String indstr = InterpreterUtil.getIndentString(indent); String indstr1 = null; String new_line_separator = DecompilerContext.getNewLineSeparator(); - StringBuilder buf = new StringBuilder(); + TextBuffer buf = new TextBuffer(); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer)); boolean labeled = isLabeled(); if (labeled) { - buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); + buf.append(indstr).append("label").append(this.id.toString()).append(":").append(new_line_separator); tracer.incrementCurrentSourceLine(); } List lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL); if (first.type == TYPE_TRYCATCH && first.varDefinitions.isEmpty() && isFinally && !labeled && !first.isLabeled() && (lstSuccs.isEmpty() || !lstSuccs.get(0).explicit)) { - String content = ExprProcessor.jmpWrapper(first, indent, true, tracer); - content = content.substring(0, content.length() - new_line_separator.length()); - + TextBuffer content = ExprProcessor.jmpWrapper(first, indent, true, tracer); + content.setStart(content.length() - new_line_separator.length()); buf.append(content); } else { @@ -162,7 +162,7 @@ public class CatchAllStatement extends Statement { buf.append(indstr).append("}").append(new_line_separator); tracer.incrementCurrentSourceLine(); - return buf.toString(); + return buf; } public void replaceStatement(Statement oldstat, Statement newstat) { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java index a096258..1cddbbc 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java @@ -17,6 +17,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.stats; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.modules.decompiler.DecHelper; @@ -150,16 +151,16 @@ public class CatchStatement extends Statement { return null; } - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { String indstr = InterpreterUtil.getIndentString(indent); - StringBuilder buf = new StringBuilder(); + TextBuffer buf = new TextBuffer(); String new_line_separator = DecompilerContext.getNewLineSeparator(); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer)); if (isLabeled()) { - buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); + buf.append(indstr).append("label").append(this.id.toString()).append(":").append(new_line_separator); tracer.incrementCurrentSourceLine(); } @@ -191,7 +192,7 @@ public class CatchStatement extends Statement { buf.append(new_line_separator); tracer.incrementCurrentSourceLine(); - return buf.toString(); + return buf; } public Statement getSimpleCopy() { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java index 1ddce1b..01d4785 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java @@ -16,6 +16,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.stats; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; @@ -92,16 +93,16 @@ public class DoStatement extends Statement { return null; } - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { String indstr = InterpreterUtil.getIndentString(indent); - StringBuilder buf = new StringBuilder(); + TextBuffer buf = new TextBuffer(); String new_line_separator = DecompilerContext.getNewLineSeparator(); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer)); if (isLabeled()) { - buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); + buf.append(indstr).append("label").append(this.id.toString()).append(":").append(new_line_separator); tracer.incrementCurrentSourceLine(); } @@ -128,7 +129,11 @@ public class DoStatement extends Statement { tracer.incrementCurrentSourceLine(); break; case LOOP_FOR: - buf.append(indstr).append("for(").append(initExprent.get(0) == null ? "" : initExprent.get(0).toJava(indent, tracer)).append("; ") + buf.append(indstr).append("for("); + if (initExprent.get(0) != null) { + buf.append(initExprent.get(0).toJava(indent, tracer)); + } + buf.append("; ") .append(conditionExprent.get(0).toJava(indent, tracer)).append("; ").append(incExprent.get(0).toJava(indent, tracer)).append(") {") .append(new_line_separator); tracer.incrementCurrentSourceLine(); @@ -137,7 +142,7 @@ public class DoStatement extends Statement { tracer.incrementCurrentSourceLine(); } - return buf.toString(); + return buf; } public List getSequentialObjects() { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/GeneralStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/GeneralStatement.java index 8541e68..e324f9f 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/GeneralStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/GeneralStatement.java @@ -16,6 +16,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.stats; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.util.InterpreterUtil; @@ -54,14 +55,14 @@ public class GeneralStatement extends Statement { // public methods // ***************************************************************************** - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { String indstr = InterpreterUtil.getIndentString(indent); - StringBuilder buf = new StringBuilder(); + TextBuffer buf = new TextBuffer(); String new_line_separator = DecompilerContext.getNewLineSeparator(); if (isLabeled()) { - buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); + buf.append(indstr).append("label").append(this.id.toString()).append(":").append(new_line_separator); } buf.append(indstr).append("abstract statement {").append(new_line_separator); @@ -70,6 +71,6 @@ public class GeneralStatement extends Statement { } buf.append(indstr).append("}"); - return buf.toString(); + return buf; } } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java index ebe2bd7..4978e91 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java @@ -16,6 +16,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.stats; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.modules.decompiler.DecHelper; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; @@ -200,9 +201,9 @@ public class IfStatement extends Statement { return null; } - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { String indstr = InterpreterUtil.getIndentString(indent); - StringBuilder buf = new StringBuilder(); + TextBuffer buf = new TextBuffer(); String new_line_separator = DecompilerContext.getNewLineSeparator(); @@ -210,7 +211,7 @@ public class IfStatement extends Statement { buf.append(first.toJava(indent, tracer)); if (isLabeled()) { - buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); + buf.append(indstr).append("label").append(this.id.toString()).append(":").append(new_line_separator); tracer.incrementCurrentSourceLine(); } @@ -231,7 +232,7 @@ public class IfStatement extends Statement { } if (ifedge.labeled) { - buf.append(" label").append(ifedge.closure.id); + buf.append(" label").append(ifedge.closure.id.toString()); } } buf.append(";").append(new_line_separator); @@ -249,8 +250,8 @@ public class IfStatement extends Statement { !elsestat.isLabeled() && (elsestat.getSuccessorEdges(STATEDGE_DIRECT_ALL).isEmpty() || !elsestat.getSuccessorEdges(STATEDGE_DIRECT_ALL).get(0).explicit)) { // else if - String content = ExprProcessor.jmpWrapper(elsestat, indent, false, tracer); - content = content.substring(indstr.length()); + TextBuffer content = ExprProcessor.jmpWrapper(elsestat, indent, false, tracer); + content.setStart(indstr.length()); buf.append(indstr).append("} else "); buf.append(content); @@ -259,7 +260,7 @@ public class IfStatement extends Statement { } else { BytecodeMappingTracer else_tracer = new BytecodeMappingTracer(tracer.getCurrentSourceLine()); - String content = ExprProcessor.jmpWrapper(elsestat, indent + 1, false, else_tracer); + TextBuffer content = ExprProcessor.jmpWrapper(elsestat, indent + 1, false, else_tracer); if (content.length() > 0) { buf.append(indstr).append("} else {").append(new_line_separator); @@ -278,7 +279,7 @@ public class IfStatement extends Statement { tracer.incrementCurrentSourceLine(); } - return buf.toString(); + return buf; } public void initExprents() { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java index 07009d6..42323fc 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java @@ -15,6 +15,7 @@ */ package org.jetbrains.java.decompiler.modules.decompiler.stats; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; @@ -34,9 +35,8 @@ public class RootStatement extends Statement { first.setParent(this); } - public String toJava(int indent, BytecodeMappingTracer tracer) { - return ExprProcessor.listToJava(varDefinitions, indent, tracer) + - first.toJava(indent, tracer); + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { + return ExprProcessor.listToJava(varDefinitions, indent, tracer).append(first.toJava(indent, tracer)); } public Statement getDummyExit() { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java index 38420e0..6636bec 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java @@ -16,6 +16,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.stats; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.modules.decompiler.DecHelper; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; @@ -99,9 +100,9 @@ public class SequenceStatement extends Statement { return null; } - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { - StringBuilder buf = new StringBuilder(); + TextBuffer buf = new TextBuffer(); String indstr = null; boolean islabeled = isLabeled(); @@ -113,7 +114,7 @@ public class SequenceStatement extends Statement { if (islabeled) { indstr = InterpreterUtil.getIndentString(indent); indent++; - buf.append(indstr).append("label").append(this.id).append(": {").append(new_line_separator); + buf.append(indstr).append("label").append(this.id.toString()).append(": {").append(new_line_separator); tracer.incrementCurrentSourceLine(); } @@ -128,10 +129,10 @@ public class SequenceStatement extends Statement { tracer.incrementCurrentSourceLine(); } - String str = ExprProcessor.jmpWrapper(st, indent, false, tracer); + TextBuffer str = ExprProcessor.jmpWrapper(st, indent, false, tracer); buf.append(str); - notempty = (str.trim().length() > 0); + notempty = !str.containsOnlyWhitespaces(); } if (islabeled) { @@ -139,7 +140,7 @@ public class SequenceStatement extends Statement { tracer.incrementCurrentSourceLine(); } - return buf.toString(); + return buf; } public Statement getSimpleCopy() { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/Statement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/Statement.java index e9eae20..af7cb46 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/Statement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/Statement.java @@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.stats; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.InstructionSequence; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; @@ -489,11 +490,11 @@ public class Statement { } // to be overwritten - public String toJava() { + public TextBuffer toJava() { return toJava(0, new BytecodeMappingTracer()); } - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { throw new RuntimeException("not implemented"); } diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java index aea44de..dbfe8ce 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java @@ -18,6 +18,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.stats; import org.jetbrains.java.decompiler.code.SwitchInstruction; import org.jetbrains.java.decompiler.code.cfg.BasicBlock; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.modules.decompiler.DecHelper; @@ -107,18 +108,18 @@ public class SwitchStatement extends Statement { return null; } - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { String indstr = InterpreterUtil.getIndentString(indent); String new_line_separator = DecompilerContext.getNewLineSeparator(); - StringBuilder buf = new StringBuilder(); + TextBuffer buf = new TextBuffer(); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer)); buf.append(first.toJava(indent, tracer)); if (isLabeled()) { - buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); + buf.append(indstr).append("label").append(this.id.toString()).append(":").append(new_line_separator); tracer.incrementCurrentSourceLine(); } @@ -153,7 +154,7 @@ public class SwitchStatement extends Statement { buf.append(indstr).append("}").append(new_line_separator); tracer.incrementCurrentSourceLine(); - return buf.toString(); + return buf; } public void initExprents() { diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java index eb94ddc..6a9c6f8 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java @@ -16,6 +16,7 @@ package org.jetbrains.java.decompiler.modules.decompiler.stats; import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.SequenceHelper; @@ -69,17 +70,17 @@ public class SynchronizedStatement extends Statement { // public methods // ***************************************************************************** - public String toJava(int indent, BytecodeMappingTracer tracer) { + public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { String indstr = InterpreterUtil.getIndentString(indent); String new_line_separator = DecompilerContext.getNewLineSeparator(); - StringBuilder buf = new StringBuilder(); + TextBuffer buf = new TextBuffer(); buf.append(ExprProcessor.listToJava(varDefinitions, indent, tracer)); buf.append(first.toJava(indent, tracer)); if (isLabeled()) { - buf.append(indstr).append("label").append(this.id).append(":").append(new_line_separator); + buf.append(indstr).append("label").append(this.id.toString()).append(":").append(new_line_separator); tracer.incrementCurrentSourceLine(); } @@ -92,7 +93,7 @@ public class SynchronizedStatement extends Statement { buf.append(indstr).append("}").append(new_line_separator); tracer.incrementCurrentSourceLine(); - return buf.toString(); + return buf; } public void initExprents() {