summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStiver <stiver.mail@gmail.com>2014-07-28 20:13:30 +0200
committerStiver <stiver.mail@gmail.com>2014-07-28 20:13:30 +0200
commit55beef6b7e5171c90c725e6fcdf48c9d248ff07e (patch)
treef721d65c1e6e3934fdc3d66557260a718bbb001b /src
parent7f116b6eb506080d552c71445737e444a065e7e1 (diff)
downloadfernflower-55beef6b7e5171c90c725e6fcdf48c9d248ff07e.tar
fernflower-55beef6b7e5171c90c725e6fcdf48c9d248ff07e.tar.gz
fernflower-55beef6b7e5171c90c725e6fcdf48c9d248ff07e.tar.lz
fernflower-55beef6b7e5171c90c725e6fcdf48c9d248ff07e.tar.xz
fernflower-55beef6b7e5171c90c725e6fcdf48c9d248ff07e.zip
Fixed 'IDEA-127301: NPE in decompiler' - a couple of issues with lambda processing
Diffstat (limited to 'src')
-rw-r--r--src/de/fernflower/main/ClassWriter.java13
-rw-r--r--src/de/fernflower/main/ClassesProcessor.java27
-rw-r--r--src/de/fernflower/main/rels/LambdaProcessor.java3
-rw-r--r--src/de/fernflower/main/rels/MethodProcessorThread.java2
-rw-r--r--src/de/fernflower/main/rels/NestedClassProcessor.java4
-rw-r--r--src/de/fernflower/modules/decompiler/ExprProcessor.java54
-rw-r--r--src/de/fernflower/modules/decompiler/FinallyProcessor.java2
-rw-r--r--src/de/fernflower/modules/decompiler/SimplifyExprentsHelper.java5
-rw-r--r--src/de/fernflower/modules/decompiler/exps/InvocationExprent.java11
-rw-r--r--src/de/fernflower/modules/decompiler/exps/NewExprent.java232
10 files changed, 212 insertions, 141 deletions
diff --git a/src/de/fernflower/main/ClassWriter.java b/src/de/fernflower/main/ClassWriter.java
index 8e569d7..7a5a2f0 100644
--- a/src/de/fernflower/main/ClassWriter.java
+++ b/src/de/fernflower/main/ClassWriter.java
@@ -112,7 +112,7 @@ public class ClassWriter {
}
- public void classLambdaToJava(ClassNode node, BufferedWriter writer, int indent) throws IOException {
+ public void classLambdaToJava(ClassNode node, BufferedWriter writer, Exprent method_object, int indent) throws IOException {
// get the class node with the content method
ClassNode node_content = node;
@@ -136,7 +136,12 @@ public class ClassWriter {
if(node.lambda_information.is_method_reference) {
- writer.write(ExprProcessor.getCastTypeName(new VarType(node.lambda_information.content_class_name, false)));
+ if(!node.lambda_information.is_content_method_static && method_object != null) { // reference to a virtual method
+ writer.write(method_object.toJava(indent));
+ } else { // reference to a static method
+ writer.write(ExprProcessor.getCastTypeName(new VarType(node.lambda_information.content_class_name, false)));
+ }
+
writer.write("::");
writer.write(node.lambda_information.content_method_name);
@@ -156,7 +161,7 @@ public class ClassWriter {
StringBuilder buff = new StringBuilder("(");
boolean firstpar = true;
- int index = 1;
+ int index = node.lambda_information.is_content_method_static ? 0 : 1;;
int start_index = md_content.params.length - md_lambda.params.length;
@@ -604,7 +609,7 @@ public class ClassWriter {
bufstrwriter.write("(");
boolean firstpar = true;
- int index = 1;
+ int index = node_lambda.lambda_information.is_content_method_static ? 0 : 1;;
int start_index = md_content.params.length - md_lambda.params.length;
diff --git a/src/de/fernflower/main/ClassesProcessor.java b/src/de/fernflower/main/ClassesProcessor.java
index 7f85696..9d761d2 100644
--- a/src/de/fernflower/main/ClassesProcessor.java
+++ b/src/de/fernflower/main/ClassesProcessor.java
@@ -379,8 +379,8 @@ public class ClassesProcessor {
public LambdaInformation lambda_information;
- public ClassNode(String content_class_name, String content_method_name, String content_method_descriptor, String lambda_class_name, String lambda_method_name,
- String lambda_method_descriptor, StructClass classStruct) { // lambda class constructor
+ public ClassNode(String content_class_name, String content_method_name, String content_method_descriptor, int content_method_invokation_type,
+ String lambda_class_name, String lambda_method_name, String lambda_method_descriptor, StructClass classStruct) { // lambda class constructor
this.type = CLASS_LAMBDA;
this.classStruct = classStruct; // 'parent' class containing the static function
@@ -393,19 +393,22 @@ public class ClassesProcessor {
lambda_information.content_class_name = content_class_name;
lambda_information.content_method_name = content_method_name;
lambda_information.content_method_descriptor = content_method_descriptor;
+ lambda_information.content_method_invokation_type = content_method_invokation_type;
+
lambda_information.content_method_key = InterpreterUtil.makeUniqueKey(lambda_information.content_method_name, lambda_information.content_method_descriptor);
anonimousClassType = new VarType(lambda_class_name, true);
- if(content_class_name != classStruct.qualifiedName) { // method reference. FIXME: class name alone doesn't cover it. Synthetic flag seems to be the only 'reliable' difference.
- lambda_information.is_method_reference = true;
- lambda_information.is_content_method_static = true; // FIXME: consider argument flag
- } else {
- StructMethod mt = classStruct.getMethod(content_method_name, content_method_descriptor);
-
- lambda_information.is_method_reference = false;
- lambda_information.is_content_method_static = ((mt.getAccessFlags() & CodeConstants.ACC_STATIC) != 0);
+ boolean is_method_reference = (content_class_name != classStruct.qualifiedName);
+ StructMethod mt = null;
+
+ if(!is_method_reference) { // content method in the same class, check synthetic flag
+ mt = classStruct.getMethod(content_method_name, content_method_descriptor);
+ is_method_reference = !((mt.getAccessFlags() & CodeConstants.ACC_SYNTHETIC) != 0 || mt.getAttributes().containsKey("Synthetic")); // if not synthetic -> method reference
}
+
+ lambda_information.is_method_reference = is_method_reference;
+ lambda_information.is_content_method_static = (lambda_information.content_method_invokation_type == CodeConstants.CONSTANT_MethodHandle_REF_invokeStatic); // FIXME: redundant?
}
public ClassNode(int type, StructClass classStruct) {
@@ -425,6 +428,9 @@ public class ClassesProcessor {
}
public class LambdaInformation {
+
+
+
public String class_name;
public String method_name;
public String method_descriptor;
@@ -432,6 +438,7 @@ public class ClassesProcessor {
public String content_class_name;
public String content_method_name;
public String content_method_descriptor;
+ public int content_method_invokation_type; // values from CONSTANT_MethodHandle_REF_*
public String content_method_key;
diff --git a/src/de/fernflower/main/rels/LambdaProcessor.java b/src/de/fernflower/main/rels/LambdaProcessor.java
index 6e404ae..8e94646 100644
--- a/src/de/fernflower/main/rels/LambdaProcessor.java
+++ b/src/de/fernflower/main/rels/LambdaProcessor.java
@@ -98,7 +98,8 @@ public class LambdaProcessor {
LinkConstant content_method_handle = (LinkConstant)bootstrap_arguments.get(1);
- ClassNode node_lambda = clprocessor.new ClassNode(content_method_handle.classname, content_method_handle.elementname, content_method_handle.descriptor,
+ ClassNode node_lambda = clprocessor.new ClassNode(content_method_handle.classname, content_method_handle.elementname,
+ content_method_handle.descriptor, content_method_handle.index1,
lambda_class_name, lambda_method_name, lambda_method_descriptor, cl);
node_lambda.simpleName = cl.qualifiedName + "##Lambda_" + invoke_dynamic.index1 + "_" + invoke_dynamic.index2;
node_lambda.enclosingMethod = InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor());
diff --git a/src/de/fernflower/main/rels/MethodProcessorThread.java b/src/de/fernflower/main/rels/MethodProcessorThread.java
index df5c925..976c838 100644
--- a/src/de/fernflower/main/rels/MethodProcessorThread.java
+++ b/src/de/fernflower/main/rels/MethodProcessorThread.java
@@ -175,7 +175,7 @@ public class MethodProcessorThread implements Runnable {
ClearStructHelper.clearStatements(root);
ExprProcessor proc = new ExprProcessor();
- proc.processStatement(root, cl.getPool());
+ proc.processStatement(root, cl);
// DotExporter.toDotFile(graph, new File("c:\\Temp\\fern3.dot"), true);
// System.out.println(graph.toString());
diff --git a/src/de/fernflower/main/rels/NestedClassProcessor.java b/src/de/fernflower/main/rels/NestedClassProcessor.java
index 32b0161..b785a75 100644
--- a/src/de/fernflower/main/rels/NestedClassProcessor.java
+++ b/src/de/fernflower/main/rels/NestedClassProcessor.java
@@ -56,8 +56,8 @@ public class NestedClassProcessor {
public void processClass(ClassNode root, ClassNode node) {
- // hide lambda content methods
- if(node.type == ClassNode.CLASS_LAMBDA) {
+ // hide synthetic lambda content methods
+ if(node.type == ClassNode.CLASS_LAMBDA && !node.lambda_information.is_method_reference) {
ClassNode node_content = DecompilerContext.getClassprocessor().getMapRootClasses().get(node.classStruct.qualifiedName);
if(node_content != null && node_content.wrapper != null) {
node_content.wrapper.getHideMembers().add(node.lambda_information.content_method_key);
diff --git a/src/de/fernflower/modules/decompiler/ExprProcessor.java b/src/de/fernflower/modules/decompiler/ExprProcessor.java
index 60ecc86..7bc1bef 100644
--- a/src/de/fernflower/modules/decompiler/ExprProcessor.java
+++ b/src/de/fernflower/modules/decompiler/ExprProcessor.java
@@ -14,22 +14,48 @@
package de.fernflower.modules.decompiler;
-import java.util.*;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import de.fernflower.code.CodeConstants;
import de.fernflower.code.Instruction;
import de.fernflower.code.InstructionSequence;
import de.fernflower.code.cfg.BasicBlock;
import de.fernflower.main.DecompilerContext;
-import de.fernflower.modules.decompiler.exps.*;
+import de.fernflower.modules.decompiler.exps.ArrayExprent;
+import de.fernflower.modules.decompiler.exps.AssignmentExprent;
+import de.fernflower.modules.decompiler.exps.ConstExprent;
+import de.fernflower.modules.decompiler.exps.ExitExprent;
+import de.fernflower.modules.decompiler.exps.Exprent;
+import de.fernflower.modules.decompiler.exps.FieldExprent;
+import de.fernflower.modules.decompiler.exps.FunctionExprent;
+import de.fernflower.modules.decompiler.exps.IfExprent;
+import de.fernflower.modules.decompiler.exps.InvocationExprent;
+import de.fernflower.modules.decompiler.exps.MonitorExprent;
+import de.fernflower.modules.decompiler.exps.NewExprent;
+import de.fernflower.modules.decompiler.exps.SwitchExprent;
+import de.fernflower.modules.decompiler.exps.VarExprent;
import de.fernflower.modules.decompiler.sforms.DirectGraph;
import de.fernflower.modules.decompiler.sforms.DirectNode;
import de.fernflower.modules.decompiler.sforms.FlattenStatementsHelper;
import de.fernflower.modules.decompiler.sforms.FlattenStatementsHelper.FinallyPathWrapper;
-import de.fernflower.modules.decompiler.stats.*;
+import de.fernflower.modules.decompiler.stats.BasicBlockStatement;
+import de.fernflower.modules.decompiler.stats.CatchAllStatement;
+import de.fernflower.modules.decompiler.stats.CatchStatement;
+import de.fernflower.modules.decompiler.stats.RootStatement;
+import de.fernflower.modules.decompiler.stats.Statement;
import de.fernflower.modules.decompiler.vars.VarProcessor;
import de.fernflower.struct.StructClass;
+import de.fernflower.struct.attr.StructBootstrapMethodsAttribute;
+import de.fernflower.struct.attr.StructGeneralAttribute;
import de.fernflower.struct.consts.ConstantPool;
+import de.fernflower.struct.consts.LinkConstant;
+import de.fernflower.struct.consts.PooledConstant;
import de.fernflower.struct.consts.PrimitiveConstant;
import de.fernflower.struct.gen.MethodDescriptor;
import de.fernflower.struct.gen.VarType;
@@ -124,7 +150,7 @@ public class ExprProcessor implements CodeConstants {
private VarProcessor varProcessor = (VarProcessor) DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR);
- public void processStatement(RootStatement root, ConstantPool pool) {
+ public void processStatement(RootStatement root, StructClass cl) {
FlattenStatementsHelper flatthelper = new FlattenStatementsHelper();
DirectGraph dgraph = flatthelper.buildDirectGraph(root);
@@ -179,7 +205,7 @@ public class ExprProcessor implements CodeConstants {
BasicBlockStatement block = node.block;
if (block != null) {
- processBlock(block, data, pool);
+ processBlock(block, data, cl);
block.setExprents(data.getLstExprents());
}
@@ -291,8 +317,11 @@ public class ExprProcessor implements CodeConstants {
}
}
- public void processBlock(BasicBlockStatement stat, PrimitiveExprsList data, ConstantPool pool) {
+ public void processBlock(BasicBlockStatement stat, PrimitiveExprsList data, StructClass cl) {
+ ConstantPool pool = cl.getPool();
+ StructBootstrapMethodsAttribute bootstrap = (StructBootstrapMethodsAttribute)cl.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS);
+
BasicBlock block = stat.getBlock();
ExprentStack stack = data.getStack();
@@ -516,7 +545,18 @@ public class ExprProcessor implements CodeConstants {
case opc_invokeinterface:
case opc_invokedynamic:
if(instr.opcode != opc_invokedynamic || instr.bytecode_version >= CodeConstants.BYTECODE_JAVA_7) {
- InvocationExprent exprinv = new InvocationExprent(instr.opcode, pool.getLinkConstant(instr.getOperand(0)), stack);
+
+ LinkConstant invoke_constant = pool.getLinkConstant(instr.getOperand(0));
+ int dynamic_invokation_type = -1;
+
+ if(instr.opcode == opc_invokedynamic && bootstrap != null) {
+ List<PooledConstant> bootstrap_arguments = bootstrap.getMethodArguments(invoke_constant.index1);
+ LinkConstant content_method_handle = (LinkConstant)bootstrap_arguments.get(1);
+
+ dynamic_invokation_type = content_method_handle.index1;
+ }
+
+ InvocationExprent exprinv = new InvocationExprent(instr.opcode, invoke_constant, stack, dynamic_invokation_type);
if (exprinv.getDescriptor().ret.type == CodeConstants.TYPE_VOID) {
exprlist.add(exprinv);
} else {
diff --git a/src/de/fernflower/modules/decompiler/FinallyProcessor.java b/src/de/fernflower/modules/decompiler/FinallyProcessor.java
index cf10f48..432e26b 100644
--- a/src/de/fernflower/modules/decompiler/FinallyProcessor.java
+++ b/src/de/fernflower/modules/decompiler/FinallyProcessor.java
@@ -206,7 +206,7 @@ public class FinallyProcessor {
}
ExprProcessor proc = new ExprProcessor();
- proc.processStatement(root, mt.getClassStruct().getPool());
+ proc.processStatement(root, mt.getClassStruct());
SSAConstructorSparseEx ssa = new SSAConstructorSparseEx();
ssa.splitVariables(root, mt);
diff --git a/src/de/fernflower/modules/decompiler/SimplifyExprentsHelper.java b/src/de/fernflower/modules/decompiler/SimplifyExprentsHelper.java
index 49db596..522e4cb 100644
--- a/src/de/fernflower/modules/decompiler/SimplifyExprentsHelper.java
+++ b/src/de/fernflower/modules/decompiler/SimplifyExprentsHelper.java
@@ -720,7 +720,10 @@ public class SimplifyExprentsHelper {
if(lambda_class != null) { // real lambda class found, replace invocation with an anonymous class
NewExprent newexp = new NewExprent(new VarType(lambda_class_name, true), null, 0);
- newexp.setConstructor(in);
+ newexp.setConstructor(in);
+ // note: we don't set the instance to null with in.setInstance(null) like it is done for a common constructor invokation
+ // lambda can also be a reference to a virtual method (e.g. String x; ...(x::toString);)
+ // in this case instance will hold the corresponding object
return newexp;
}
diff --git a/src/de/fernflower/modules/decompiler/exps/InvocationExprent.java b/src/de/fernflower/modules/decompiler/exps/InvocationExprent.java
index 1e4c596..b4aeb0e 100644
--- a/src/de/fernflower/modules/decompiler/exps/InvocationExprent.java
+++ b/src/de/fernflower/modules/decompiler/exps/InvocationExprent.java
@@ -76,7 +76,7 @@ public class InvocationExprent extends Exprent {
public InvocationExprent() {}
- public InvocationExprent(int opcode, LinkConstant cn, ListStack<Exprent> stack) {
+ public InvocationExprent(int opcode, LinkConstant cn, ListStack<Exprent> stack, int dynamic_invokation_type) {
name = cn.elementname;
classname = cn.classname;
@@ -99,6 +99,7 @@ public class InvocationExprent extends Exprent {
classname = "java/lang/Class"; // dummy class name
invoke_dynamic_classsuffix = "##Lambda_" + cn.index1 + "_" + cn.index2;
+
}
if("<init>".equals(name)) {
@@ -114,7 +115,13 @@ public class InvocationExprent extends Exprent {
lstParameters.add(0, stack.pop());
}
- if(opcode == CodeConstants.opc_invokestatic || opcode == CodeConstants.opc_invokedynamic) {
+ if(opcode == CodeConstants.opc_invokedynamic) {
+ if(dynamic_invokation_type == CodeConstants.CONSTANT_MethodHandle_REF_invokeStatic) {
+ isStatic = true;
+ } else {
+ instance = lstParameters.get(0); // FIXME: remove the first parameter completely from the list. It's the object type for a virtual lambda method.
+ }
+ } else if(opcode == CodeConstants.opc_invokestatic) {
isStatic = true;
} else {
instance = stack.pop();
diff --git a/src/de/fernflower/modules/decompiler/exps/NewExprent.java b/src/de/fernflower/modules/decompiler/exps/NewExprent.java
index 22ee631..1023982 100644
--- a/src/de/fernflower/modules/decompiler/exps/NewExprent.java
+++ b/src/de/fernflower/modules/decompiler/exps/NewExprent.java
@@ -133,6 +133,12 @@ public class NewExprent extends Exprent {
List<Exprent> lst = new ArrayList<Exprent>();
if(newtype.arraydim == 0) {
if(constructor != null) {
+ Exprent constructor_instance = constructor.getInstance();
+
+ if(constructor_instance != null) { // should be true only for a lambda expression with a virtual content method
+ lst.add(constructor_instance);
+ }
+
lst.addAll(constructor.getLstParameters());
}
} else {
@@ -164,22 +170,22 @@ public class NewExprent extends Exprent {
public String toJava(int indent) {
StringBuilder buf = new StringBuilder();
-
- if(anonymous) {
-
- ClassNode child = DecompilerContext.getClassprocessor().getMapRootClasses().get(newtype.value);
+
+ if (anonymous) {
+
+ ClassNode child = DecompilerContext.getClassprocessor().getMapRootClasses().get(newtype.value);
buf.append("(");
-
- if(!lambda && constructor != null) {
-
+
+ if (!lambda && constructor != null) {
+
InvocationExprent invsuper = child.superInvocation;
-
- ClassNode newnode = DecompilerContext.getClassprocessor().getMapRootClasses().get(invsuper.getClassname());
+
+ ClassNode newnode = DecompilerContext.getClassprocessor().getMapRootClasses().get(invsuper.getClassname());
List<VarVersionPaar> sigFields = null;
- if(newnode != null) { // own class
- if(newnode.wrapper != null) {
+ if (newnode != null) { // own class
+ if (newnode.wrapper != null) {
sigFields = newnode.wrapper.getMethodWrapper("<init>", invsuper.getStringDescriptor()).signatureFields;
} else {
if(newnode.type == ClassNode.CLASS_MEMBER && (newnode.access & CodeConstants.ACC_STATIC) == 0 &&
@@ -191,27 +197,28 @@ public class NewExprent extends Exprent {
}
boolean firstpar = true;
- int start = 0, end = invsuper.getLstParameters().size();
- if(enumconst) {
- start += 2; end -= 1;
- }
- for(int i=start;i<end;i++) {
- if(sigFields == null || sigFields.get(i) == null) {
- if(!firstpar) {
+ int start = 0, end = invsuper.getLstParameters().size();
+ if (enumconst) {
+ start += 2;
+ end -= 1;
+ }
+ for(int i = start; i < end; i++) {
+ if (sigFields == null || sigFields.get(i) == null) {
+ if (!firstpar) {
buf.append(", ");
}
-
+
Exprent param = invsuper.getLstParameters().get(i);
- if(param.type == Exprent.EXPRENT_VAR) {
- int varindex = ((VarExprent)param).getIndex();
- if(varindex > 0 && varindex <= constructor.getLstParameters().size()) {
- param = constructor.getLstParameters().get(varindex-1);
+ if (param.type == Exprent.EXPRENT_VAR) {
+ int varindex = ((VarExprent) param).getIndex();
+ if (varindex > 0 && varindex <= constructor.getLstParameters().size()) {
+ param = constructor.getLstParameters().get(varindex - 1);
}
}
-
+
StringBuilder buff = new StringBuilder();
ExprProcessor.getCastedExprent(param, invsuper.getDescriptor().params[i], buff, indent, true);
-
+
buf.append(buff);
firstpar = false;
}
@@ -219,161 +226,162 @@ public class NewExprent extends Exprent {
}
- if(!enumconst) {
+ if (!enumconst) {
String enclosing = null;
- if(!lambda && constructor != null) {
+ if (!lambda && constructor != null) {
enclosing = getQualifiedNewInstance(child.anonimousClassType.value, constructor.getLstParameters(), indent);
}
-
+
String typename = ExprProcessor.getCastTypeName(child.anonimousClassType);
-
- if(enclosing != null) {
+
+ if (enclosing != null) {
ClassNode anonimousNode = DecompilerContext.getClassprocessor().getMapRootClasses().get(child.anonimousClassType.value);
- if(anonimousNode != null) {
- typename = anonimousNode.simpleName;
+ if (anonimousNode != null) {
+ typename = anonimousNode.simpleName;
} else {
- typename = typename.substring(typename.lastIndexOf('.')+1);
+ typename = typename.substring(typename.lastIndexOf('.') + 1);
}
}
- buf.insert(0, "new "+typename);
-
- if(enclosing != null) {
- buf.insert(0, enclosing+".");
+ buf.insert(0, "new " + typename);
+
+ if (enclosing != null) {
+ buf.insert(0, enclosing + ".");
}
}
-
+
buf.append(")");
- if(enumconst && buf.length() == 2) {
- buf.setLength(0);
- }
+ if (enumconst && buf.length() == 2) {
+ buf.setLength(0);
+ }
StringWriter strwriter = new StringWriter();
BufferedWriter bufstrwriter = new BufferedWriter(strwriter);
-
+
ClassWriter clwriter = new ClassWriter();
try {
- if(lambda) {
- clwriter.classLambdaToJava(child, bufstrwriter, indent);
+ if (lambda) {
+ clwriter.classLambdaToJava(child, bufstrwriter, (constructor == null ? null : constructor.getInstance()), indent);
} else {
clwriter.classToJava(child, bufstrwriter, indent);
}
bufstrwriter.flush();
- } catch(IOException ex) {
+ } catch (IOException ex) {
throw new RuntimeException(ex);
}
-
- if(lambda && !DecompilerContext.getOption(IFernflowerPreferences.LAMBDA_TO_ANONYMOUS_CLASS)) {
- buf.setLength(0); // remove the usual 'new <class>()', it will be replaced with lambda style '() ->'
+
+ if (lambda && !DecompilerContext.getOption(IFernflowerPreferences.LAMBDA_TO_ANONYMOUS_CLASS)) {
+ buf.setLength(0); // remove the usual 'new <class>()', it will
+ // be replaced with lambda style '() ->'
}
-
+
buf.append(strwriter.toString());
-
- } else if(directArrayInit) {
+
+ } else if (directArrayInit) {
VarType leftType = newtype.copy();
leftType.decArrayDim();
-
+
buf.append("{");
- for(int i=0;i<lstArrayElements.size();i++) {
- if(i>0) {
+ for(int i = 0; i < lstArrayElements.size(); i++) {
+ if (i > 0) {
buf.append(", ");
}
StringBuilder buff = new StringBuilder();
ExprProcessor.getCastedExprent(lstArrayElements.get(i), leftType, buff, indent, false);
-
+
buf.append(buff);
}
buf.append("}");
} else {
- if(newtype.arraydim == 0) {
-
- if(constructor != null) {
+ if (newtype.arraydim == 0) {
+
+ if (constructor != null) {
List<Exprent> lstParameters = constructor.getLstParameters();
-
- ClassNode newnode = DecompilerContext.getClassprocessor().getMapRootClasses().get(constructor.getClassname());
-
+
+ ClassNode newnode = DecompilerContext.getClassprocessor().getMapRootClasses().get(constructor.getClassname());
+
List<VarVersionPaar> sigFields = null;
- if(newnode != null) { // own class
- if(newnode.wrapper != null) {
+ if (newnode != null) { // own class
+ if (newnode.wrapper != null) {
sigFields = newnode.wrapper.getMethodWrapper("<init>", constructor.getStringDescriptor()).signatureFields;
} else {
- if(newnode.type == ClassNode.CLASS_MEMBER && (newnode.access & CodeConstants.ACC_STATIC) == 0 &&
- !constructor.getLstParameters().isEmpty()) { // member non-static class invoked with enclosing class instance
- sigFields = new ArrayList<VarVersionPaar>(Collections.nCopies(lstParameters.size(), (VarVersionPaar)null));
+ if (newnode.type == ClassNode.CLASS_MEMBER && (newnode.access & CodeConstants.ACC_STATIC) == 0 &&
+ !constructor.getLstParameters().isEmpty()) { // member non-static class invoked with enclosing class instance
+ sigFields = new ArrayList<VarVersionPaar>(Collections.nCopies(lstParameters.size(), (VarVersionPaar) null));
sigFields.set(0, new VarVersionPaar(-1, 0));
}
}
}
- int start = enumconst ? 2 : 0;
- if(!enumconst || start < lstParameters.size()) {
- buf.append("(");
-
- boolean firstpar = true;
- for(int i=start;i<lstParameters.size();i++) {
- if(sigFields == null || sigFields.get(i) == null) {
- if(!firstpar) {
- buf.append(", ");
- }
-
- StringBuilder buff = new StringBuilder();
- ExprProcessor.getCastedExprent(lstParameters.get(i), constructor.getDescriptor().params[i], buff, indent, true);
-
- buf.append(buff);
- firstpar = false;
- }
- }
- buf.append(")");
- }
- }
-
- if(!enumconst) {
+ int start = enumconst ? 2 : 0;
+ if (!enumconst || start < lstParameters.size()) {
+ buf.append("(");
+
+ boolean firstpar = true;
+ for(int i = start; i < lstParameters.size(); i++) {
+ if (sigFields == null || sigFields.get(i) == null) {
+ if (!firstpar) {
+ buf.append(", ");
+ }
+
+ StringBuilder buff = new StringBuilder();
+ ExprProcessor.getCastedExprent(lstParameters.get(i), constructor.getDescriptor().params[i], buff, indent, true);
+
+ buf.append(buff);
+ firstpar = false;
+ }
+ }
+ buf.append(")");
+ }
+ }
+
+ if (!enumconst) {
String enclosing = null;
- if(constructor != null) {
+ if (constructor != null) {
enclosing = getQualifiedNewInstance(newtype.value, constructor.getLstParameters(), indent);
}
-
+
String typename = ExprProcessor.getTypeName(newtype);
-
- if(enclosing != null) {
+
+ if (enclosing != null) {
ClassNode newNode = DecompilerContext.getClassprocessor().getMapRootClasses().get(newtype.value);
- if(newNode != null) {
- typename = newNode.simpleName;
+ if (newNode != null) {
+ typename = newNode.simpleName;
} else {
- typename = typename.substring(typename.lastIndexOf('.')+1);
+ typename = typename.substring(typename.lastIndexOf('.') + 1);
}
}
- buf.insert(0, "new "+typename);
-
- if(enclosing != null) {
- buf.insert(0, enclosing+".");
+ buf.insert(0, "new " + typename);
+
+ if (enclosing != null) {
+ buf.insert(0, enclosing + ".");
}
}
-
+
} else {
buf.append("new ").append(ExprProcessor.getTypeName(newtype));
- if(lstArrayElements.isEmpty()) {
- for(int i=0;i<newtype.arraydim;i++) {
+ if (lstArrayElements.isEmpty()) {
+ for(int i = 0; i < newtype.arraydim; i++) {
buf.append("[").append(i < lstDims.size() ? lstDims.get(i).toJava(indent) : "").append("]");
}
} else {
- for(int i=0;i<newtype.arraydim;i++) {
+ for(int i = 0; i < newtype.arraydim; i++) {
buf.append("[]");
}
-
- VarType leftType = newtype.copy();
- leftType.decArrayDim();
-
- buf.append("{");
- for(int i=0;i<lstArrayElements.size();i++) {
- if(i>0) {
+
+ VarType leftType = newtype.copy();
+ leftType.decArrayDim();
+
+ buf.append("{");
+ for(int i = 0; i < lstArrayElements.size(); i++) {
+ if (i > 0) {
buf.append(", ");
}
StringBuilder buff = new StringBuilder();
ExprProcessor.getCastedExprent(lstArrayElements.get(i), leftType, buff, indent, false);
-
+
buf.append(buff);
}
buf.append("}");