package jadx.core.dex.nodes.parser;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.DexNode;
import jadx.core.utils.InsnUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
final class LocalVar {
private static final Logger LOG = LoggerFactory.getLogger(LocalVar.class);
private final int regNum;
private String name;
private ArgType type;
private boolean isEnd;
private int startAddr;
private int endAddr;
public LocalVar(DexNode dex, int rn, int nameId, int typeId, int signId) {
this.regNum = rn;
String name = nameId == DexNode.NO_INDEX ? null : dex.getString(nameId);
ArgType type = typeId == DexNode.NO_INDEX ? null : dex.getType(typeId);
String sign = signId == DexNode.NO_INDEX ? null : dex.getString(signId);
init(name, type, sign);
}
public LocalVar(RegisterArg arg) {
this.regNum = arg.getRegNum();
init(arg.getName(), arg.getType(), null);
}
private void init(String name, ArgType type, String sign) {
if (sign != null) {
try {
ArgType gType = ArgType.generic(sign);
if (checkSignature(type, sign, gType)) {
type = gType;
}
} catch (Exception e) {
LOG.error("Can't parse signature for local variable: {}", sign, e);
}
}
this.name = name;
this.type = type;
}
private boolean checkSignature(ArgType type, String sign, ArgType gType) {
boolean apply;
ArgType el = gType.getArrayRootElement();
if (el.isGeneric()) {
if (!type.getArrayRootElement().getObject().equals(el.getObject())) {
LOG.warn("Generic type in debug info not equals: {} != {}", type, gType);
}
apply = true;
} else {
apply = el.isGenericType();
}
return apply;
}
public void start(int addr, int line) {
this.isEnd = false;
this.startAddr = addr;
}
/**
* Sets end address of local variable
*
* @param addr address
* @param line source line
* @return <b>true</b> if local variable was active, else <b>false</b>
*/
public boolean end(int addr, int line) {
if (!isEnd) {
this.isEnd = true;
this.endAddr = addr;
return true;
}
return false;
}
public int getRegNum() {
return regNum;
}
public String getName() {
return name;
}
public ArgType getType() {
return type;
}
public boolean isEnd() {
return isEnd;
}
public int getStartAddr() {
return startAddr;
}
public int getEndAddr() {
return endAddr;
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public int hashCode() {
return super.hashCode();
}
@Override
public String toString() {
return super.toString() + " " + (isEnd
? "end: " + InsnUtils.formatOffset(startAddr) + "-" + InsnUtils.formatOffset(endAddr)
: "active: " + InsnUtils.formatOffset(startAddr));
}
}