IDEA-130708 Incorrect locals names

This commit is contained in:
Egor.Ushakov
2017-01-12 15:03:43 +03:00
parent 6a09fe2524
commit 5e45e5ac40
15 changed files with 296 additions and 75 deletions

View File

@@ -61,7 +61,7 @@ public class StructMember {
if (StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE.equals(name) && attributes.containsKey(name)) {
// merge all variable tables
StructLocalVariableTableAttribute table = (StructLocalVariableTableAttribute)attributes.getWithKey(name);
table.addLocalVariableTable((StructLocalVariableTableAttribute)attribute);
table.add((StructLocalVariableTableAttribute)attribute);
}
else if (StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE.equals(name) && attributes.containsKey(name)) {
// merge all variable tables

View File

@@ -19,9 +19,12 @@ import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
import org.jetbrains.java.decompiler.util.DataInputFullStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/*
u2 local_variable_table_length;
@@ -34,32 +37,70 @@ import java.util.Map;
}
*/
public class StructLocalVariableTableAttribute extends StructGeneralAttribute {
private Map<Integer, String> mapVarNames = Collections.emptyMap();
private List<LocalVariable> localVariables = Collections.emptyList();
@Override
public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
int len = data.readUnsignedShort();
if (len > 0) {
mapVarNames = new HashMap<>(len);
localVariables = new ArrayList<>(len);
for (int i = 0; i < len; i++) {
data.discard(4);
int start_pc = data.readUnsignedShort();
int length = data.readUnsignedShort();
int nameIndex = data.readUnsignedShort();
data.discard(2);
int descriptorIndex = data.readUnsignedShort();
int varIndex = data.readUnsignedShort();
mapVarNames.put(varIndex, pool.getPrimitiveConstant(nameIndex).getString());
localVariables.add(new LocalVariable(start_pc,
length,
pool.getPrimitiveConstant(nameIndex).getString(),
pool.getPrimitiveConstant(descriptorIndex).getString(),
varIndex));
}
}
else {
mapVarNames = Collections.emptyMap();
localVariables = Collections.emptyList();
}
}
public void addLocalVariableTable(StructLocalVariableTableAttribute attr) {
mapVarNames.putAll(attr.getMapVarNames());
public void add(StructLocalVariableTableAttribute attr) {
localVariables.addAll(attr.localVariables);
}
public Map<Integer, String> getMapVarNames() {
return mapVarNames;
public String getName(int index, int visibleOffset) {
return matchingVars(index, visibleOffset).map(v -> v.name).findFirst().orElse(null);
}
public String getDescriptor(int index, int visibleOffset) {
return matchingVars(index, visibleOffset).map(v -> v.descriptor).findFirst().orElse(null);
}
private Stream<LocalVariable> matchingVars(int index, int visibleOffset) {
return localVariables.stream()
.filter(v -> v.index == index && (visibleOffset >= v.start_pc && visibleOffset < v.start_pc + v.length));
}
public boolean containsName(String name) {
return localVariables.stream().anyMatch(v -> v.name == name);
}
public Map<Integer, String> getMapParamNames() {
return localVariables.stream().filter(v -> v.start_pc == 0).collect(Collectors.toMap(v -> v.index, v -> v.name, (n1, n2) -> n2));
}
private static class LocalVariable {
final int start_pc;
final int length;
final String name;
final String descriptor;
final int index;
private LocalVariable(int start_pc, int length, String name, String descriptor, int index) {
this.start_pc = start_pc;
this.length = length;
this.name = name;
this.descriptor = descriptor;
this.index = index;
}
}
}

View File

@@ -19,9 +19,7 @@ import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
import org.jetbrains.java.decompiler.util.DataInputFullStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/*
u2 local_variable_type_table_length;
@@ -33,31 +31,19 @@ import java.util.Map;
} local_variable_type_table[local_variable_type_table_length];
*/
public class StructLocalVariableTypeTableAttribute extends StructGeneralAttribute {
private Map<Integer, String> mapVarSignatures = Collections.emptyMap();
// store signature instead of descriptor
private final StructLocalVariableTableAttribute backingAttribute = new StructLocalVariableTableAttribute();
@Override
public void initContent(DataInputFullStream data, ConstantPool pool) throws IOException {
int len = data.readUnsignedShort();
if (len > 0) {
mapVarSignatures = new HashMap<>(len);
for (int i = 0; i < len; i++) {
data.discard(6);
int signatureIndex = data.readUnsignedShort();
int varIndex = data.readUnsignedShort();
mapVarSignatures.put(varIndex, pool.getPrimitiveConstant(signatureIndex).getString());
}
}
else {
mapVarSignatures = Collections.emptyMap();
}
backingAttribute.initContent(data, pool);
}
public void add(StructLocalVariableTypeTableAttribute attr) {
mapVarSignatures.putAll(attr.getMapVarSignatures());
backingAttribute.add(attr.backingAttribute);
}
public Map<Integer, String> getMapVarSignatures() {
return mapVarSignatures;
public String getSignature(int index, int visibleOffset) {
return backingAttribute.getDescriptor(index, visibleOffset);
}
}