improved/fixed go to declaration in AS3

This commit is contained in:
Jindra Petřík
2016-03-26 22:48:12 +01:00
parent bfeb2dc2ba
commit 33d6cd5c29
8 changed files with 139 additions and 15 deletions
@@ -311,6 +311,30 @@ public class AVM2ConstantPool implements Cloneable {
return null;
}
/**
* Converts kind MULTINAME with one namespace to QNAME with that namespace
* (must exist in the abc). Ignores others.
*
* @param cpool
* @param index MULTINAME index
* @return
*/
public int convertToQname(AVM2ConstantPool cpool, int index) {
Multiname mx = cpool.getMultiname(index);
if (mx.isMULTINAMEwithOneNs(cpool)) {
Multiname mx2 = new Multiname();
mx2.kind = Multiname.QNAME;
mx2.name_index = mx.name_index;
mx2.namespace_index = mx.getSingleNamespaceIndex(cpool);
//and same QNAME exists within this ABC
int newMultinameIndex = cpool.getMultinameId(mx2, false);
if (newMultinameIndex > 0) {
index = newMultinameIndex; //use that QNAME
}
}
return index;
}
public Multiname getMultiname(int index) {
try {
return constant_multiname.get(index);
@@ -514,6 +538,23 @@ public class AVM2ConstantPool implements Cloneable {
return id;
}
/**
* Finds multiname index based on multiname in other constant pool
*
* @param val
* @param origConst
* @return
*/
public int getMultinameId(Multiname val, AVM2ConstantPool origConst) {
for (int i = 1; i < getMultinameCount(); i++) {
if (getMultiname(i).qnameEquals(this, val, origConst)) {
return i;
}
}
return -1;
}
public int getStringId(String val, boolean add) {
if (val == null) {
return 0;
@@ -106,7 +106,7 @@ public class InstanceInfo {
writer.hilightSpecial(abc.constants.getMultiname(name_index).getName(abc.constants, null/* No full names here*/, false), HighlightSpecialType.CLASS_NAME);
if (super_index > 0) {
String typeName = abc.constants.getMultiname(super_index).getNameWithNamespace(abc.constants).toPrintableString(true);
String typeName = abc.constants.getMultiname(super_index).getNameWithNamespace(abc.constants).toRawString();
String parentName = abc.constants.getMultiname(super_index).getName(abc.constants, fullyQualifiedNames, false);
if (!parentName.equals("Object")) {
writer.appendNoHilight(" extends ");
@@ -123,7 +123,7 @@ public class InstanceInfo {
if (i > 0) {
writer.append(", ");
}
String typeName = abc.constants.getMultiname(interfaces[i]).getNameWithNamespace(abc.constants).toPrintableString(true);
String typeName = abc.constants.getMultiname(interfaces[i]).getNameWithNamespace(abc.constants).toRawString();
writer.hilightSpecial(abc.constants.getMultiname(interfaces[i]).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName);
}
}
@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
import com.jpexs.decompiler.flash.types.annotations.Internal;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.helpers.Helper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -418,4 +419,72 @@ public class Multiname {
}
return true;
}
/**
* Is this MULTINAME kind with only one namespace. Hint: it is sometimes
* used for interfaces
*
* @param pool
* @return
*/
public boolean isMULTINAMEwithOneNs(AVM2ConstantPool pool) {
return kind == MULTINAME && pool.getNamespaceSet(namespace_set_index).namespaces.length == 1;
}
/**
* Gets single namespace index. It can be the namespace index of QNAME or
* namespace index in namespace set of MULTINAME, if it has only one
* namespace in the set.
*
* @param pool
* @return
*/
public int getSingleNamespaceIndex(AVM2ConstantPool pool) {
if (isMULTINAMEwithOneNs(pool)) {
return pool.getNamespaceSet(namespace_set_index).namespaces[0];
}
return namespace_index;
}
/**
* Gets single namespace. It can be the namespace of QNAME or namespace in
* namespace set of MULTINAME, if it has only one namespace in the set.
*
* @param pool
* @return
*/
public Namespace getSingleNamespace(AVM2ConstantPool pool) {
int index = getSingleNamespaceIndex(pool);
if (index < 0) {
return null;
}
return pool.getNamespace(index);
}
private boolean isEfectivelyQname(AVM2ConstantPool thisCpool) {
return kind == QNAME || kind == QNAMEA || isMULTINAMEwithOneNs(thisCpool);
}
public boolean qnameEquals(AVM2ConstantPool thisCpool, Multiname other, AVM2ConstantPool otherCpool) {
if (!isEfectivelyQname(thisCpool) || !other.isEfectivelyQname(otherCpool)) {
return false;
}
Namespace otherNs = other.getSingleNamespace(otherCpool);
Namespace thisNs = getSingleNamespace(thisCpool);
if (otherNs.kind != thisNs.kind) {
return false;
}
if (otherNs.kind == Namespace.KIND_PRIVATE) {
return false;
}
if (!Objects.equals(otherNs.getName(otherCpool).toRawString(), thisNs.getName(thisCpool).toRawString())) {
return false;
}
if (!Objects.equals(other.getName(otherCpool, new ArrayList<>(), true), getName(thisCpool, new ArrayList<>(), true))) {
return false;
}
return true;
}
}
@@ -79,9 +79,9 @@ public class TypeItem extends GraphTargetItem {
boolean as3 = localData.constantsAvm2 != null;
if (localData.fullyQualifiedNames.contains(new DottedChain(fullTypeName.getLast()))) {
writer.hilightSpecial(fullTypeName.toPrintableString(as3), HighlightSpecialType.TYPE_NAME, fullTypeName.toPrintableString(as3));
writer.hilightSpecial(fullTypeName.toPrintableString(as3), HighlightSpecialType.TYPE_NAME, fullTypeName.toRawString());
} else {
writer.hilightSpecial(IdentifiersDeobfuscation.printIdentifier(as3, fullTypeName.getLast()), HighlightSpecialType.TYPE_NAME, fullTypeName.toPrintableString(as3));
writer.hilightSpecial(IdentifiersDeobfuscation.printIdentifier(as3, fullTypeName.getLast()), HighlightSpecialType.TYPE_NAME, fullTypeName.toRawString());
}
return writer;