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

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -341,7 +341,7 @@ public class ExprProcessor implements CodeConstants {
case opc_fload:
case opc_dload:
case opc_aload:
pushEx(stack, exprlist, new VarExprent(instr.getOperand(0), varTypes[instr.opcode - opc_iload], varProcessor));
pushEx(stack, exprlist, new VarExprent(instr.getOperand(0), varTypes[instr.opcode - opc_iload], varProcessor, bytecode_offset));
break;
case opc_iaload:
case opc_laload:
@@ -371,8 +371,8 @@ public class ExprProcessor implements CodeConstants {
case opc_astore:
Exprent top = stack.pop();
int varindex = instr.getOperand(0);
AssignmentExprent assign =
new AssignmentExprent(new VarExprent(varindex, varTypes[instr.opcode - opc_istore], varProcessor), top, bytecode_offsets);
AssignmentExprent assign = new AssignmentExprent(
new VarExprent(varindex, varTypes[instr.opcode - opc_istore], varProcessor, nextMeaningfulOffset(block, i)), top, bytecode_offsets);
exprlist.add(assign);
break;
case opc_iastore:
@@ -624,6 +624,23 @@ public class ExprProcessor implements CodeConstants {
}
}
private static int nextMeaningfulOffset(BasicBlock block, int index) {
InstructionSequence seq = block.getSeq();
while (++index < seq.length()) {
switch (seq.getInstr(index).opcode) {
case opc_nop:
case opc_istore:
case opc_lstore:
case opc_fstore:
case opc_dstore:
case opc_astore:
continue;
}
return block.getOldOffset(index);
}
return -1;
}
private void pushEx(ExprentStack stack, List<Exprent> exprlist, Exprent exprent) {
pushEx(stack, exprlist, exprent, null);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -88,7 +88,7 @@ public class FieldExprent extends Exprent {
if (method != null) {
StructLocalVariableTableAttribute attr = method.methodStruct.getLocalVariableAttr();
if (attr != null) {
return attr.getMapVarNames().containsValue(name);
return attr.containsName(name);
}
}

View File

@@ -28,6 +28,7 @@ import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarTypeProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute;
import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTableAttribute;
import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTypeTableAttribute;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.struct.gen.generics.GenericFieldDescriptor;
@@ -36,6 +37,7 @@ import org.jetbrains.java.decompiler.struct.match.MatchEngine;
import org.jetbrains.java.decompiler.struct.match.MatchNode;
import org.jetbrains.java.decompiler.struct.match.MatchNode.RuleValue;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.TextUtil;
import java.util.ArrayList;
import java.util.List;
@@ -49,15 +51,21 @@ public class VarExprent extends Exprent {
private VarType varType;
private boolean definition = false;
private VarProcessor processor;
private final int visibleOffset;
private int version = 0;
private boolean classDef = false;
private boolean stack = false;
public VarExprent(int index, VarType varType, VarProcessor processor) {
this(index, varType, processor, -1);
}
public VarExprent(int index, VarType varType, VarProcessor processor, int visibleOffset) {
super(EXPRENT_VAR);
this.index = index;
this.varType = varType;
this.processor = processor;
this.visibleOffset = visibleOffset;
}
@Override
@@ -77,7 +85,7 @@ public class VarExprent extends Exprent {
@Override
public Exprent copy() {
VarExprent var = new VarExprent(index, getVarType(), processor);
VarExprent var = new VarExprent(index, getVarType(), processor, visibleOffset);
var.setDefinition(definition);
var.setVersion(version);
var.setClassDef(classDef);
@@ -97,43 +105,85 @@ public class VarExprent extends Exprent {
tracer.incrementCurrentSourceLine(buffer.countLines());
}
else {
String name = null;
if (processor != null) {
name = processor.getVarName(new VarVersionPair(index, version));
}
VarVersionPair varVersion = new VarVersionPair(index, version);
String name = getName(varVersion);
if (definition) {
if (processor != null && processor.getVarFinal(new VarVersionPair(index, version)) == VarTypeProcessor.VAR_EXPLICIT_FINAL) {
if (processor != null && processor.getVarFinal(varVersion) == VarTypeProcessor.VAR_EXPLICIT_FINAL) {
buffer.append("final ");
}
boolean generic = false;
if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) {
MethodWrapper method = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER);
StructLocalVariableTypeTableAttribute attr = (StructLocalVariableTypeTableAttribute)method.methodStruct.getAttributes()
.getWithKey(StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE);
if (attr != null && processor != null) {
Integer index = processor.getVarOriginalIndex(new VarVersionPair(this.index, version));
if (index != null) {
String signature = attr.getMapVarSignatures().get(index);
appendDefinitionType(buffer, varVersion);
buffer.append(" ");
}
buffer.append(name == null ? ("var" + index + (this.version == 0 ? "" : "_" + this.version)) : name);
}
return buffer;
}
private String getName(VarVersionPair varVersion) {
String name = null;
if (DecompilerContext.getOption(IFernflowerPreferences.USE_DEBUG_VAR_NAMES)) {
MethodWrapper method = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER);
if (method != null) {
StructLocalVariableTableAttribute attr = method.methodStruct.getLocalVariableAttr();
if (attr != null && processor != null) {
Integer index = processor.getVarOriginalIndex(varVersion);
if (index != null) {
name = attr.getName(index, visibleOffset);
if (name != null && TextUtil.isValidIdentifier(name, method.methodStruct.getClassStruct().getBytecodeVersion())) {
return name;
}
}
}
}
}
if (processor != null) {
name = processor.getVarName(varVersion);
}
return name;
}
private void appendDefinitionType(TextBuffer buffer, VarVersionPair varVersion) {
if (DecompilerContext.getOption(IFernflowerPreferences.USE_DEBUG_VAR_NAMES)) {
MethodWrapper method = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER);
if (method != null) {
Integer originalIndex = null;
if (processor != null) {
originalIndex = processor.getVarOriginalIndex(varVersion);
}
if (originalIndex != null) {
// first try from signature
if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) {
StructLocalVariableTypeTableAttribute attr = (StructLocalVariableTypeTableAttribute)method.methodStruct.getAttributes()
.getWithKey(StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE);
if (attr != null) {
String signature = attr.getSignature(originalIndex, visibleOffset);
if (signature != null) {
GenericFieldDescriptor descriptor = GenericMain.parseFieldSignature(signature);
if (descriptor != null) {
buffer.append(GenericMain.getGenericCastTypeName(descriptor.type));
generic = true;
return;
}
}
}
}
// then try from descriptor
StructLocalVariableTableAttribute attr = method.methodStruct.getLocalVariableAttr();
if (attr != null) {
String descriptor = attr.getDescriptor(originalIndex, visibleOffset);
if (descriptor != null) {
buffer.append(ExprProcessor.getCastTypeName(new VarType(descriptor)));
return;
}
}
}
if (!generic) {
buffer.append(ExprProcessor.getCastTypeName(getVarType()));
}
buffer.append(" ");
}
buffer.append(name == null ? ("var" + index + (version == 0 ? "" : "_" + version)) : name);
}
return buffer;
buffer.append(ExprProcessor.getCastTypeName(getVarType()));
}
@Override

View File

@@ -40,8 +40,9 @@ public class VarProcessor {
}
public void setVarVersions(RootStatement root) {
VarVersionsProcessor oldProcessor = varVersions;
varVersions = new VarVersionsProcessor(method, methodDescriptor);
varVersions.setVarVersions(root);
varVersions.setVarVersions(root, oldProcessor);
}
public void setVarDefinitions(Statement root) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 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.
@@ -35,7 +35,7 @@ import java.util.Map.Entry;
public class VarVersionsProcessor {
private final StructMethod method;
private Map<Integer, Integer> mapOriginalVarIndices = new HashMap<>();
private Map<Integer, Integer> mapOriginalVarIndices = Collections.emptyMap();
private VarTypeProcessor typeProcessor;
public VarVersionsProcessor(StructMethod mt, MethodDescriptor md) {
@@ -43,7 +43,7 @@ public class VarVersionsProcessor {
typeProcessor = new VarTypeProcessor(mt, md);
}
public void setVarVersions(RootStatement root) {
public void setVarVersions(RootStatement root, VarVersionsProcessor previousVersionsProcessor) {
SSAConstructorSparseEx ssa = new SSAConstructorSparseEx();
ssa.splitVariables(root, method);
@@ -60,7 +60,7 @@ public class VarVersionsProcessor {
eliminateNonJavaTypes(typeProcessor);
setNewVarIndices(typeProcessor, graph);
setNewVarIndices(typeProcessor, graph, previousVersionsProcessor);
}
private static void mergePhiVersions(SSAConstructorSparseEx ssa, DirectGraph graph) {
@@ -227,7 +227,7 @@ public class VarVersionsProcessor {
}
}
private void setNewVarIndices(VarTypeProcessor typeProcessor, DirectGraph graph) {
private void setNewVarIndices(VarTypeProcessor typeProcessor, DirectGraph graph, VarVersionsProcessor previousVersionsProcessor) {
final Map<VarVersionPair, VarType> mapExprentMaxTypes = typeProcessor.getMapExprentMaxTypes();
Map<VarVersionPair, VarType> mapExprentMinTypes = typeProcessor.getMapExprentMinTypes();
Map<VarVersionPair, Integer> mapFinalVars = typeProcessor.getMapFinalVars();
@@ -286,7 +286,19 @@ public class VarVersionsProcessor {
}
});
this.mapOriginalVarIndices = mapOriginalVarIndices;
if (previousVersionsProcessor != null) {
Map<Integer, Integer> oldIndices = previousVersionsProcessor.getMapOriginalVarIndices();
this.mapOriginalVarIndices = new HashMap<>(mapOriginalVarIndices.size());
for (Entry<Integer, Integer> entry : mapOriginalVarIndices.entrySet()) {
Integer value = entry.getValue();
Integer oldValue = oldIndices.get(value);
value = oldValue != null ? oldValue : value;
this.mapOriginalVarIndices.put(entry.getKey(), value);
}
}
else {
this.mapOriginalVarIndices = mapOriginalVarIndices;
}
}
public VarType getVarType(VarVersionPair pair) {