AS3 editation with flex - not really working yet:

- needs fixing circular references, etc. (eg. editing class which references classes which references this class)
 - needs better errors displaying with jump to error line, etc.
This commit is contained in:
Jindra Petřík
2016-08-06 07:19:52 +02:00
parent c8951d9522
commit 8c5345cfd8
25 changed files with 1067 additions and 154 deletions
@@ -55,7 +55,11 @@ import com.jpexs.decompiler.flash.abc.usages.MethodParamsMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.MethodReturnTypeMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.MultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.TypeNameMultinameUsage;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.dumpview.DumpInfo;
import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter;
import com.jpexs.decompiler.flash.flexsdk.As3ScriptReplacer;
import com.jpexs.decompiler.flash.flexsdk.MxmlcException;
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.Tag;
@@ -137,6 +141,25 @@ public class ABC {
return method_info.size() - 1;
}
public void deleteClass(int class_info, boolean d) {
ABC abc = this;
ClassInfo classInfo = abc.class_info.get(class_info);
classInfo.deleted = d;
InstanceInfo instanceInfo = abc.instance_info.get(class_info);
instanceInfo.deleted = d;
classInfo.static_traits.delete(abc, d);
abc.method_info.get(classInfo.cinit_index).delete(abc, d);
instanceInfo.instance_traits.delete(abc, d);
abc.method_info.get(instanceInfo.iinit_index).delete(abc, d);
int protectedNS = instanceInfo.protectedNS;
if (protectedNS != 0) {
abc.constants.getNamespace(protectedNS).deleted = d;
}
}
public TraitMethodGetterSetter addMethod(int classId, String name, boolean isStatic) {
Multiname multiname = new Multiname();
multiname.kind = Multiname.QNAME;
@@ -743,10 +766,19 @@ public class ABC {
aos.writeU30(ci.cinit_index);
aos.writeTraits(ci.static_traits);
}
aos.writeU30(script_info.size());
int numScripts = script_info.size();
for (ScriptInfo si : script_info) {
aos.writeU30(si.init_index);
aos.writeTraits(si.traits);
if (si.deleted) {
numScripts--;
}
}
aos.writeU30(numScripts);
for (ScriptInfo si : script_info) {
if (!si.deleted) {
aos.writeU30(si.init_index);
aos.writeTraits(si.traits);
}
}
aos.writeU30(bodies.size());
@@ -964,7 +996,9 @@ public class ABC {
public List<ScriptPack> getScriptPacks(String packagePrefix, List<ABC> allAbcs) {
List<ScriptPack> ret = new ArrayList<>();
for (int i = 0; i < script_info.size(); i++) {
ret.addAll(script_info.get(i).getPacks(this, i, packagePrefix, allAbcs));
if (!script_info.get(i).deleted) {
ret.addAll(script_info.get(i).getPacks(this, i, packagePrefix, allAbcs));
}
}
return ret;
}
@@ -1328,67 +1362,81 @@ public class ABC {
}
public boolean replaceScriptPack(ScriptPack pack, String as) throws AVM2ParseException, CompilationException, IOException, InterruptedException {
String scriptName = pack.getPathScriptName() + ".as";
int oldIndex = pack.scriptIndex;
int newIndex = script_info.size();
String documentClass = getSwf().getDocumentClass();
boolean isDocumentClass = documentClass != null && documentClass.equals(pack.getClassPath().toString());
final boolean USE_FLEX = true;
boolean isSimple = pack.isSimple;
ScriptInfo si = script_info.get(oldIndex);
if (isSimple) {
si.delete(this, true);
if (USE_FLEX) {
if (!pack.isSimple) {
return false;
}
As3ScriptReplacer asr = new As3ScriptReplacer(Configuration.flexSdkLocation.get(), new LinkReportExporter());
try {
asr.replaceScript(pack.getSwf(), pack, as);
} catch (MxmlcException ex) {
throw new AVM2ParseException(ex.getMxmlcErrorOutput(), 0);
}
} else {
String scriptName = pack.getPathScriptName() + ".as";
int oldIndex = pack.scriptIndex;
int newIndex = script_info.size();
String documentClass = getSwf().getDocumentClass();
boolean isDocumentClass = documentClass != null && documentClass.equals(pack.getClassPath().toString());
ScriptInfo si = script_info.get(oldIndex);
if (isSimple) {
si.delete(this, true);
} else {
for (int t : pack.traitIndices) {
si.traits.traits.get(t).delete(this, true);
}
}
int newClassIndex = instance_info.size();
for (int t : pack.traitIndices) {
si.traits.traits.get(t).delete(this, true);
if (si.traits.traits.get(t) instanceof TraitClass) {
TraitClass tc = (TraitClass) si.traits.traits.get(t);
newClassIndex = tc.class_info + 1;
}
}
}
List<ABC> otherAbcs = new ArrayList<>(pack.allABCs);
otherAbcs.remove(this);
ActionScript3Parser.compile(as, this, otherAbcs, isDocumentClass, scriptName, newClassIndex, oldIndex);
int newClassIndex = instance_info.size();
for (int t : pack.traitIndices) {
if (si.traits.traits.get(t) instanceof TraitClass) {
TraitClass tc = (TraitClass) si.traits.traits.get(t);
newClassIndex = tc.class_info + 1;
if (isSimple) {
// Move newly added script to its position
script_info.set(oldIndex, script_info.get(newIndex));
script_info.remove(newIndex);
} else {
script_info.get(newIndex).setModified(true);
//Note: Is deleting traits safe?
List<Integer> todel = new ArrayList<>(new TreeSet<>(pack.traitIndices));
for (int i = todel.size() - 1; i >= 0; i--) {
si.traits.traits.remove((int) todel.get(i));
}
}
script_info.get(oldIndex).setModified(true);
}
List<ABC> otherAbcs = new ArrayList<>(pack.allABCs);
otherAbcs.remove(this);
ActionScript3Parser.compile(as, this, otherAbcs, isDocumentClass, scriptName, newClassIndex, oldIndex);
if (isSimple) {
// Move newly added script to its position
script_info.set(oldIndex, script_info.get(newIndex));
script_info.remove(newIndex);
} else {
script_info.get(newIndex).setModified(true);
//Note: Is deleting traits safe?
List<Integer> todel = new ArrayList<>(new TreeSet<>(pack.traitIndices));
for (int i = todel.size() - 1; i >= 0; i--) {
si.traits.traits.remove((int) todel.get(i));
}
}
script_info.get(oldIndex).setModified(true);
pack(); // removes old classes/methods
((Tag) parentTag).setModified(true);
return !isSimple;
}
public void pack() {
for (int c = 0; c < instance_info.size(); c++) {
if (instance_info.get(c).deleted) {
removeClass(c);
c--;
}
}
for (int m = 0; m < method_info.size(); m++) {
if (method_info.get(m).deleted) {
removeMethod(m);
m--;
}
}
for (int c = 0; c < instance_info.size(); c++) {
if (instance_info.get(c).deleted) {
removeClass(c);
c--;
}
}
getMethodIndexing();
}
@@ -42,7 +42,9 @@ 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.exporters.script.Dependency;
import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
import com.jpexs.decompiler.flash.exporters.script.DependencyType;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
@@ -174,14 +176,14 @@ public abstract class Trait implements Cloneable, Serializable {
return getName(abc).getNamespace(abc.constants).getName(abc.constants);
}
public void getImportsUsages(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
public void getDependencies(String ignoredCustom, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
if (ignoredCustom == null) {
Namespace n = getName(abc).getNamespace(abc.constants);
if (n.kind == Namespace.KIND_NAMESPACE) {
ignoredCustom = n.getName(abc.constants).toRawString();
}
}
ImportsUsagesParser.parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, getName(abc), ignorePackage, fullyQualifiedNames);
DependencyParser.parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, 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"};
@@ -210,14 +212,21 @@ public abstract class Trait implements Cloneable, Serializable {
}
//imports
List<DottedChain> imports = new ArrayList<>();
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();
}
getImportsUsages(customNs, abc, imports, uses, ignorePackage, new ArrayList<>());
getDependencies(customNs, abc, dependencies, uses, ignorePackage, new ArrayList<>());
List<DottedChain> imports = new ArrayList<>();
for (Dependency d : dependencies) {
if (!imports.contains(d.getId())) {
imports.add(d.getId());
}
}
List<String> importnames = new ArrayList<>();
importnames.addAll(namesInThisPackage);
@@ -25,7 +25,9 @@ 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.exporters.script.Dependency;
import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
import com.jpexs.decompiler.flash.exporters.script.DependencyType;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.graph.DottedChain;
@@ -49,22 +51,7 @@ public class TraitClass extends Trait implements TraitWithSlot {
@Override
public void delete(ABC abc, boolean d) {
ClassInfo classInfo = abc.class_info.get(class_info);
classInfo.deleted = d;
InstanceInfo instanceInfo = abc.instance_info.get(class_info);
instanceInfo.deleted = d;
classInfo.static_traits.delete(abc, d);
abc.method_info.get(classInfo.cinit_index).delete(abc, d);
instanceInfo.instance_traits.delete(abc, d);
abc.method_info.get(instanceInfo.iinit_index).delete(abc, d);
int protectedNS = instanceInfo.protectedNS;
if (protectedNS != 0) {
abc.constants.getNamespace(protectedNS).deleted = d;
}
abc.deleteClass(class_info, d);
abc.constants.getMultiname(name_index).deleted = d;
}
@@ -79,32 +66,31 @@ public class TraitClass extends Trait implements TraitWithSlot {
}
@Override
public void getImportsUsages(String customNs, ABC abc, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
super.getImportsUsages(customNs, abc, imports, uses, ignorePackage == null ? getPackage(abc) : ignorePackage, fullyQualifiedNames);
public void getDependencies(String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
super.getDependencies(customNs, abc, dependencies, uses, 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
ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames);
//DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames);
if (instanceInfo.super_index > 0) {
ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames);
DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames, DependencyType.INHERITANCE);
}
for (int i : instanceInfo.interfaces) {
ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames);
DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames, DependencyType.INHERITANCE);
}
//static
classInfo.static_traits.getImportsUsages(customNs, abc, imports, uses, packageName, fullyQualifiedNames);
classInfo.static_traits.getDependencies(customNs, abc, dependencies, uses, packageName, fullyQualifiedNames);
//static initializer
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, classInfo.cinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
DependencyParser.parseDependenciesFromMethodInfo(customNs, abc, classInfo.cinit_index, dependencies, uses, packageName, fullyQualifiedNames, new ArrayList<>());
//instance
instanceInfo.instance_traits.getImportsUsages(customNs, abc, imports, uses, packageName, fullyQualifiedNames);
instanceInfo.instance_traits.getDependencies(customNs, abc, dependencies, uses, packageName, fullyQualifiedNames);
//instance initializer
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
DependencyParser.parseDependenciesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, dependencies, uses, packageName, fullyQualifiedNames, new ArrayList<>());
}
@Override
@@ -20,7 +20,8 @@ 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.exporters.script.Dependency;
import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
@@ -124,14 +125,14 @@ public class TraitFunction extends Trait implements TraitWithSlot {
}
@Override
public void getImportsUsages(String customNs, ABC abc, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
public void getDependencies(String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
if (ignorePackage == null) {
ignorePackage = getPackage(abc);
}
super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
super.getDependencies(customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
//if (method_info != 0)
{
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
DependencyParser.parseDependenciesFromMethodInfo(customNs, abc, method_info, dependencies, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
}
}
}
@@ -23,7 +23,8 @@ 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.exporters.script.Dependency;
import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
@@ -59,11 +60,11 @@ public class TraitMethodGetterSetter extends Trait {
}
@Override
public void getImportsUsages(String customNs, ABC abc, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
public void getDependencies(String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
if (ignorePackage == null) {
ignorePackage = getPackage(abc);
}
super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
super.getDependencies(customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
if (customNs == null) {
Namespace n = getName(abc).getNamespace(abc.constants);
@@ -73,7 +74,7 @@ public class TraitMethodGetterSetter extends Trait {
}
//if (method_info != 0)
{
ImportsUsagesParser.parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
DependencyParser.parseDependenciesFromMethodInfo(customNs, abc, method_info, dependencies, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
}
}
@@ -26,7 +26,9 @@ 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.exporters.script.Dependency;
import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
import com.jpexs.decompiler.flash.exporters.script.DependencyType;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
@@ -197,12 +199,12 @@ public class TraitSlotConst extends Trait implements TraitWithSlot {
}
@Override
public void getImportsUsages(String customNs, ABC abc, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
public void getDependencies(String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
if (ignorePackage == null) {
ignorePackage = getPackage(abc);
}
super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
ImportsUsagesParser.parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames);
super.getDependencies(customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames, DependencyType.SIGNATURE);
}
@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.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.Dependency;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.graph.DottedChain;
@@ -244,9 +245,9 @@ public class Traits implements Cloneable, Serializable {
}
}
public void getImportsUsages(String customNs, ABC abc, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
public void getDependencies(String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
for (Trait t : traits) {
t.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
t.getDependencies(customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
}
}
}