[java-decompiler] cleanup (arrays to data classes; formatting; typos; dead code)

master
Roman Shevchenko 9 years ago
parent 26ab681d56
commit 45a41684e6
  1. 29
      src/org/jetbrains/java/decompiler/main/ClassWriter.java
  2. 78
      src/org/jetbrains/java/decompiler/main/ClassesProcessor.java
  3. 12
      src/org/jetbrains/java/decompiler/main/collectors/BytecodeMappingTracer.java
  4. 724
      src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java
  5. 209
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java
  6. 62
      src/org/jetbrains/java/decompiler/struct/attr/StructInnerClassesAttribute.java
  7. 25
      src/org/jetbrains/java/decompiler/util/InterpreterUtil.java

@ -46,7 +46,6 @@ import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.*;
public class ClassWriter {
private final ClassReference14Processor ref14processor;
private final PoolInterceptor interceptor;
@ -154,15 +153,6 @@ public class ClassWriter {
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) {
ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node);
@ -183,12 +173,7 @@ public class ClassWriter {
int start_class_def = buffer.length();
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;
// fields
boolean enumFields = false;
dummy_tracer.incrementCurrentSourceLine(buffer.countLines(start_class_def));
@ -287,6 +272,13 @@ public class ClassWriter {
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) {
if (node.type == ClassNode.CLASS_ANONYMOUS) {
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;
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
StructLineNumberTableAttribute lineNumberTable =
(StructLineNumberTableAttribute)mt.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
buffer.append('{').appendLineSeparator();
tracer.incrementCurrentSourceLine();
@ -842,8 +832,6 @@ public class ClassWriter {
if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence
try {
int startLine = tracer.getCurrentSourceLine();
TextBuffer code = root.toJava(indent + 1, tracer);
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};
private static void appendAnnotations(TextBuffer buffer, StructMember mb, int indent) {
BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
for (String name : ANNOTATION_ATTRIBUTES) {

@ -40,14 +40,22 @@ import java.util.*;
import java.util.Map.Entry;
public class ClassesProcessor {
public static final int AVERAGE_CLASS_SIZE = 16 * 1024;
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;
private static boolean equal(Inner o1, Inner o2) {
return o1.type == o2.type && o1.accessFlags == o2.accessFlags && InterpreterUtil.equalObjects(o1.simpleName, o2.simpleName);
}
}
Map<String, Object[]> mapInnerClasses = new HashMap<String, Object[]>();
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>> mapEnclosingClassReferences = new HashMap<String, Set<String>>();
Map<String, String> mapNewSimpleNames = new HashMap<String, String>();
@ -57,25 +65,16 @@ public class ClassesProcessor {
// create class nodes
for (StructClass cl : context.getClasses().values()) {
if (cl.isOwn() && !mapRootClasses.containsKey(cl.qualifiedName)) {
if (bDecompileInner) {
StructInnerClassesAttribute inner = (StructInnerClassesAttribute)cl.getAttributes().getWithKey("InnerClasses");
if (inner != null) {
for (int i = 0; i < inner.getClassEntries().size(); i++) {
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;
if (inner != null) {
for (StructInnerClassesAttribute.Entry entry : inner.getEntries()) {
String innerName = entry.innerName;
// original simple name
String simpleName = strEntry[2];
String simpleName = entry.simpleName;
String savedName = mapNewSimpleNames.get(innerName);
if (savedName != null) {
simpleName = savedName;
}
@ -87,15 +86,15 @@ public class ClassesProcessor {
}
}
arr[1] = simpleName;
// original access flags
arr[3] = entry[3];
Inner rec = new Inner();
rec.simpleName = simpleName;
rec.type = entry.outerNameIdx != 0 ? ClassNode.CLASS_MEMBER : entry.simpleNameIdx != 0 ? ClassNode.CLASS_LOCAL : ClassNode.CLASS_ANONYMOUS;
rec.accessFlags = entry.accessFlags;
// enclosing class
String enclClassName;
if (entry[1] != 0) {
enclClassName = strEntry[1];
if (entry.outerNameIdx != 0) {
enclClassName = entry.enclosingName;
}
else {
enclClassName = cl.qualifiedName;
@ -105,11 +104,11 @@ public class ClassesProcessor {
StructClass enclosing_class = context.getClasses().get(enclClassName);
if (enclosing_class != null && enclosing_class.isOwn()) { // own classes only
Object[] arrOld = mapInnerClasses.get(innerName);
if (arrOld == null) {
mapInnerClasses.put(innerName, arr);
Inner existingRec = mapInnerClasses.get(innerName);
if (existingRec == null) {
mapInnerClasses.put(innerName, rec);
}
else if (!InterpreterUtil.equalObjectArrays(arrOld, arr)) {
else if (!Inner.equal(existingRec, rec)) {
String message = "Inconsistent inner class entries for " + innerName + "!";
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
}
@ -140,12 +139,10 @@ public class ClassesProcessor {
}
if (bDecompileInner) {
// connect nested classes
for (Entry<String, ClassNode> ent : mapRootClasses.entrySet()) {
// root class?
if (!mapInnerClasses.containsKey(ent.getKey())) {
Set<String> setVisited = new HashSet<String>();
LinkedList<String> stack = new LinkedList<String>();
@ -153,7 +150,6 @@ public class ClassesProcessor {
setVisited.add(ent.getKey());
while (!stack.isEmpty()) {
String superClass = stack.removeFirst();
ClassNode superNode = mapRootClasses.get(superClass);
@ -163,13 +159,13 @@ public class ClassesProcessor {
StructClass scl = superNode.classStruct;
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);
continue;
}
for (int i = 0; i < inner.getStringEntries().size(); i++) {
String nestedClass = inner.getStringEntries().get(i)[0];
for (StructInnerClassesAttribute.Entry entry : inner.getEntries()) {
String nestedClass = entry.innerName;
if (!setNestedClasses.contains(nestedClass)) {
continue;
}
@ -184,21 +180,20 @@ public class ClassesProcessor {
continue;
}
Object[] arr = mapInnerClasses.get(nestedClass);
Inner rec = mapInnerClasses.get(nestedClass);
//if ((Integer)arr[2] == ClassNode.CLASS_MEMBER) {
// FIXME: check for consistent naming
//}
nestedNode.type = (Integer)arr[2];
nestedNode.simpleName = (String)arr[1];
nestedNode.access = (Integer)arr[3];
nestedNode.simpleName = rec.simpleName;
nestedNode.type = rec.type;
nestedNode.access = rec.accessFlags;
if (nestedNode.type == ClassNode.CLASS_ANONYMOUS) {
StructClass cl = nestedNode.classStruct;
// remove static if anonymous class
// a common compiler bug
// remove static if anonymous class (a common compiler bug)
nestedNode.access &= ~CodeConstants.ACC_STATIC;
int[] interfaces = cl.getInterfaces();
@ -215,8 +210,7 @@ public class ClassesProcessor {
}
}
else if (nestedNode.type == ClassNode.CLASS_LOCAL) {
// only abstract and final are permitted
// a common compiler bug
// only abstract and final are permitted (a common compiler bug)
nestedNode.access &= (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_FINAL);
}
@ -301,7 +295,6 @@ public class ClassesProcessor {
}
private static void initWrappers(ClassNode node) throws IOException {
if (node.type == ClassNode.CLASS_LAMBDA) {
return;
}
@ -317,7 +310,6 @@ public class ClassesProcessor {
}
private static void addClassnameToImport(ClassNode node, ImportCollector imp) {
if (node.simpleName != null && node.simpleName.length() > 0) {
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) {
node.wrapper = null;
node.classStruct.releaseResources();
@ -343,7 +334,6 @@ public class ClassesProcessor {
public static class ClassNode {
public static final int CLASS_ROOT = 0;
public static final int CLASS_MEMBER = 1;
public static final int CLASS_ANONYMOUS = 2;

@ -21,13 +21,9 @@ import java.util.*;
import java.util.Map.Entry;
public class BytecodeMappingTracer {
private int currentSourceLine;
private StructLineNumberTableAttribute lineNumberTable = null;
// bytecode offset, source line
private final Map<Integer, Integer> mapping = new HashMap<Integer, Integer>();
private final Map<Integer, Integer> mapping = new HashMap<Integer, Integer>(); // bytecode offset, source line
public BytecodeMappingTracer() { }
@ -43,12 +39,6 @@ public class BytecodeMappingTracer {
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) {
if (!mapping.containsKey(bytecode_offset)) {
mapping.put(bytecode_offset, currentSourceLine);

@ -36,7 +36,6 @@ import java.util.List;
import java.util.Set;
public class NewExprent extends Exprent {
private InvocationExprent constructor;
private final VarType newType;
private List<Exprent> lstDims = new ArrayList<Exprent>();
@ -80,12 +79,7 @@ public class NewExprent extends Exprent {
@Override
public VarType getExprType() {
if (anonymous) {
return DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value).anonymousClassType;
}
else {
return newType;
}
return anonymous ? DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value).anonymousClassType : newType;
}
@Override
@ -163,24 +157,22 @@ public class NewExprent extends Exprent {
TextBuffer buf = new TextBuffer();
if (anonymous) {
ClassNode child = DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value);
buf.append("(");
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;
if (newnode != null) { // own class
if (newnode.getWrapper() != null) {
sigFields = newnode.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, invsuper.getStringDescriptor()).signatureFields;
if (newNode != null) { // own class
if (newNode.getWrapper() != null) {
sigFields = newNode.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, invSuper.getStringDescriptor()).signatureFields;
}
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
sigFields = new ArrayList<VarVersionPair>(Collections.nCopies(constructor.getLstParameters().size(), (VarVersionPair)null));
sigFields.set(0, new VarVersionPair(-1, 0));
@ -188,31 +180,29 @@ public class NewExprent extends Exprent {
}
}
boolean firstpar = true;
int start = 0, end = invsuper.getLstParameters().size();
boolean firstParam = 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) {
if (!firstParam) {
buf.append(", ");
}
Exprent param = invsuper.getLstParameters().get(i);
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);
int varIndex = ((VarExprent)param).getIndex();
if (varIndex > 0 && varIndex <= constructor.getLstParameters().size()) {
param = constructor.getLstParameters().get(varIndex - 1);
}
}
TextBuffer buff = new TextBuffer();
ExprProcessor.getCastedExprent(param, invsuper.getDescriptor().params[i], buff, indent, true, tracer);
ExprProcessor.getCastedExprent(param, invSuper.getDescriptor().params[i], buf, indent, true, tracer);
buf.append(buff);
firstpar = false;
firstParam = false;
}
}
}
@ -226,14 +216,15 @@ public class NewExprent extends Exprent {
String typename = ExprProcessor.getCastTypeName(child.anonymousClassType);
if (enclosing != null) {
ClassNode anonimousNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(child.anonymousClassType.value);
if (anonimousNode != null) {
typename = anonimousNode.simpleName;
ClassNode anonymousNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(child.anonymousClassType.value);
if (anonymousNode != null) {
typename = anonymousNode.simpleName;
}
else {
typename = typename.substring(typename.lastIndexOf('.') + 1);
}
}
buf.prepend("new " + typename);
if (enclosing != null) {
@ -275,118 +266,108 @@ public class NewExprent extends Exprent {
}
buf.append("}");
}
else {
if (newType.arrayDim == 0) {
else 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
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));
}
}
ClassNode newnode = DecompilerContext.getClassProcessor().getMapRootClasses().get(constructor.getClassname());
int start = enumConst ? 2 : 0;
if (!enumConst || start < lstParameters.size()) {
buf.append("(");
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));
}
}
}
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];
int start = enumConst ? 2 : 0;
if (!enumConst || start < lstParameters.size()) {
buf.append("(");
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 (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(", ");
}
if (!firstParam) {
buf.append(", ");
}
TextBuffer buff = new TextBuffer();
ExprProcessor.getCastedExprent(expr, leftType, buff, indent, true, tracer);
buf.append(buff);
ExprProcessor.getCastedExprent(expr, leftType, buf, indent, true, tracer);
firstParam = false;
}
firstParam = false;
}
buf.append(")");
}
buf.append(")");
}
}
if (!enumConst) {
String enclosing = null;
if (constructor != null) {
enclosing = getQualifiedNewInstance(newType.value, constructor.getLstParameters(), indent, tracer);
}
if (!enumConst) {
String enclosing = null;
if (constructor != null) {
enclosing = getQualifiedNewInstance(newType.value, constructor.getLstParameters(), indent, tracer);
}
String typename = ExprProcessor.getTypeName(newType);
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);
}
if (enclosing != null) {
ClassNode newNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value);
if (newNode != null) {
typename = newNode.simpleName;
}
buf.prepend("new " + typename);
if (enclosing != null) {
buf.prepend(enclosing + ".");
else {
typename = typename.substring(typename.lastIndexOf('.') + 1);
}
}
buf.prepend("new " + typename);
if (enclosing != null) {
buf.prepend(enclosing + ".");
}
}
else {
buf.append("new ").append(ExprProcessor.getTypeName(newType));
}
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("]");
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("[]");
}
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(", ");
}
TextBuffer buff = new TextBuffer();
ExprProcessor.getCastedExprent(lstArrayElements.get(i), leftType, buff, indent, false, tracer);
buf.append(buff);
VarType leftType = newType.decreaseArrayDim();
buf.append("{");
for (int i = 0; i < lstArrayElements.size(); i++) {
if (i > 0) {
buf.append(", ");
}
buf.append("}");
ExprProcessor.getCastedExprent(lstArrayElements.get(i), leftType, buf, indent, false, tracer);
}
buf.append("}");
}
}
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");
* you may not use this file except in compliance with the License.
@ -24,9 +24,27 @@ import java.util.Collections;
import java.util.List;
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 List<String[]> stringEntries;
private Entry(int innerNameIdx, int outerNameIdx, int simpleNameIdx, int accessFlags, String innerName, String enclosingName, String simpleName) {
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
public void initContent(ConstantPool pool) throws IOException {
@ -34,39 +52,27 @@ public class StructInnerClassesAttribute extends StructGeneralAttribute {
int len = data.readUnsignedShort();
if (len > 0) {
classEntries = new ArrayList<int[]>(len);
stringEntries = new ArrayList<String[]>(len);
entries = new ArrayList<Entry>(len);
for (int i = 0; i < len; i++) {
int[] classEntry = new int[4];
for (int j = 0; j < 4; j++) {
classEntry[j] = data.readUnsignedShort();
}
classEntries.add(classEntry);
int innerNameIdx = data.readUnsignedShort();
int outerNameIdx = data.readUnsignedShort();
int simpleNameIdx = data.readUnsignedShort();
int accessFlags = data.readUnsignedShort();
// inner name, enclosing class, original simple name
String[] stringEntry = new String[3];
stringEntry[0] = pool.getPrimitiveConstant(classEntry[0]).getString();
if (classEntry[1] != 0) {
stringEntry[1] = pool.getPrimitiveConstant(classEntry[1]).getString();
}
if (classEntry[2] != 0) {
stringEntry[2] = pool.getPrimitiveConstant(classEntry[2]).getString();
}
stringEntries.add(stringEntry);
String innerName = pool.getPrimitiveConstant(innerNameIdx).getString();
String outerName = outerNameIdx != 0 ? pool.getPrimitiveConstant(outerNameIdx).getString() : null;
String simpleName = simpleNameIdx != 0 ? pool.getPrimitiveConstant(simpleNameIdx).getString() : null;
entries.add(new Entry(innerNameIdx, outerNameIdx, simpleNameIdx, accessFlags, innerName, outerName, simpleName));
}
}
else {
classEntries = Collections.emptyList();
stringEntries = Collections.emptyList();
entries = Collections.emptyList();
}
}
public List<int[]> getClassEntries() {
return classEntries;
}
public List<String[]> getStringEntries() {
return stringEntries;
public List<Entry> getEntries() {
return entries;
}
}

@ -120,25 +120,6 @@ public class InterpreterUtil {
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) {
if (first == null) {
return second == null;
@ -172,6 +153,10 @@ public class InterpreterUtil {
}
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;
}
}

Loading…
Cancel
Save