Fixed #1981 AS3 star import collisions

This commit is contained in:
Jindra Petřík
2023-03-19 22:43:41 +01:00
parent 60409accd0
commit f81d1ac58d
17 changed files with 171 additions and 163 deletions
@@ -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<DottedChain, Set<String>> pkgToObjectsName = new LinkedHashMap<>();
private final Map<ClassDef, ClassIndex> classes = new HashMap<>();
private final Map<PropertyDef, TraitIndex> instanceProperties = new HashMap<>();
@@ -436,6 +441,36 @@ public final class AbcIndexing {
private final Map<PropertyNsDef, TraitIndex> classNsProperties = new HashMap<>();
private final Map<PropertyNsDef, TraitIndex> 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<String> getPackageObjects(DottedChain pkg) {
Set<String> 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();
}
}
@@ -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<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> 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<Dependency> dependencies = new ArrayList<>();
List<String> 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<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void writeImports(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, ABC abc, GraphTextWriter writer, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
List<String> namesInThisPackage = new ArrayList<>();
for (ABCContainerTag tag : abc.getAbcTags()) {
@@ -222,13 +209,12 @@ public abstract class Trait implements Cloneable, Serializable {
//imports
List<Dependency> dependencies = new ArrayList<>();
List<String> 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<DottedChain> imports = new ArrayList<>();
for (Dependency d : dependencies) {
@@ -240,21 +226,21 @@ public abstract class Trait implements Cloneable, Serializable {
List<String> 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<String> 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) {
@@ -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<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> 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<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> 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);
@@ -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<DottedChain> 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<DottedChain> 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<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> 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<>());
}
}
@@ -63,11 +63,11 @@ public class TraitMethodGetterSetter extends Trait {
}
@Override
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> 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<DottedChain> 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<DottedChain> 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);
@@ -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<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> 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
@@ -298,9 +298,9 @@ public class Traits implements Cloneable, Serializable {
}
}
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> 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);
}
}