Import/Usage parsing separated to one class

Class for generating linker reports from SWF files
(similar to -link-report option in Flex)
Generating linker report from commandline
This commit is contained in:
Jindra Petřík
2016-07-31 15:15:36 +02:00
parent 234ed1c915
commit c8951d9522
8 changed files with 486 additions and 179 deletions
@@ -42,6 +42,7 @@ import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
@@ -169,117 +170,6 @@ public abstract class Trait implements Cloneable, Serializable {
return ret;
}
protected void parseImportsUsagesFromMultiname(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
if (m != null) {
if (m.kind == Multiname.TYPENAME) {
if (m.qname_index != 0) {
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames);
}
for (Integer i : m.params) {
if (i != 0) {
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames);
}
}
return;
}
Namespace ns = m.getNamespace(abc.constants);
String name = m.getName(abc.constants, fullyQualifiedNames, true);
NamespaceSet nss = m.getNamespaceSet(abc.constants);
if (ns != null) {
parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name);
}
if (nss != null) {
for (int n : nss.namespaces) {
parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, nss.namespaces.length > 1 ? "" : name);
}
}
}
}
private boolean parseUsagesFromNS(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, int namespace_index, DottedChain ignorePackage, String name) {
Namespace ns = abc.constants.getNamespace(namespace_index);
if (ns.kind == Namespace.KIND_NAMESPACE) {
String nsVal = ns.getName(abc.constants).toRawString();
for (ABCContainerTag abcTag : abc.getAbcTags()) {
DottedChain nsimport = abcTag.getABC().nsValueToName(nsVal);
if (nsimport.equals(AVM2Deobfuscation.BUILTIN)) {
return true; //handled, but import/use not added
}
if (!nsimport.isEmpty()) {
if (!nsimport.getWithoutLast().equals(ignorePackage) && !imports.contains(nsimport)) {
imports.add(nsimport);
}
if (ignoredCustom != null && nsVal.equals(ignoredCustom)) {
return true;
}
if (!uses.contains(nsimport.getLast())) {
uses.add(nsimport.getLast());
}
return true;
}
}
}
return false;
}
protected void parseImportsUsagesFromNS(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, int namespace_index, DottedChain ignorePackage, String name) {
Namespace ns = abc.constants.getNamespace(namespace_index);
if (name.isEmpty()) {
name = "*";
}
DottedChain newimport = ns.getName(abc.constants);
if (parseUsagesFromNS(ignoredCustom, abc, imports, uses, namespace_index, ignorePackage, name)) {
return;
} else if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) {
return;
}
newimport = newimport.add(name);
if (!imports.contains(newimport)) {
DottedChain pkg = newimport.getWithoutLast(); //.substring(0, newimport.lastIndexOf('.'));
if (pkg.equals(InitVectorAVM2Item.VECTOR_PACKAGE)) { //special case - is imported always
return;
}
if (!pkg.equals(ignorePackage)) {
imports.add(newimport);
}
}
//}
}
protected void parseUsagesFromMultiname(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
if (m != null) {
if (m.kind == Multiname.TYPENAME) {
if (m.qname_index != 0) {
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames);
}
for (Integer i : m.params) {
if (i != 0) {
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames);
}
}
return;
}
Namespace ns = m.getNamespace(abc.constants);
String name = m.getName(abc.constants, fullyQualifiedNames, false);
NamespaceSet nss = m.getNamespaceSet(abc.constants);
if (ns != null) {
parseUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name);
}
if (nss != null) {
if (nss.namespaces.length == 1) {
parseUsagesFromNS(ignoredCustom, abc, imports, uses, nss.namespaces[0], ignorePackage, name);
} else {
for (int n : nss.namespaces) {
parseUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, "");
}
}
}
}
}
protected DottedChain getPackage(ABC abc) {
return getName(abc).getNamespace(abc.constants).getName(abc.constants);
}
@@ -291,7 +181,7 @@ public abstract class Trait implements Cloneable, Serializable {
ignoredCustom = n.getName(abc.constants).toRawString();
}
}
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, getName(abc), ignorePackage, fullyQualifiedNames);
ImportsUsagesParser.parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, getName(abc), ignorePackage, fullyQualifiedNames);
}
private static final String[] builtInClasses = {"ArgumentError", "arguments", "Array", "Boolean", "Class", "Date", "DefinitionError", "Error", "EvalError", "Function", "int", "JSON", "Math", "Namespace", "Number", "Object", "QName", "RangeError", "ReferenceError", "RegExp", "SecurityError", "String", "SyntaxError", "TypeError", "uint", "URIError", "VerifyError", "XML", "XMLList"};
@@ -375,64 +265,6 @@ public abstract class Trait implements Cloneable, Serializable {
}
}
protected void parseImportsUsagesFromMethodInfo(String ignoredCustom, ABC abc, int method_index, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, List<Integer> visitedMethods) {
if ((method_index < 0) || (method_index >= abc.method_info.size())) {
return;
}
visitedMethods.add(method_index);
if (abc.method_info.get(method_index).ret_type != 0) {
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames);
}
for (int t : abc.method_info.get(method_index).param_types) {
if (t != 0) {
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames);
}
}
MethodBody body = abc.findBody(method_index);
if (body != null) {
body.traits.getImportsUsages(ignoredCustom, abc, imports, uses, ignorePackage, fullyQualifiedNames);
for (ABCException ex : body.exceptions) {
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames);
}
for (AVM2Instruction ins : body.getCode().code) {
if (ins.definition instanceof AlchemyTypeIns) {
DottedChain nimport = AlchemyTypeIns.ALCHEMY_PACKAGE.add(ins.definition.instructionName);
if (!imports.contains(nimport)) {
imports.add(nimport);
}
}
if (ins.definition instanceof NewFunctionIns) {
if (ins.operands[0] != method_index) {
if (!visitedMethods.contains(ins.operands[0])) {
parseImportsUsagesFromMethodInfo(ignoredCustom, abc, ins.operands[0], imports, uses, ignorePackage, fullyQualifiedNames, visitedMethods);
}
}
}
if ((ins.definition instanceof FindPropertyStrictIns)
|| (ins.definition instanceof FindPropertyIns)
|| (ins.definition instanceof GetLexIns)
|| (ins.definition instanceof CoerceIns)
|| (ins.definition instanceof AsTypeIns)) {
int m = ins.operands[0];
if (m != 0) {
if (m < abc.constants.getMultinameCount()) {
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames);
}
}
} else {
for (int k = 0; k < ins.definition.operands.length; k++) {
if (ins.definition.operands[k] == AVM2Code.DAT_MULTINAME_INDEX) {
int multinameIndex = ins.operands[k];
if (multinameIndex < abc.constants.getMultinameCount()) {
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(multinameIndex), ignorePackage, fullyQualifiedNames);
}
}
}
}
}
}
}
public final GraphTextWriter getMetaData(Trait parent, ConvertData convertData, ABC abc, GraphTextWriter writer) {
List<Entry<String, Map<String, String>>> md = getMetaDataTable(parent, convertData, abc);
for (Entry<String, Map<String, String>> en : md) {
@@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.graph.DottedChain;
@@ -84,26 +85,26 @@ public class TraitClass extends Trait implements TraitWithSlot {
InstanceInfo instanceInfo = abc.instance_info.get(class_info);
DottedChain packageName = instanceInfo.getName(abc.constants).getNamespace(abc.constants).getName(abc.constants); //assume not null name
parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames);
ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames);
if (instanceInfo.super_index > 0) {
parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames);
ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames);
}
for (int i : instanceInfo.interfaces) {
parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames);
ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames);
}
//static
classInfo.static_traits.getImportsUsages(customNs, abc, imports, uses, packageName, fullyQualifiedNames);
//static initializer
parseImportsUsagesFromMethodInfo(customNs, abc, classInfo.cinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, classInfo.cinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
//instance
instanceInfo.instance_traits.getImportsUsages(customNs, abc, imports, uses, packageName, fullyQualifiedNames);
//instance initializer
parseImportsUsagesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
}
@Override
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.types.ConvertData;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
@@ -130,7 +131,7 @@ public class TraitFunction extends Trait implements TraitWithSlot {
super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
//if (method_info != 0)
{
parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
}
}
}
@@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
@@ -72,7 +73,7 @@ public class TraitMethodGetterSetter extends Trait {
}
//if (method_info != 0)
{
parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
}
}
@@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.ValueKind;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.ImportsUsagesParser;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
@@ -201,7 +202,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot {
ignorePackage = getPackage(abc);
}
super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames);
ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames);
}
@Override