diff --git a/CHANGELOG.md b/CHANGELOG.md index 859bd4bdf..d8957b6d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ All notable changes to this project will be documented in this file. - [#2077] AS3 allow star string as property name (XML access) - [#2077] AS3 try..catch parts outside block - AS3 try..catch inside loop unneccessary continue +- [#2077] AS3 colliding types in current package with trait names ### Changed - [#2070] String values inside SWF to XML export are backslash escaped 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 945a3e809..9a6d993db 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 @@ -39,6 +39,7 @@ import com.jpexs.decompiler.flash.search.MethodId; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.helpers.Helper; import java.io.Serializable; import java.util.AbstractMap.SimpleEntry; @@ -193,7 +194,35 @@ public abstract class Trait implements Cloneable, Serializable { } return false; } - + + private void getAllClassTraitNames(List traitNamesInThisScript, AbcIndexing abcIndex, ABC abc, int classIndex, Integer scriptIndex, boolean isParent) { + boolean publicProtectedOnly = isParent; + for (Trait it : abc.instance_info.get(classIndex).instance_traits.traits) { + if (publicProtectedOnly) { + Namespace ns = it.getName(abc).getNamespace(abc.constants); + if (ns.kind != Namespace.KIND_PACKAGE && ns.kind != Namespace.KIND_PROTECTED) { + continue; + } + } + traitNamesInThisScript.add(it.getName(abc).getName(abc.constants, new ArrayList<>(), true, true)); + } + for (Trait ct : abc.class_info.get(classIndex).static_traits.traits) { + if (publicProtectedOnly) { + Namespace ns = ct.getName(abc).getNamespace(abc.constants); + if (ns.kind != Namespace.KIND_PACKAGE && ns.kind != Namespace.KIND_STATIC_PROTECTED) { + continue; + } + } + traitNamesInThisScript.add(ct.getName(abc).getName(abc.constants, new ArrayList<>(), true, true)); + } + if (abc.instance_info.get(classIndex).super_index == 0) { + return; + } + DottedChain fullClassName = abc.constants.getMultiname(abc.instance_info.get(classIndex).super_index).getNameWithNamespace(abc.constants, true); + AbcIndexing.ClassIndex ci = abcIndex.findClass(new TypeItem(fullClassName), abc, scriptIndex); + getAllClassTraitNames(traitNamesInThisScript, abcIndex, ci.abc, ci.index, ci.scriptIndex, true); + } + 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<>(); @@ -208,6 +237,15 @@ public abstract class Trait implements Cloneable, Serializable { } } + List traitNamesInThisScript = new ArrayList<>(); + for (Trait st : abc.script_info.get(scriptIndex).traits.traits) { + if (st instanceof TraitClass) { + getAllClassTraitNames(traitNamesInThisScript, abcIndex, abc, ((TraitClass) st).class_info, scriptIndex, false); + } else { + traitNamesInThisScript.add(st.getName(abc).getName(abc.constants, new ArrayList<>(), true, true)); + } + } + //imports List dependencies = new ArrayList<>(); String customNs = null; @@ -226,8 +264,9 @@ public abstract class Trait implements Cloneable, Serializable { List importnames = new ArrayList<>(); importnames.addAll(namesInThisPackage); + importnames.addAll(traitNamesInThisScript); importnames.addAll(Arrays.asList(builtInClasses)); - + for (DottedChain imp : imports) { if (imp.getLast().equals("*")) { Set objectsInPkg = abcIndex.getPackageObjects(imp.getWithoutLast()); @@ -240,8 +279,7 @@ public abstract class Trait implements Cloneable, Serializable { } } } - - + for (int i = 0; i < imports.size(); i++) { DottedChain imp = imports.get(i); DottedChain pkg = imp.getWithoutLast(); @@ -255,16 +293,20 @@ 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 (ipath.getWithoutLast().equals(ignorePackage)) { //do not check classes from same package, they are imported automatically + if (traitNamesInThisScript.contains(name)) { + fullyQualifiedNames.add(DottedChain.parseWithSuffix(name)); + } + imports.remove(i); - i--; + i--; continue; } - + if (importnames.contains(name)) { fullyQualifiedNames.add(DottedChain.parseWithSuffix(name)); } else { @@ -272,8 +314,6 @@ public abstract class Trait implements Cloneable, Serializable { } } - - boolean hasImport = false; Collections.sort(imports); for (DottedChain imp : imports) { @@ -284,9 +324,9 @@ public abstract class Trait implements Cloneable, Serializable { writer.appendNoHilight(imp.getWithoutLast().toPrintableString(true)); writer.appendNoHilight("."); } - if ("*".equals(imp.getLast())){ + if ("*".equals(imp.getLast())) { writer.appendNoHilight("*"); - }else{ + } else { writer.hilightSpecial(IdentifiersDeobfuscation.printIdentifier(true, imp.getLast()), HighlightSpecialType.TYPE_NAME, imp.toRawString()); } writer.appendNoHilight(";").newLine(); @@ -370,7 +410,7 @@ public abstract class Trait implements Cloneable, Serializable { } else { writer.appendNoHilight("static "); } - } + } return writer; } @@ -423,7 +463,7 @@ public abstract class Trait implements Cloneable, Serializable { } if ((kindFlags & ATTR_Metadata) > 0) { for (int m : metadata) { - writer.newLine(); + writer.newLine(); writer.append("metadata "); writer.append("\""); writer.append(Helper.escapePCodeString(abc.constants.getString(abc.metadata_info.get(m).name_index))); 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 342c6bedf..02636ea1d 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 @@ -91,7 +91,8 @@ public class DependencyParser { if (pkg.equals(InitVectorAVM2Item.VECTOR_PACKAGE)) { //special case - is imported always return; } - if (!pkg.equals(ignorePackage)) { + //if (!pkg.equals(ignorePackage)) + { dependencies.add(dep); } } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassTest.java index 1d1dda64b..9caecd142 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassTest.java @@ -530,4 +530,32 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase { + " }\n" + "}"); } + + @Test + public void testCollidingTraitNames() { + decompileScriptPack("standard", "tests_classes.TestCollidingTraitNames", "package tests_classes\n" + + "{\n" + + " public class TestCollidingTraitNames extends CollidingAttributeParent\n" + + " {\n" + + " \n" + + " \n" + + " public var CollidingAttribute:tests_classes.CollidingAttribute;\n" + + " \n" + + " public function TestCollidingTraitNames()\n" + + " {\n" + + " super();\n" + + " }\n" + + " \n" + + " public function test() : void\n" + + " {\n" + + " var t:tests_classes.CollidingAttribute2 = null;\n" + + " }\n" + + " \n" + + " public function CollidingMethod() : void\n" + + " {\n" + + " var t:tests_classes.CollidingMethod = null;\n" + + " }\n" + + " }\n" + + "}"); + } } 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 368c2a0d6..a352c4e1d 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 878c2041f..4837ada37 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/Main.as b/libsrc/ffdec_lib/testdata/as3_new/src/Main.as index 804b71688..e1c518395 100644 --- a/libsrc/ffdec_lib/testdata/as3_new/src/Main.as +++ b/libsrc/ffdec_lib/testdata/as3_new/src/Main.as @@ -23,7 +23,8 @@ package TestCatchFinally; TestChain2; TestChainedAssignments; - TestCollidingTry; + TestCollidingTraitNames; + TestCollidingTry; TestComplexExpressions; TestContinueLevels; TestConvert; @@ -157,4 +158,4 @@ package } -} \ No newline at end of file +} diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/CollidingAttribute.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/CollidingAttribute.as new file mode 100644 index 000000000..0ded04a1c --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/CollidingAttribute.as @@ -0,0 +1,7 @@ +package tests_classes +{ + public class CollidingAttribute + { + + } +} diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/CollidingAttribute2.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/CollidingAttribute2.as new file mode 100644 index 000000000..91d44a72a --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/CollidingAttribute2.as @@ -0,0 +1,7 @@ +package tests_classes +{ + public class CollidingAttribute2 + { + + } +} diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/CollidingAttributeParent.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/CollidingAttributeParent.as new file mode 100644 index 000000000..b2ec8e514 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/CollidingAttributeParent.as @@ -0,0 +1,7 @@ +package tests_classes +{ + public class CollidingAttributeParent + { + public var CollidingAttribute2:int = 5; + } +} diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/CollidingMethod.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/CollidingMethod.as new file mode 100644 index 000000000..d97178a08 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/CollidingMethod.as @@ -0,0 +1,7 @@ +package tests_classes +{ + public class CollidingMethod + { + + } +} diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/TestCollidingTraitNames.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/TestCollidingTraitNames.as new file mode 100644 index 000000000..9b258847d --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests_classes/TestCollidingTraitNames.as @@ -0,0 +1,16 @@ +package tests_classes +{ + public class TestCollidingTraitNames extends CollidingAttributeParent + { + public var CollidingAttribute:tests_classes.CollidingAttribute; + + public function test(): void + { + var t:tests_classes.CollidingAttribute2 = null; + } + + public function CollidingMethod(): void { + var t:tests_classes.CollidingMethod = null; + } + } +}