diff --git a/CHANGELOG.md b/CHANGELOG.md index a9e37e6d7..b6486caef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. - AS3 Metadata values order - AS3 Metadata in P-code formatting - AS3 Metadata single value (null item key) +- [#1981] AS3 star import collisions ## [18.3.6] - 2023-02-25 ### Fixed diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index adba388f6..9ed958b88 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -456,6 +456,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { abcIndex.addAbc(((ABCContainerTag) tag).getABC()); } } + abcIndex.rebuildPkgToObjectsNameMap(); return abcIndex; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java index 8bf72e2f9..7d8b0edbb 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java @@ -40,6 +40,8 @@ import com.jpexs.helpers.Reference; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -83,6 +85,7 @@ public final class AbcIndexing { for (ABCContainerTag at : swf.getAbcList()) { addAbc(at.getABC()); } + rebuildPkgToObjectsNameMap(); } } @@ -425,6 +428,8 @@ public final class AbcIndexing { } } + private Map> pkgToObjectsName = new LinkedHashMap<>(); + private final Map classes = new HashMap<>(); private final Map instanceProperties = new HashMap<>(); @@ -436,6 +441,36 @@ public final class AbcIndexing { private final Map classNsProperties = new HashMap<>(); private final Map scriptProperties = new HashMap<>(); + + public void rebuildPkgToObjectsNameMap() { + pkgToObjectsName.clear(); + for (ClassDef cd:classes.keySet()) { + if (!(cd.type instanceof TypeItem)) { + continue; + } + if (!pkgToObjectsName.containsKey(cd.pkg)) { + pkgToObjectsName.put(cd.pkg, new LinkedHashSet<>()); + } + pkgToObjectsName.get(cd.pkg).add(((TypeItem)cd.type).fullTypeName.getLast()); + } + for (PropertyNsDef nsdef:scriptProperties.keySet()) { + if (!pkgToObjectsName.containsKey(nsdef.ns)) { + pkgToObjectsName.put(nsdef.ns, new LinkedHashSet<>()); + } + pkgToObjectsName.get(nsdef.ns).add(nsdef.propName); + } + } + + public Set getPackageObjects(DottedChain pkg) { + Set classNames = new LinkedHashSet<>(); + if (pkgToObjectsName.containsKey(pkg)) { + classNames.addAll(pkgToObjectsName.get(pkg)); + } + if (parent != null) { + classNames.addAll(parent.getPackageObjects(pkg)); + } + return classNames; + } public ClassIndex findClass(GraphTargetItem cls, ABC abc, Integer scriptIndex) { ClassDef keyWithScriptIndex = new ClassDef(cls, abc, scriptIndex); @@ -717,6 +752,7 @@ public final class AbcIndexing { } removeAbc(abc); addAbc(abc); + rebuildPkgToObjectsNameMap(); } public void removeAbc(ABC abc) { @@ -808,7 +844,7 @@ public final class AbcIndexing { } } abcs.add(abc); - selectedAbc = abc; + selectedAbc = abc; } public void selectAbc(ABC abc) { @@ -816,6 +852,7 @@ public final class AbcIndexing { selectedAbc = abc; } else { addAbc(abc); + rebuildPkgToObjectsNameMap(); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index 2044df86c..e24f685b7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -49,6 +49,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; /** * @@ -170,14 +171,15 @@ public abstract class Trait implements Cloneable, Serializable { return getName(abc).getNamespace(abc.constants).getName(abc.constants); } - public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { + public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { if (ignoredCustom == null) { Namespace n = getName(abc).getNamespace(abc.constants); if (n.kind == Namespace.KIND_NAMESPACE) { ignoredCustom = n.getName(abc.constants).toRawString(); } } - DependencyParser.parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, getName(abc), ignorePackage, fullyQualifiedNames, DependencyType.NAMESPACE); + DependencyParser.parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, getName(abc), ignorePackage, fullyQualifiedNames, DependencyType.NAMESPACE); + //DependencyParser.parseUsagesFromMultiname(ignoredCustom, abc, dependencies, getName(abc), ignorePackage, fullyQualifiedNames, DependencyType.NAMESPACE); } 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"}; @@ -190,23 +192,8 @@ public abstract class Trait implements Cloneable, Serializable { } return false; } - - - public void writeUses(int scriptIndex, int classIndex, boolean isStatic, ABC abc, GraphTextWriter writer) throws InterruptedException { - List dependencies = new ArrayList<>(); - List uses = new ArrayList<>(); - String customNs = null; - Namespace ns = getName(abc).getNamespace(abc.constants); - if (ns.kind == Namespace.KIND_NAMESPACE) { - customNs = ns.getName(abc.constants).toRawString(); - } - getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, uses, null, new ArrayList<>()); - for (String us : uses) { - writer.appendNoHilight("use namespace " + us + ";").newLine(); - } - } - - public void writeImportsUsages(int scriptIndex, int classIndex, boolean isStatic, ABC abc, GraphTextWriter writer, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { + + public void writeImports(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, ABC abc, GraphTextWriter writer, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { List namesInThisPackage = new ArrayList<>(); for (ABCContainerTag tag : abc.getAbcTags()) { @@ -222,13 +209,12 @@ public abstract class Trait implements Cloneable, Serializable { //imports List dependencies = new ArrayList<>(); - List uses = new ArrayList<>(); String customNs = null; Namespace ns = getName(abc).getNamespace(abc.constants); if (ns.kind == Namespace.KIND_NAMESPACE) { customNs = ns.getName(abc.constants).toRawString(); } - getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, uses, ignorePackage, new ArrayList<>()); + getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, new ArrayList<>()); List imports = new ArrayList<>(); for (Dependency d : dependencies) { @@ -240,21 +226,21 @@ public abstract class Trait implements Cloneable, Serializable { List importnames = new ArrayList<>(); importnames.addAll(namesInThisPackage); importnames.addAll(Arrays.asList(builtInClasses)); - for (int i = 0; i < imports.size(); i++) { - DottedChain ipath = imports.get(i); - if (ipath.getWithoutLast().equals(ignorePackage)) { //do not check classes from same package, they are imported automatically - imports.remove(i); - i--; - continue; - } - String name = ipath.getLast(); - if (importnames.contains(name)) { - fullyQualifiedNames.add(DottedChain.parseWithSuffix(name)); - } else { - importnames.add(name); + + for (DottedChain imp : imports) { + if (imp.getLast().equals("*")) { + Set objectsInPkg = abcIndex.getPackageObjects(imp.getWithoutLast()); + for (String objectName : objectsInPkg) { + if (importnames.contains(objectName)) { + fullyQualifiedNames.add(DottedChain.parseWithSuffix(objectName)); + } else { + importnames.add(objectName); + } + } } } - + + for (int i = 0; i < imports.size(); i++) { DottedChain imp = imports.get(i); DottedChain pkg = imp.getWithoutLast(); @@ -268,6 +254,28 @@ public abstract class Trait implements Cloneable, Serializable { i--; } } + + for (int i = 0; i < imports.size(); i++) { + DottedChain ipath = imports.get(i); + String name = ipath.getLast(); + if (ipath.getWithoutLast().equals(ignorePackage)) { //do not check classes from same package, they are imported automatically + if (importnames.contains(name)) { + fullyQualifiedNames.add(DottedChain.parseWithSuffix(name)); + } + + imports.remove(i); + i--; + continue; + } + + if (importnames.contains(name)) { + fullyQualifiedNames.add(DottedChain.parseWithSuffix(name)); + } else { + importnames.add(name); + } + } + + boolean hasImport = false; Collections.sort(imports); @@ -291,12 +299,6 @@ public abstract class Trait implements Cloneable, Serializable { if (hasImport) { writer.newLine(); } - /*for (String us : uses) { - writer.appendNoHilight("use namespace " + us + ";").newLine(); - } - if (uses.size() > 0) { - writer.newLine(); - }*/ } public final GraphTextWriter getMetaData(Trait parent, ConvertData convertData, ABC abc, GraphTextWriter writer) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index b041555cd..56baffe26 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -78,31 +78,31 @@ public class TraitClass extends Trait implements TraitWithSlot { } @Override - public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { - super.getDependencies(scriptIndex, -1, false, customNs, abc, dependencies, uses, ignorePackage == null ? getPackage(abc) : ignorePackage, fullyQualifiedNames); + public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { + super.getDependencies(scriptIndex, -1, false, customNs, abc, dependencies, ignorePackage == null ? getPackage(abc) : ignorePackage, fullyQualifiedNames); ClassInfo classInfo = abc.class_info.get(class_info); InstanceInfo instanceInfo = abc.instance_info.get(class_info); DottedChain packageName = instanceInfo.getName(abc.constants).getNamespace(abc.constants).getName(abc.constants); //assume not null name //DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames); if (instanceInfo.super_index > 0) { - DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames, DependencyType.INHERITANCE); + DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames, DependencyType.INHERITANCE); } for (int i : instanceInfo.interfaces) { - DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames, DependencyType.INHERITANCE); + DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, abc.constants.getMultiname(i), packageName, fullyQualifiedNames, DependencyType.INHERITANCE); } //static - classInfo.static_traits.getDependencies(scriptIndex, class_info, true, customNs, abc, dependencies, uses, packageName, fullyQualifiedNames); + classInfo.static_traits.getDependencies(scriptIndex, class_info, true, customNs, abc, dependencies, packageName, fullyQualifiedNames); //static initializer - DependencyParser.parseDependenciesFromMethodInfo(null, scriptIndex, class_info, true, customNs, abc, classInfo.cinit_index, dependencies, uses, packageName, fullyQualifiedNames, new ArrayList<>()); + DependencyParser.parseDependenciesFromMethodInfo(null, scriptIndex, class_info, true, customNs, abc, classInfo.cinit_index, dependencies, packageName, fullyQualifiedNames, new ArrayList<>()); //instance - instanceInfo.instance_traits.getDependencies(scriptIndex, class_info, false, customNs, abc, dependencies, uses, packageName, fullyQualifiedNames); + instanceInfo.instance_traits.getDependencies(scriptIndex, class_info, false, customNs, abc, dependencies, packageName, fullyQualifiedNames); //instance initializer - DependencyParser.parseDependenciesFromMethodInfo(null, scriptIndex, class_info, false, customNs, abc, instanceInfo.iinit_index, dependencies, uses, packageName, fullyQualifiedNames, new ArrayList<>()); + DependencyParser.parseDependenciesFromMethodInfo(null, scriptIndex, class_info, false, customNs, abc, instanceInfo.iinit_index, dependencies, packageName, fullyQualifiedNames, new ArrayList<>()); } @Override @@ -123,7 +123,7 @@ public class TraitClass extends Trait implements TraitWithSlot { DottedChain packageName = instanceInfoMultiname.getNamespace(abc.constants).getName(abc.constants); //assume not null name fullyQualifiedNames = new ArrayList<>(); - writeImportsUsages(scriptIndex, classIndex, false, abc, writer, packageName, fullyQualifiedNames); + writeImports(abcIndex, scriptIndex, classIndex, false, abc, writer, packageName, fullyQualifiedNames); String instanceInfoName = instanceInfoMultiname.getName(abc.constants, fullyQualifiedNames, false, true); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java index d7b68e43d..4db356181 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java @@ -82,7 +82,7 @@ public class TraitFunction extends Trait implements TraitWithSlot { @Override public GraphTextWriter toString(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - writeImportsUsages(scriptIndex, classIndex, false, abc, writer, getPackage(abc), fullyQualifiedNames); + writeImports(abcIndex, scriptIndex, classIndex, false, abc, writer, getPackage(abc), fullyQualifiedNames); getMetaData(parent, convertData, abc, writer); writer.startMethod(method_info); toStringHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); @@ -105,7 +105,7 @@ public class TraitFunction extends Trait implements TraitWithSlot { @Override public void convert(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { fullyQualifiedNames = new ArrayList<>(); - writeImportsUsages(scriptIndex, classIndex, false, abc, writer, getPackage(abc), fullyQualifiedNames); + writeImports(abcIndex, scriptIndex, classIndex, false, abc, writer, getPackage(abc), fullyQualifiedNames); writer.startMethod(method_info); convertHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); int bodyIndex = abc.findBodyIndex(method_info); @@ -133,14 +133,14 @@ public class TraitFunction extends Trait implements TraitWithSlot { } @Override - public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { + public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { if (ignorePackage == null) { ignorePackage = getPackage(abc); } - super.getDependencies(scriptIndex, classIndex, false, customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames); + super.getDependencies(scriptIndex, classIndex, false, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames); //if (method_info != 0) { - DependencyParser.parseDependenciesFromMethodInfo(this, scriptIndex, classIndex, false, customNs, abc, method_info, dependencies, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>()); + DependencyParser.parseDependenciesFromMethodInfo(this, scriptIndex, classIndex, false, customNs, abc, method_info, dependencies, ignorePackage, fullyQualifiedNames, new ArrayList<>()); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java index 7764e2443..3544d5949 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java @@ -63,11 +63,11 @@ public class TraitMethodGetterSetter extends Trait { } @Override - public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { + public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { if (ignorePackage == null) { ignorePackage = getPackage(abc); } - super.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames); + super.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames); if (customNs == null) { Namespace n = getName(abc).getNamespace(abc.constants); @@ -77,7 +77,7 @@ public class TraitMethodGetterSetter extends Trait { } //if (method_info != 0) { - DependencyParser.parseDependenciesFromMethodInfo(this, scriptIndex, classIndex, isStatic, customNs, abc, method_info, dependencies, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>()); + DependencyParser.parseDependenciesFromMethodInfo(this, scriptIndex, classIndex, isStatic, customNs, abc, method_info, dependencies, ignorePackage, fullyQualifiedNames, new ArrayList<>()); } } @@ -110,7 +110,7 @@ public class TraitMethodGetterSetter extends Trait { @Override public void convert(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { if (classIndex < 0) { - writeImportsUsages(scriptIndex, classIndex, isStatic, abc, writer, getPackage(abc), fullyQualifiedNames); + writeImports(abcIndex, scriptIndex, classIndex, isStatic, abc, writer, getPackage(abc), fullyQualifiedNames); } writer.startMethod(method_info); path = path + "." + getName(abc).getName(abc.constants, fullyQualifiedNames, false, true); @@ -132,7 +132,7 @@ public class TraitMethodGetterSetter extends Trait { public GraphTextWriter toString(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { if (classIndex < 0) { - writeImportsUsages(scriptIndex, classIndex, isStatic, abc, writer, getPackage(abc), fullyQualifiedNames); + writeImports(abcIndex, scriptIndex, classIndex, isStatic, abc, writer, getPackage(abc), fullyQualifiedNames); } getMetaData(parent, convertData, abc, writer); writer.startMethod(method_info); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java index 9f782d06d..bea04594a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java @@ -221,12 +221,12 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { } @Override - public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { + public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { if (ignorePackage == null) { ignorePackage = getPackage(abc); } - super.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames); - DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames, DependencyType.SIGNATURE); + super.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames); + DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames, DependencyType.SIGNATURE); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java index 26f69f7f9..343a6039a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java @@ -298,9 +298,9 @@ public class Traits implements Cloneable, Serializable { } } - public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { + public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { for (Trait t : traits) { - t.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames); + t.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyParser.java index d3803272b..5216b2b7c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyParser.java @@ -21,10 +21,15 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.AVM2Deobfuscation; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.AlchemyTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructPropIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyStrictIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetLexIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetPropertyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetSuperIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetPropertyIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSuperIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceIns; import com.jpexs.decompiler.flash.abc.avm2.model.InitVectorAVM2Item; @@ -41,16 +46,36 @@ import java.util.List; public class DependencyParser { - public static void parseDependenciesFromNS(String ignoredCustom, ABC abc, List dependencies, List uses, int namespace_index, DottedChain ignorePackage, String name, DependencyType dependencyType) { + public static void parseDependenciesFromNS(String ignoredCustom, ABC abc, List dependencies, int namespace_index, DottedChain ignorePackage, String name, DependencyType dependencyType) { Namespace ns = abc.constants.getNamespace(namespace_index); if (name.isEmpty()) { name = "*"; } DottedChain newimport = ns.getName(abc.constants); - if (parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, namespace_index, ignorePackage, name)) { - return; - } else if (ns.kind != Namespace.KIND_PACKAGE) { // && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) { + + if (ns.kind == Namespace.KIND_NAMESPACE || ns.kind == Namespace.KIND_PACKAGE_INTERNAL) { + String nsVal = ns.getName(abc.constants).toRawString(); + for (ABCContainerTag abcTag : abc.getAbcTags()) { + DottedChain nsimport = abcTag.getABC().nsValueToName(nsVal); + if (nsimport.equals(AVM2Deobfuscation.BUILTIN)) { + return; //builtin, no dependency + } + if (!nsimport.isEmpty()) { + + Dependency depNs = new Dependency(nsimport, DependencyType.NAMESPACE); + if ((ignorePackage == null || !nsimport.getWithoutLast().equals(ignorePackage)) && !dependencies.contains(depNs)) { + dependencies.add(depNs); + } + if (ignoredCustom != null && nsVal.equals(ignoredCustom)) { + return; + } + return; + } + } + } + + if (ns.kind != Namespace.KIND_PACKAGE) { // && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) { return; } newimport = newimport.addWithSuffix(name); @@ -68,15 +93,15 @@ public class DependencyParser { //} } - public static void parseDependenciesFromMultiname(String ignoredCustom, ABC abc, List dependencies, List uses, Multiname m, DottedChain ignorePackage, List fullyQualifiedNames, DependencyType dependencyType) { + public static void parseDependenciesFromMultiname(String ignoredCustom, ABC abc, List dependencies, Multiname m, DottedChain ignorePackage, List fullyQualifiedNames, DependencyType dependencyType) { if (m != null) { if (m.kind == Multiname.TYPENAME) { if (m.qname_index != 0) { - parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames, dependencyType); + parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames, dependencyType); } for (Integer i : m.params) { if (i != 0) { - parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames, dependencyType); + parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames, dependencyType); } } return; @@ -85,35 +110,35 @@ public class DependencyParser { String name = m.getName(abc.constants, fullyQualifiedNames, true, true); NamespaceSet nss = m.getNamespaceSet(abc.constants); if (ns != null) { - parseDependenciesFromNS(ignoredCustom, abc, dependencies, uses, m.namespace_index, ignorePackage, name, dependencyType); + parseDependenciesFromNS(ignoredCustom, abc, dependencies, m.namespace_index, ignorePackage, name, dependencyType); } if (nss != null) { for (int n : nss.namespaces) { - parseDependenciesFromNS(ignoredCustom, abc, dependencies, uses, n, ignorePackage, nss.namespaces.length > 1 ? "" : name, dependencyType); + parseDependenciesFromNS(ignoredCustom, abc, dependencies, n, ignorePackage, nss.namespaces.length > 1 ? "" : name, dependencyType); } } } } - public static void parseDependenciesFromMethodInfo(Trait trait, int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, int method_index, List dependencies, List uses, DottedChain ignorePackage, List fullyQualifiedNames, List visitedMethods) throws InterruptedException { + public static void parseDependenciesFromMethodInfo(Trait trait, int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, int method_index, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames, List visitedMethods) throws InterruptedException { 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) { - parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE); + parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE); } for (int t : abc.method_info.get(method_index).param_types) { if (t != 0) { - parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE); + parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE); } } MethodBody body = abc.findBody(method_index); if (body != null && body.convertException == null) { body = body.convertMethodBodyCanUseLast(Configuration.autoDeobfuscate.get(), "", isStatic, scriptIndex, classIndex, abc, trait); - body.traits.getDependencies(scriptIndex, classIndex, isStatic, ignoredCustom, abc, dependencies, uses, ignorePackage, fullyQualifiedNames); + body.traits.getDependencies(scriptIndex, classIndex, isStatic, ignoredCustom, abc, dependencies, ignorePackage, fullyQualifiedNames); for (ABCException ex : body.exceptions) { - parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION /* or signature?*/); + parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION /* or signature?*/); } for (AVM2Instruction ins : body.getCode().code) { if (ins.definition instanceof AlchemyTypeIns) { @@ -126,93 +151,20 @@ public class DependencyParser { if (ins.definition instanceof NewFunctionIns) { if (ins.operands[0] != method_index) { if (!visitedMethods.contains(ins.operands[0])) { - parseDependenciesFromMethodInfo(trait, scriptIndex, classIndex, isStatic, ignoredCustom, abc, ins.operands[0], dependencies, uses, ignorePackage, fullyQualifiedNames, visitedMethods); + parseDependenciesFromMethodInfo(trait, scriptIndex, classIndex, isStatic, ignoredCustom, abc, ins.operands[0], dependencies, 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) { + for (int k = 0; k < ins.definition.operands.length; k++) { + if (ins.definition.operands[k] == AVM2Code.DAT_MULTINAME_INDEX) { + int m = ins.operands[k]; if (m < abc.constants.getMultinameCount()) { - parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION); - } - } - } 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, dependencies, uses, abc.constants.getMultiname(multinameIndex), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION); - } + parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION); } } } } } - } - - public static void parseUsagesFromMultiname(String ignoredCustom, ABC abc, List dependencies, List uses, Multiname m, DottedChain ignorePackage, List fullyQualifiedNames, DependencyType dependencyType) { - if (m != null) { - if (m.kind == Multiname.TYPENAME) { - if (m.qname_index != 0) { - parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames, dependencyType); - } - for (Integer i : m.params) { - if (i != 0) { - parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames, dependencyType); - } - } - return; - } - Namespace ns = m.getNamespace(abc.constants); - String name = m.getName(abc.constants, fullyQualifiedNames, false, true); - NamespaceSet nss = m.getNamespaceSet(abc.constants); - if (ns != null) { - parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, m.namespace_index, ignorePackage, name); - } - if (nss != null) { - if (nss.namespaces.length == 1) { - parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, nss.namespaces[0], ignorePackage, name); - } else { - for (int n : nss.namespaces) { - parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, n, ignorePackage, ""); - } - } - } - } - } - - private static boolean parseUsagesFromNS(String ignoredCustom, ABC abc, List dependencies, List uses, int namespace_index, DottedChain ignorePackage, String name) { - Namespace ns = abc.constants.getNamespace(namespace_index); - - if (ns.kind == Namespace.KIND_NAMESPACE || ns.kind == Namespace.KIND_PACKAGE_INTERNAL) { - 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()) { - - Dependency depNs = new Dependency(nsimport, DependencyType.NAMESPACE); - if ((ignorePackage == null || !nsimport.getWithoutLast().equals(ignorePackage)) && !dependencies.contains(depNs)) { - dependencies.add(depNs); - } - if (ignoredCustom != null && nsVal.equals(ignoredCustom)) { - return true; - } - if (!uses.contains(nsimport.getLast())) { - uses.add(nsimport.getLast()); - } - return true; - } - } - } - return false; - } + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java index 04838939f..cbeb6b198 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java @@ -163,11 +163,9 @@ public class LinkReportExporter { reportTrait(scriptIndex, externalDefs, existingObjects, swf, abc, it); } List dependencies = new ArrayList<>(); - List uses = new ArrayList<>(); - sb.append(indent(3)).append("").append(newLineChar); //Automatic - tc.getDependencies(scriptIndex, -1, false, null, abc, dependencies, uses, new DottedChain(new String[]{"FAKE!PACKAGE"}), new ArrayList<>()); + tc.getDependencies(scriptIndex, -1, false, null, abc, dependencies, new DottedChain(new String[]{"FAKE!PACKAGE"}), new ArrayList<>()); for (Dependency dependency : dependencies) { DottedChain dc = dependency.getId(); if (!"*".equals(dc.getLast())) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java index f42eccdcf..f4929e75c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java @@ -148,8 +148,7 @@ public class SwfToSwcExporter { sb.append(" \n"); if (!skipDependencies) { List dependencies = new ArrayList<>(); - List uses = new ArrayList<>(); - pack.abc.script_info.get(pack.scriptIndex).traits.getDependencies(pack.scriptIndex, -1, false, null, pack.abc, dependencies, uses, new DottedChain(new String[]{"NO:PACKAGE"}), new ArrayList<>()); + pack.abc.script_info.get(pack.scriptIndex).traits.getDependencies(pack.scriptIndex, -1, false, null, pack.abc, dependencies, new DottedChain(new String[]{"NO:PACKAGE"}), new ArrayList<>()); for (Dependency d : dependencies) { if ("*".equals(d.getId().getLast())) { diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java index fddd4e9eb..097c52b93 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java @@ -130,6 +130,7 @@ public class ActionScript3DeobfuscatorTest extends ActionScriptTestBase { }); AbcIndexing index = swf.getAbcIndex(); index.addAbc(abc); + index.rebuildPkgToObjectsNameMap(); ActionScript3Parser par = new ActionScript3Parser(index); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); par.addScript(str, "Test.as", 0, 0); diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf index 90d1ef521..a9cbff8ca 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf index d9fbd8bf1..f65db78e7 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/mypackage1/SetupMyPackage1.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/mypackage1/SetupMyPackage1.as index c89fca656..d16501426 100644 --- a/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/mypackage1/SetupMyPackage1.as +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/mypackage1/SetupMyPackage1.as @@ -5,6 +5,7 @@ package tests_classes.mypackage1 myNamespace; TestClass; TestClass2; + TestClass3; TestInterface; public function SetupMyPackage1() diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/mypackage1/TestClass3.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/mypackage1/TestClass3.as new file mode 100644 index 000000000..c911c767a --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/mypackage1/TestClass3.as @@ -0,0 +1,16 @@ +package tests_classes.mypackage1 +{ + import tests_classes.mypackage2.*; + import flash.utils.Dictionary; + + public class TestClass3 + { + private var c:tests_classes.mypackage1.TestClass; + + public function run() : void { + var a:Dictionary = new Dictionary(); + a["test"] = 5; + trace(a["test"]); + } + } +} \ No newline at end of file