[java-decompiler] cleanup (arrays to data classes; formatting; typos; dead code)
This commit is contained in:
@@ -46,7 +46,6 @@ import org.jetbrains.java.decompiler.util.InterpreterUtil;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class ClassWriter {
|
public class ClassWriter {
|
||||||
|
|
||||||
private final ClassReference14Processor ref14processor;
|
private final ClassReference14Processor ref14processor;
|
||||||
private final PoolInterceptor interceptor;
|
private final PoolInterceptor interceptor;
|
||||||
|
|
||||||
@@ -154,15 +153,6 @@ public class ClassWriter {
|
|||||||
DecompilerContext.getLogger().endWriteClass();
|
DecompilerContext.getLogger().endWriteClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addTracer(StructClass cls, StructMethod method, BytecodeMappingTracer tracer) {
|
|
||||||
StructLineNumberTableAttribute lineNumberTable =
|
|
||||||
(StructLineNumberTableAttribute)method.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
|
|
||||||
tracer.setLineNumberTable(lineNumberTable);
|
|
||||||
DecompilerContext.getBytecodeSourceMapper().addTracer(cls.qualifiedName,
|
|
||||||
InterpreterUtil.makeUniqueKey(method.getName(), method.getDescriptor()),
|
|
||||||
tracer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void classToJava(ClassNode node, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) {
|
public void classToJava(ClassNode node, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) {
|
||||||
ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
|
ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
|
||||||
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node);
|
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node);
|
||||||
@@ -183,12 +173,7 @@ public class ClassWriter {
|
|||||||
int start_class_def = buffer.length();
|
int start_class_def = buffer.length();
|
||||||
writeClassDefinition(node, buffer, indent);
|
writeClassDefinition(node, buffer, indent);
|
||||||
|
|
||||||
// // count lines in class definition the easiest way
|
|
||||||
// startLine = buffer.substring(start_class_def).toString().split(lineSeparator, -1).length - 1;
|
|
||||||
|
|
||||||
boolean hasContent = false;
|
boolean hasContent = false;
|
||||||
|
|
||||||
// fields
|
|
||||||
boolean enumFields = false;
|
boolean enumFields = false;
|
||||||
|
|
||||||
dummy_tracer.incrementCurrentSourceLine(buffer.countLines(start_class_def));
|
dummy_tracer.incrementCurrentSourceLine(buffer.countLines(start_class_def));
|
||||||
@@ -287,6 +272,13 @@ public class ClassWriter {
|
|||||||
DecompilerContext.getLogger().endWriteClass();
|
DecompilerContext.getLogger().endWriteClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void addTracer(StructClass cls, StructMethod method, BytecodeMappingTracer tracer) {
|
||||||
|
StructLineNumberTableAttribute table = (StructLineNumberTableAttribute)method.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
|
||||||
|
tracer.setLineNumberTable(table);
|
||||||
|
String key = InterpreterUtil.makeUniqueKey(method.getName(), method.getDescriptor());
|
||||||
|
DecompilerContext.getBytecodeSourceMapper().addTracer(cls.qualifiedName, key, tracer);
|
||||||
|
}
|
||||||
|
|
||||||
private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) {
|
private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) {
|
||||||
if (node.type == ClassNode.CLASS_ANONYMOUS) {
|
if (node.type == ClassNode.CLASS_ANONYMOUS) {
|
||||||
buffer.append(" {").appendLineSeparator();
|
buffer.append(" {").appendLineSeparator();
|
||||||
@@ -567,7 +559,7 @@ public class ClassWriter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toValidJavaIdentifier(String name) {
|
private static String toValidJavaIdentifier(String name) {
|
||||||
if (name == null || name.isEmpty()) return name;
|
if (name == null || name.isEmpty()) return name;
|
||||||
|
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
@@ -833,8 +825,6 @@ public class ClassWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We do not have line information for method start, lets have it here for now
|
// We do not have line information for method start, lets have it here for now
|
||||||
StructLineNumberTableAttribute lineNumberTable =
|
|
||||||
(StructLineNumberTableAttribute)mt.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
|
|
||||||
buffer.append('{').appendLineSeparator();
|
buffer.append('{').appendLineSeparator();
|
||||||
tracer.incrementCurrentSourceLine();
|
tracer.incrementCurrentSourceLine();
|
||||||
|
|
||||||
@@ -842,8 +832,6 @@ public class ClassWriter {
|
|||||||
|
|
||||||
if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence
|
if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence
|
||||||
try {
|
try {
|
||||||
int startLine = tracer.getCurrentSourceLine();
|
|
||||||
|
|
||||||
TextBuffer code = root.toJava(indent + 1, tracer);
|
TextBuffer code = root.toJava(indent + 1, tracer);
|
||||||
|
|
||||||
hideMethod = (clinit || dinit || hideConstructor(wrapper, init, throwsExceptions, paramCount)) && code.length() == 0;
|
hideMethod = (clinit || dinit || hideConstructor(wrapper, init, throwsExceptions, paramCount)) && code.length() == 0;
|
||||||
@@ -960,7 +948,6 @@ public class ClassWriter {
|
|||||||
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS};
|
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS};
|
||||||
|
|
||||||
private static void appendAnnotations(TextBuffer buffer, StructMember mb, int indent) {
|
private static void appendAnnotations(TextBuffer buffer, StructMember mb, int indent) {
|
||||||
|
|
||||||
BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
|
BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
|
||||||
|
|
||||||
for (String name : ANNOTATION_ATTRIBUTES) {
|
for (String name : ANNOTATION_ATTRIBUTES) {
|
||||||
|
|||||||
@@ -40,14 +40,22 @@ import java.util.*;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
public class ClassesProcessor {
|
public class ClassesProcessor {
|
||||||
|
|
||||||
public static final int AVERAGE_CLASS_SIZE = 16 * 1024;
|
public static final int AVERAGE_CLASS_SIZE = 16 * 1024;
|
||||||
|
|
||||||
private final Map<String, ClassNode> mapRootClasses = new HashMap<String, ClassNode>();
|
private final Map<String, ClassNode> mapRootClasses = new HashMap<String, ClassNode>();
|
||||||
|
|
||||||
public ClassesProcessor(StructContext context) {
|
private static class Inner {
|
||||||
|
private String simpleName;
|
||||||
|
private int type;
|
||||||
|
private int accessFlags;
|
||||||
|
|
||||||
Map<String, Object[]> mapInnerClasses = new HashMap<String, Object[]>();
|
private static boolean equal(Inner o1, Inner o2) {
|
||||||
|
return o1.type == o2.type && o1.accessFlags == o2.accessFlags && InterpreterUtil.equalObjects(o1.simpleName, o2.simpleName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassesProcessor(StructContext context) {
|
||||||
|
Map<String, Inner> mapInnerClasses = new HashMap<String, Inner>();
|
||||||
Map<String, Set<String>> mapNestedClassReferences = new HashMap<String, Set<String>>();
|
Map<String, Set<String>> mapNestedClassReferences = new HashMap<String, Set<String>>();
|
||||||
Map<String, Set<String>> mapEnclosingClassReferences = new HashMap<String, Set<String>>();
|
Map<String, Set<String>> mapEnclosingClassReferences = new HashMap<String, Set<String>>();
|
||||||
Map<String, String> mapNewSimpleNames = new HashMap<String, String>();
|
Map<String, String> mapNewSimpleNames = new HashMap<String, String>();
|
||||||
@@ -57,25 +65,16 @@ public class ClassesProcessor {
|
|||||||
// create class nodes
|
// create class nodes
|
||||||
for (StructClass cl : context.getClasses().values()) {
|
for (StructClass cl : context.getClasses().values()) {
|
||||||
if (cl.isOwn() && !mapRootClasses.containsKey(cl.qualifiedName)) {
|
if (cl.isOwn() && !mapRootClasses.containsKey(cl.qualifiedName)) {
|
||||||
|
|
||||||
if (bDecompileInner) {
|
if (bDecompileInner) {
|
||||||
StructInnerClassesAttribute inner = (StructInnerClassesAttribute)cl.getAttributes().getWithKey("InnerClasses");
|
StructInnerClassesAttribute inner = (StructInnerClassesAttribute)cl.getAttributes().getWithKey("InnerClasses");
|
||||||
|
|
||||||
if (inner != null) {
|
if (inner != null) {
|
||||||
|
for (StructInnerClassesAttribute.Entry entry : inner.getEntries()) {
|
||||||
for (int i = 0; i < inner.getClassEntries().size(); i++) {
|
String innerName = entry.innerName;
|
||||||
|
|
||||||
int[] entry = inner.getClassEntries().get(i);
|
|
||||||
String[] strEntry = inner.getStringEntries().get(i);
|
|
||||||
Object[] arr = new Object[4]; // arr[0] not used
|
|
||||||
String innerName = strEntry[0];
|
|
||||||
|
|
||||||
// nested class type
|
|
||||||
arr[2] = entry[1] == 0 ? (entry[2] == 0 ? ClassNode.CLASS_ANONYMOUS : ClassNode.CLASS_LOCAL) : ClassNode.CLASS_MEMBER;
|
|
||||||
|
|
||||||
// original simple name
|
// original simple name
|
||||||
String simpleName = strEntry[2];
|
String simpleName = entry.simpleName;
|
||||||
String savedName = mapNewSimpleNames.get(innerName);
|
String savedName = mapNewSimpleNames.get(innerName);
|
||||||
|
|
||||||
if (savedName != null) {
|
if (savedName != null) {
|
||||||
simpleName = savedName;
|
simpleName = savedName;
|
||||||
}
|
}
|
||||||
@@ -87,15 +86,15 @@ public class ClassesProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arr[1] = simpleName;
|
Inner rec = new Inner();
|
||||||
|
rec.simpleName = simpleName;
|
||||||
// original access flags
|
rec.type = entry.outerNameIdx != 0 ? ClassNode.CLASS_MEMBER : entry.simpleNameIdx != 0 ? ClassNode.CLASS_LOCAL : ClassNode.CLASS_ANONYMOUS;
|
||||||
arr[3] = entry[3];
|
rec.accessFlags = entry.accessFlags;
|
||||||
|
|
||||||
// enclosing class
|
// enclosing class
|
||||||
String enclClassName;
|
String enclClassName;
|
||||||
if (entry[1] != 0) {
|
if (entry.outerNameIdx != 0) {
|
||||||
enclClassName = strEntry[1];
|
enclClassName = entry.enclosingName;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
enclClassName = cl.qualifiedName;
|
enclClassName = cl.qualifiedName;
|
||||||
@@ -105,11 +104,11 @@ public class ClassesProcessor {
|
|||||||
StructClass enclosing_class = context.getClasses().get(enclClassName);
|
StructClass enclosing_class = context.getClasses().get(enclClassName);
|
||||||
if (enclosing_class != null && enclosing_class.isOwn()) { // own classes only
|
if (enclosing_class != null && enclosing_class.isOwn()) { // own classes only
|
||||||
|
|
||||||
Object[] arrOld = mapInnerClasses.get(innerName);
|
Inner existingRec = mapInnerClasses.get(innerName);
|
||||||
if (arrOld == null) {
|
if (existingRec == null) {
|
||||||
mapInnerClasses.put(innerName, arr);
|
mapInnerClasses.put(innerName, rec);
|
||||||
}
|
}
|
||||||
else if (!InterpreterUtil.equalObjectArrays(arrOld, arr)) {
|
else if (!Inner.equal(existingRec, rec)) {
|
||||||
String message = "Inconsistent inner class entries for " + innerName + "!";
|
String message = "Inconsistent inner class entries for " + innerName + "!";
|
||||||
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
|
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
|
||||||
}
|
}
|
||||||
@@ -140,12 +139,10 @@ public class ClassesProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bDecompileInner) {
|
if (bDecompileInner) {
|
||||||
|
|
||||||
// connect nested classes
|
// connect nested classes
|
||||||
for (Entry<String, ClassNode> ent : mapRootClasses.entrySet()) {
|
for (Entry<String, ClassNode> ent : mapRootClasses.entrySet()) {
|
||||||
// root class?
|
// root class?
|
||||||
if (!mapInnerClasses.containsKey(ent.getKey())) {
|
if (!mapInnerClasses.containsKey(ent.getKey())) {
|
||||||
|
|
||||||
Set<String> setVisited = new HashSet<String>();
|
Set<String> setVisited = new HashSet<String>();
|
||||||
LinkedList<String> stack = new LinkedList<String>();
|
LinkedList<String> stack = new LinkedList<String>();
|
||||||
|
|
||||||
@@ -153,7 +150,6 @@ public class ClassesProcessor {
|
|||||||
setVisited.add(ent.getKey());
|
setVisited.add(ent.getKey());
|
||||||
|
|
||||||
while (!stack.isEmpty()) {
|
while (!stack.isEmpty()) {
|
||||||
|
|
||||||
String superClass = stack.removeFirst();
|
String superClass = stack.removeFirst();
|
||||||
ClassNode superNode = mapRootClasses.get(superClass);
|
ClassNode superNode = mapRootClasses.get(superClass);
|
||||||
|
|
||||||
@@ -163,13 +159,13 @@ public class ClassesProcessor {
|
|||||||
StructClass scl = superNode.classStruct;
|
StructClass scl = superNode.classStruct;
|
||||||
StructInnerClassesAttribute inner = (StructInnerClassesAttribute)scl.getAttributes().getWithKey("InnerClasses");
|
StructInnerClassesAttribute inner = (StructInnerClassesAttribute)scl.getAttributes().getWithKey("InnerClasses");
|
||||||
|
|
||||||
if (inner == null || inner.getStringEntries().isEmpty()) {
|
if (inner == null || inner.getEntries().isEmpty()) {
|
||||||
DecompilerContext.getLogger().writeMessage(superClass + " does not contain inner classes!", IFernflowerLogger.Severity.WARN);
|
DecompilerContext.getLogger().writeMessage(superClass + " does not contain inner classes!", IFernflowerLogger.Severity.WARN);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < inner.getStringEntries().size(); i++) {
|
for (StructInnerClassesAttribute.Entry entry : inner.getEntries()) {
|
||||||
String nestedClass = inner.getStringEntries().get(i)[0];
|
String nestedClass = entry.innerName;
|
||||||
if (!setNestedClasses.contains(nestedClass)) {
|
if (!setNestedClasses.contains(nestedClass)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -184,21 +180,20 @@ public class ClassesProcessor {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object[] arr = mapInnerClasses.get(nestedClass);
|
Inner rec = mapInnerClasses.get(nestedClass);
|
||||||
|
|
||||||
//if ((Integer)arr[2] == ClassNode.CLASS_MEMBER) {
|
//if ((Integer)arr[2] == ClassNode.CLASS_MEMBER) {
|
||||||
// FIXME: check for consistent naming
|
// FIXME: check for consistent naming
|
||||||
//}
|
//}
|
||||||
|
|
||||||
nestedNode.type = (Integer)arr[2];
|
nestedNode.simpleName = rec.simpleName;
|
||||||
nestedNode.simpleName = (String)arr[1];
|
nestedNode.type = rec.type;
|
||||||
nestedNode.access = (Integer)arr[3];
|
nestedNode.access = rec.accessFlags;
|
||||||
|
|
||||||
if (nestedNode.type == ClassNode.CLASS_ANONYMOUS) {
|
if (nestedNode.type == ClassNode.CLASS_ANONYMOUS) {
|
||||||
StructClass cl = nestedNode.classStruct;
|
StructClass cl = nestedNode.classStruct;
|
||||||
|
|
||||||
// remove static if anonymous class
|
// remove static if anonymous class (a common compiler bug)
|
||||||
// a common compiler bug
|
|
||||||
nestedNode.access &= ~CodeConstants.ACC_STATIC;
|
nestedNode.access &= ~CodeConstants.ACC_STATIC;
|
||||||
|
|
||||||
int[] interfaces = cl.getInterfaces();
|
int[] interfaces = cl.getInterfaces();
|
||||||
@@ -215,8 +210,7 @@ public class ClassesProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (nestedNode.type == ClassNode.CLASS_LOCAL) {
|
else if (nestedNode.type == ClassNode.CLASS_LOCAL) {
|
||||||
// only abstract and final are permitted
|
// only abstract and final are permitted (a common compiler bug)
|
||||||
// a common compiler bug
|
|
||||||
nestedNode.access &= (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_FINAL);
|
nestedNode.access &= (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_FINAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +295,6 @@ public class ClassesProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void initWrappers(ClassNode node) throws IOException {
|
private static void initWrappers(ClassNode node) throws IOException {
|
||||||
|
|
||||||
if (node.type == ClassNode.CLASS_LAMBDA) {
|
if (node.type == ClassNode.CLASS_LAMBDA) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -317,7 +310,6 @@ public class ClassesProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void addClassnameToImport(ClassNode node, ImportCollector imp) {
|
private static void addClassnameToImport(ClassNode node, ImportCollector imp) {
|
||||||
|
|
||||||
if (node.simpleName != null && node.simpleName.length() > 0) {
|
if (node.simpleName != null && node.simpleName.length() > 0) {
|
||||||
imp.getShortName(node.type == ClassNode.CLASS_ROOT ? node.classStruct.qualifiedName : node.simpleName, false);
|
imp.getShortName(node.type == ClassNode.CLASS_ROOT ? node.classStruct.qualifiedName : node.simpleName, false);
|
||||||
}
|
}
|
||||||
@@ -328,7 +320,6 @@ public class ClassesProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void destroyWrappers(ClassNode node) {
|
private static void destroyWrappers(ClassNode node) {
|
||||||
|
|
||||||
node.wrapper = null;
|
node.wrapper = null;
|
||||||
node.classStruct.releaseResources();
|
node.classStruct.releaseResources();
|
||||||
|
|
||||||
@@ -343,7 +334,6 @@ public class ClassesProcessor {
|
|||||||
|
|
||||||
|
|
||||||
public static class ClassNode {
|
public static class ClassNode {
|
||||||
|
|
||||||
public static final int CLASS_ROOT = 0;
|
public static final int CLASS_ROOT = 0;
|
||||||
public static final int CLASS_MEMBER = 1;
|
public static final int CLASS_MEMBER = 1;
|
||||||
public static final int CLASS_ANONYMOUS = 2;
|
public static final int CLASS_ANONYMOUS = 2;
|
||||||
|
|||||||
@@ -21,13 +21,9 @@ import java.util.*;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
public class BytecodeMappingTracer {
|
public class BytecodeMappingTracer {
|
||||||
|
|
||||||
private int currentSourceLine;
|
private int currentSourceLine;
|
||||||
|
|
||||||
private StructLineNumberTableAttribute lineNumberTable = null;
|
private StructLineNumberTableAttribute lineNumberTable = null;
|
||||||
|
private final Map<Integer, Integer> mapping = new HashMap<Integer, Integer>(); // bytecode offset, source line
|
||||||
// bytecode offset, source line
|
|
||||||
private final Map<Integer, Integer> mapping = new HashMap<Integer, Integer>();
|
|
||||||
|
|
||||||
public BytecodeMappingTracer() { }
|
public BytecodeMappingTracer() { }
|
||||||
|
|
||||||
@@ -43,12 +39,6 @@ public class BytecodeMappingTracer {
|
|||||||
currentSourceLine += number_lines;
|
currentSourceLine += number_lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shiftSourceLines(int shift) {
|
|
||||||
for (Entry<Integer, Integer> entry : mapping.entrySet()) {
|
|
||||||
entry.setValue(entry.getValue() + shift);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addMapping(int bytecode_offset) {
|
public void addMapping(int bytecode_offset) {
|
||||||
if (!mapping.containsKey(bytecode_offset)) {
|
if (!mapping.containsKey(bytecode_offset)) {
|
||||||
mapping.put(bytecode_offset, currentSourceLine);
|
mapping.put(bytecode_offset, currentSourceLine);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -36,7 +36,6 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class NewExprent extends Exprent {
|
public class NewExprent extends Exprent {
|
||||||
|
|
||||||
private InvocationExprent constructor;
|
private InvocationExprent constructor;
|
||||||
private final VarType newType;
|
private final VarType newType;
|
||||||
private List<Exprent> lstDims = new ArrayList<Exprent>();
|
private List<Exprent> lstDims = new ArrayList<Exprent>();
|
||||||
@@ -80,12 +79,7 @@ public class NewExprent extends Exprent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VarType getExprType() {
|
public VarType getExprType() {
|
||||||
if (anonymous) {
|
return anonymous ? DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value).anonymousClassType : newType;
|
||||||
return DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value).anonymousClassType;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return newType;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -163,24 +157,22 @@ public class NewExprent extends Exprent {
|
|||||||
TextBuffer buf = new TextBuffer();
|
TextBuffer buf = new TextBuffer();
|
||||||
|
|
||||||
if (anonymous) {
|
if (anonymous) {
|
||||||
|
|
||||||
ClassNode child = DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value);
|
ClassNode child = DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value);
|
||||||
|
|
||||||
buf.append("(");
|
buf.append("(");
|
||||||
|
|
||||||
if (!lambda && constructor != null) {
|
if (!lambda && constructor != null) {
|
||||||
|
InvocationExprent invSuper = child.superInvocation;
|
||||||
|
|
||||||
InvocationExprent invsuper = child.superInvocation;
|
ClassNode newNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(invSuper.getClassname());
|
||||||
|
|
||||||
ClassNode newnode = DecompilerContext.getClassProcessor().getMapRootClasses().get(invsuper.getClassname());
|
|
||||||
|
|
||||||
List<VarVersionPair> sigFields = null;
|
List<VarVersionPair> sigFields = null;
|
||||||
if (newnode != null) { // own class
|
if (newNode != null) { // own class
|
||||||
if (newnode.getWrapper() != null) {
|
if (newNode.getWrapper() != null) {
|
||||||
sigFields = newnode.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, invsuper.getStringDescriptor()).signatureFields;
|
sigFields = newNode.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, invSuper.getStringDescriptor()).signatureFields;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (newnode.type == ClassNode.CLASS_MEMBER && (newnode.access & CodeConstants.ACC_STATIC) == 0 &&
|
if (newNode.type == ClassNode.CLASS_MEMBER && (newNode.access & CodeConstants.ACC_STATIC) == 0 &&
|
||||||
!constructor.getLstParameters().isEmpty()) { // member non-static class invoked with enclosing class instance
|
!constructor.getLstParameters().isEmpty()) { // member non-static class invoked with enclosing class instance
|
||||||
sigFields = new ArrayList<VarVersionPair>(Collections.nCopies(constructor.getLstParameters().size(), (VarVersionPair)null));
|
sigFields = new ArrayList<VarVersionPair>(Collections.nCopies(constructor.getLstParameters().size(), (VarVersionPair)null));
|
||||||
sigFields.set(0, new VarVersionPair(-1, 0));
|
sigFields.set(0, new VarVersionPair(-1, 0));
|
||||||
@@ -188,31 +180,29 @@ public class NewExprent extends Exprent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean firstpar = true;
|
boolean firstParam = true;
|
||||||
int start = 0, end = invsuper.getLstParameters().size();
|
int start = 0, end = invSuper.getLstParameters().size();
|
||||||
if (enumConst) {
|
if (enumConst) {
|
||||||
start += 2;
|
start += 2;
|
||||||
end -= 1;
|
end -= 1;
|
||||||
}
|
}
|
||||||
for (int i = start; i < end; i++) {
|
for (int i = start; i < end; i++) {
|
||||||
if (sigFields == null || sigFields.get(i) == null) {
|
if (sigFields == null || sigFields.get(i) == null) {
|
||||||
if (!firstpar) {
|
if (!firstParam) {
|
||||||
buf.append(", ");
|
buf.append(", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
Exprent param = invsuper.getLstParameters().get(i);
|
Exprent param = invSuper.getLstParameters().get(i);
|
||||||
if (param.type == Exprent.EXPRENT_VAR) {
|
if (param.type == Exprent.EXPRENT_VAR) {
|
||||||
int varindex = ((VarExprent)param).getIndex();
|
int varIndex = ((VarExprent)param).getIndex();
|
||||||
if (varindex > 0 && varindex <= constructor.getLstParameters().size()) {
|
if (varIndex > 0 && varIndex <= constructor.getLstParameters().size()) {
|
||||||
param = constructor.getLstParameters().get(varindex - 1);
|
param = constructor.getLstParameters().get(varIndex - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextBuffer buff = new TextBuffer();
|
ExprProcessor.getCastedExprent(param, invSuper.getDescriptor().params[i], buf, indent, true, tracer);
|
||||||
ExprProcessor.getCastedExprent(param, invsuper.getDescriptor().params[i], buff, indent, true, tracer);
|
|
||||||
|
|
||||||
buf.append(buff);
|
firstParam = false;
|
||||||
firstpar = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,14 +216,15 @@ public class NewExprent extends Exprent {
|
|||||||
String typename = ExprProcessor.getCastTypeName(child.anonymousClassType);
|
String typename = ExprProcessor.getCastTypeName(child.anonymousClassType);
|
||||||
|
|
||||||
if (enclosing != null) {
|
if (enclosing != null) {
|
||||||
ClassNode anonimousNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(child.anonymousClassType.value);
|
ClassNode anonymousNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(child.anonymousClassType.value);
|
||||||
if (anonimousNode != null) {
|
if (anonymousNode != null) {
|
||||||
typename = anonimousNode.simpleName;
|
typename = anonymousNode.simpleName;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
typename = typename.substring(typename.lastIndexOf('.') + 1);
|
typename = typename.substring(typename.lastIndexOf('.') + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.prepend("new " + typename);
|
buf.prepend("new " + typename);
|
||||||
|
|
||||||
if (enclosing != null) {
|
if (enclosing != null) {
|
||||||
@@ -275,118 +266,108 @@ public class NewExprent extends Exprent {
|
|||||||
}
|
}
|
||||||
buf.append("}");
|
buf.append("}");
|
||||||
}
|
}
|
||||||
else {
|
else if (newType.arrayDim == 0) {
|
||||||
if (newType.arrayDim == 0) {
|
if (constructor != null) {
|
||||||
|
List<Exprent> lstParameters = constructor.getLstParameters();
|
||||||
|
|
||||||
if (constructor != null) {
|
ClassNode newNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(constructor.getClassname());
|
||||||
|
|
||||||
List<Exprent> lstParameters = constructor.getLstParameters();
|
List<VarVersionPair> sigFields = null;
|
||||||
|
if (newNode != null) { // own class
|
||||||
ClassNode newnode = DecompilerContext.getClassProcessor().getMapRootClasses().get(constructor.getClassname());
|
if (newNode.getWrapper() != null) {
|
||||||
|
sigFields = newNode.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, constructor.getStringDescriptor()).signatureFields;
|
||||||
List<VarVersionPair> sigFields = null;
|
|
||||||
if (newnode != null) { // own class
|
|
||||||
if (newnode.getWrapper() != null) {
|
|
||||||
sigFields = newnode.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, 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<VarVersionPair>(Collections.nCopies(lstParameters.size(), (VarVersionPair)null));
|
|
||||||
sigFields.set(0, new VarVersionPair(-1, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (newNode.type == ClassNode.CLASS_MEMBER && (newNode.access & CodeConstants.ACC_STATIC) == 0 && !constructor.getLstParameters().isEmpty()) {
|
||||||
int start = enumConst ? 2 : 0;
|
// member non-static class invoked with enclosing class instance
|
||||||
if (!enumConst || start < lstParameters.size()) {
|
sigFields = new ArrayList<VarVersionPair>(Collections.nCopies(lstParameters.size(), (VarVersionPair)null));
|
||||||
buf.append("(");
|
sigFields.set(0, new VarVersionPair(-1, 0));
|
||||||
|
|
||||||
boolean firstParam = true;
|
|
||||||
for (int i = start; i < lstParameters.size(); i++) {
|
|
||||||
if (sigFields == null || sigFields.get(i) == null) {
|
|
||||||
Exprent expr = lstParameters.get(i);
|
|
||||||
VarType leftType = constructor.getDescriptor().params[i];
|
|
||||||
|
|
||||||
if (i == lstParameters.size() - 1 && expr.getExprType() == VarType.VARTYPE_NULL) {
|
|
||||||
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(leftType.value);
|
|
||||||
if (node != null && node.namelessConstructorStub) {
|
|
||||||
break; // skip last parameter of synthetic constructor call
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!firstParam) {
|
|
||||||
buf.append(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
TextBuffer buff = new TextBuffer();
|
|
||||||
ExprProcessor.getCastedExprent(expr, leftType, buff, indent, true, tracer);
|
|
||||||
buf.append(buff);
|
|
||||||
|
|
||||||
firstParam = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.append(")");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!enumConst) {
|
int start = enumConst ? 2 : 0;
|
||||||
String enclosing = null;
|
if (!enumConst || start < lstParameters.size()) {
|
||||||
if (constructor != null) {
|
buf.append("(");
|
||||||
enclosing = getQualifiedNewInstance(newType.value, constructor.getLstParameters(), indent, tracer);
|
|
||||||
}
|
|
||||||
|
|
||||||
String typename = ExprProcessor.getTypeName(newType);
|
boolean firstParam = true;
|
||||||
|
for (int i = start; i < lstParameters.size(); i++) {
|
||||||
|
if (sigFields == null || sigFields.get(i) == null) {
|
||||||
|
Exprent expr = lstParameters.get(i);
|
||||||
|
VarType leftType = constructor.getDescriptor().params[i];
|
||||||
|
|
||||||
if (enclosing != null) {
|
if (i == lstParameters.size() - 1 && expr.getExprType() == VarType.VARTYPE_NULL) {
|
||||||
ClassNode newNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value);
|
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(leftType.value);
|
||||||
if (newNode != null) {
|
if (node != null && node.namelessConstructorStub) {
|
||||||
typename = newNode.simpleName;
|
break; // skip last parameter of synthetic constructor call
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
typename = typename.substring(typename.lastIndexOf('.') + 1);
|
|
||||||
|
if (!firstParam) {
|
||||||
|
buf.append(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
ExprProcessor.getCastedExprent(expr, leftType, buf, indent, true, tracer);
|
||||||
|
|
||||||
|
firstParam = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf.prepend("new " + typename);
|
|
||||||
|
|
||||||
if (enclosing != null) {
|
buf.append(")");
|
||||||
buf.prepend(enclosing + ".");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
buf.append("new ").append(ExprProcessor.getTypeName(newType));
|
|
||||||
|
|
||||||
if (lstArrayElements.isEmpty()) {
|
if (!enumConst) {
|
||||||
for (int i = 0; i < newType.arrayDim; i++) {
|
String enclosing = null;
|
||||||
buf.append("[");
|
if (constructor != null) {
|
||||||
if (i < lstDims.size()) {
|
enclosing = getQualifiedNewInstance(newType.value, constructor.getLstParameters(), indent, tracer);
|
||||||
buf.append(lstDims.get(i).toJava(indent, tracer));
|
}
|
||||||
}
|
|
||||||
buf.append("]");
|
String typename = ExprProcessor.getTypeName(newType);
|
||||||
|
|
||||||
|
if (enclosing != null) {
|
||||||
|
ClassNode newNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value);
|
||||||
|
if (newNode != null) {
|
||||||
|
typename = newNode.simpleName;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
typename = typename.substring(typename.lastIndexOf('.') + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
buf.prepend("new " + typename);
|
||||||
for (int i = 0; i < newType.arrayDim; i++) {
|
|
||||||
buf.append("[]");
|
|
||||||
}
|
|
||||||
|
|
||||||
VarType leftType = newType.decreaseArrayDim();
|
if (enclosing != null) {
|
||||||
buf.append("{");
|
buf.prepend(enclosing + ".");
|
||||||
for (int i = 0; i < lstArrayElements.size(); i++) {
|
|
||||||
if (i > 0) {
|
|
||||||
buf.append(", ");
|
|
||||||
}
|
|
||||||
TextBuffer buff = new TextBuffer();
|
|
||||||
ExprProcessor.getCastedExprent(lstArrayElements.get(i), leftType, buff, indent, false, tracer);
|
|
||||||
|
|
||||||
buf.append(buff);
|
|
||||||
}
|
|
||||||
buf.append("}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
buf.append("new ").append(ExprProcessor.getTypeName(newType));
|
||||||
|
|
||||||
|
if (lstArrayElements.isEmpty()) {
|
||||||
|
for (int i = 0; i < newType.arrayDim; i++) {
|
||||||
|
buf.append("[");
|
||||||
|
if (i < lstDims.size()) {
|
||||||
|
buf.append(lstDims.get(i).toJava(indent, tracer));
|
||||||
|
}
|
||||||
|
buf.append("]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < newType.arrayDim; i++) {
|
||||||
|
buf.append("[]");
|
||||||
|
}
|
||||||
|
|
||||||
|
VarType leftType = newType.decreaseArrayDim();
|
||||||
|
buf.append("{");
|
||||||
|
for (int i = 0; i < lstArrayElements.size(); i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
buf.append(", ");
|
||||||
|
}
|
||||||
|
ExprProcessor.getCastedExprent(lstArrayElements.get(i), leftType, buf, indent, false, tracer);
|
||||||
|
}
|
||||||
|
buf.append("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2000-2014 JetBrains s.r.o.
|
* Copyright 2000-2015 JetBrains s.r.o.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -24,9 +24,27 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class StructInnerClassesAttribute extends StructGeneralAttribute {
|
public class StructInnerClassesAttribute extends StructGeneralAttribute {
|
||||||
|
public static class Entry {
|
||||||
|
public final int innerNameIdx;
|
||||||
|
public final int outerNameIdx;
|
||||||
|
public final int simpleNameIdx;
|
||||||
|
public final int accessFlags;
|
||||||
|
public final String innerName;
|
||||||
|
public final String enclosingName;
|
||||||
|
public final String simpleName;
|
||||||
|
|
||||||
private List<int[]> classEntries;
|
private Entry(int innerNameIdx, int outerNameIdx, int simpleNameIdx, int accessFlags, String innerName, String enclosingName, String simpleName) {
|
||||||
private List<String[]> stringEntries;
|
this.innerNameIdx = innerNameIdx;
|
||||||
|
this.outerNameIdx = outerNameIdx;
|
||||||
|
this.simpleNameIdx = simpleNameIdx;
|
||||||
|
this.accessFlags = accessFlags;
|
||||||
|
this.innerName = innerName;
|
||||||
|
this.enclosingName = enclosingName;
|
||||||
|
this.simpleName = simpleName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Entry> entries;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initContent(ConstantPool pool) throws IOException {
|
public void initContent(ConstantPool pool) throws IOException {
|
||||||
@@ -34,39 +52,27 @@ public class StructInnerClassesAttribute extends StructGeneralAttribute {
|
|||||||
|
|
||||||
int len = data.readUnsignedShort();
|
int len = data.readUnsignedShort();
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
classEntries = new ArrayList<int[]>(len);
|
entries = new ArrayList<Entry>(len);
|
||||||
stringEntries = new ArrayList<String[]>(len);
|
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
int[] classEntry = new int[4];
|
int innerNameIdx = data.readUnsignedShort();
|
||||||
for (int j = 0; j < 4; j++) {
|
int outerNameIdx = data.readUnsignedShort();
|
||||||
classEntry[j] = data.readUnsignedShort();
|
int simpleNameIdx = data.readUnsignedShort();
|
||||||
}
|
int accessFlags = data.readUnsignedShort();
|
||||||
classEntries.add(classEntry);
|
|
||||||
|
|
||||||
// inner name, enclosing class, original simple name
|
String innerName = pool.getPrimitiveConstant(innerNameIdx).getString();
|
||||||
String[] stringEntry = new String[3];
|
String outerName = outerNameIdx != 0 ? pool.getPrimitiveConstant(outerNameIdx).getString() : null;
|
||||||
stringEntry[0] = pool.getPrimitiveConstant(classEntry[0]).getString();
|
String simpleName = simpleNameIdx != 0 ? pool.getPrimitiveConstant(simpleNameIdx).getString() : null;
|
||||||
if (classEntry[1] != 0) {
|
|
||||||
stringEntry[1] = pool.getPrimitiveConstant(classEntry[1]).getString();
|
entries.add(new Entry(innerNameIdx, outerNameIdx, simpleNameIdx, accessFlags, innerName, outerName, simpleName));
|
||||||
}
|
|
||||||
if (classEntry[2] != 0) {
|
|
||||||
stringEntry[2] = pool.getPrimitiveConstant(classEntry[2]).getString();
|
|
||||||
}
|
|
||||||
stringEntries.add(stringEntry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
classEntries = Collections.emptyList();
|
entries = Collections.emptyList();
|
||||||
stringEntries = Collections.emptyList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<int[]> getClassEntries() {
|
public List<Entry> getEntries() {
|
||||||
return classEntries;
|
return entries;
|
||||||
}
|
|
||||||
|
|
||||||
public List<String[]> getStringEntries() {
|
|
||||||
return stringEntries;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,25 +120,6 @@ public class InterpreterUtil {
|
|||||||
return first == null ? second == null : first.equals(second);
|
return first == null ? second == null : first.equals(second);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean equalObjectArrays(Object[] first, Object[] second) {
|
|
||||||
if (first == null || second == null) {
|
|
||||||
return equalObjects(first, second);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (first.length != second.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < first.length; i++) {
|
|
||||||
if (!equalObjects(first[i], second[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean equalLists(List<?> first, List<?> second) {
|
public static boolean equalLists(List<?> first, List<?> second) {
|
||||||
if (first == null) {
|
if (first == null) {
|
||||||
return second == null;
|
return second == null;
|
||||||
@@ -172,6 +153,10 @@ public class InterpreterUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String makeUniqueKey(String name, String descriptor) {
|
public static String makeUniqueKey(String name, String descriptor) {
|
||||||
return name + " " + descriptor;
|
return name + ' ' + descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String makeUniqueKey(String name, String descriptor1, String descriptor2) {
|
||||||
|
return name + ' ' + descriptor1 + ' ' + descriptor2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user