Added AS3 P-code editing class trait

This commit is contained in:
Jindra Petřík
2023-03-05 21:20:41 +01:00
parent b762bebe70
commit 045d475647
21 changed files with 2067 additions and 1508 deletions

View File

@@ -247,9 +247,9 @@ public class ScriptPack extends AS3ClassTreeItem {
Trait trait = traits.get(t);
if (!(trait instanceof TraitClass)) {
//if (!(trait instanceof TraitClass)) {
writer.startTrait(t);
}
//}
Multiname name = trait.getName(abc);
Namespace ns = name.getNamespace(abc.constants);
if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) {
@@ -257,7 +257,8 @@ public class ScriptPack extends AS3ClassTreeItem {
} else {
trait.toString(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false);
}
if (!(trait instanceof TraitClass)) {
if (!(trait instanceof TraitClass))
{
writer.endTrait();
}
first = false;

View File

@@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushShortIns;
import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.abc.types.Float4;
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
import com.jpexs.decompiler.flash.abc.types.MetadataInfo;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
@@ -35,6 +36,7 @@ import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
import com.jpexs.decompiler.flash.abc.types.ValueKind;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
@@ -111,6 +113,14 @@ public class ASM3Parser {
}
return index;
}
private static void expectEnd(Flasm3Lexer lexer) throws IOException, AVM2ParseException {
expected(ParsedSymbol.TYPE_KEYWORD_END, "end", lexer);
ParsedSymbol symb = lexer.lex();
if (symb.type != ParsedSymbol.TYPE_COMMENT) {
lexer.pushback(symb);
}
}
private static void expected(int type, String expStr, Flasm3Lexer lexer) throws IOException, AVM2ParseException {
ParsedSymbol s = lexer.lex();
@@ -238,6 +248,86 @@ public class ASM3Parser {
return true;
}
public static boolean parseClass(ABC abc, Reader reader, AVM2ConstantPool constants, TraitClass tc) throws IOException, AVM2ParseException {
Flasm3Lexer lexer = new Flasm3Lexer(reader);
return parseClass(abc, lexer, constants, tc);
}
private static boolean parseClass(ABC abc, Flasm3Lexer lexer, AVM2ConstantPool constants, TraitClass tc) throws IOException, AVM2ParseException {
expected(ParsedSymbol.TYPE_KEYWORD_TRAIT, "trait", lexer);
expected(ParsedSymbol.TYPE_KEYWORD_CLASS, "class", lexer);
int name_index = parseMultiName(constants, lexer);
parseTraitParams(abc, lexer, tc);
expected(ParsedSymbol.TYPE_KEYWORD_SLOTID, "slotid", lexer);
ParsedSymbol symb;
symb = lexer.lex();
expected(symb, ParsedSymbol.TYPE_INTEGER, "Integer");
int slotid = (int) (Integer) symb.value;
expected(ParsedSymbol.TYPE_KEYWORD_CLASS, "class", lexer);
expected(ParsedSymbol.TYPE_KEYWORD_INSTANCE, "instance", lexer);
int instance_name_index = parseMultiName(constants, lexer);
expected(ParsedSymbol.TYPE_KEYWORD_EXTENDS, "extends", lexer);
int super_index = parseMultiName(constants, lexer);
symb = lexer.lex();
List<Integer> ifacesList = new ArrayList<>();
while (symb.type == ParsedSymbol.TYPE_KEYWORD_IMPLEMENTS) {
ifacesList.add(parseMultiName(constants, lexer));
symb = lexer.lex();
}
int interfaces[] = new int[ifacesList.size()];
for(int i = 0; i < ifacesList.size(); i++) {
interfaces[i] = ifacesList.get(i);
}
int instanceFlags = 0;
while (symb.type == ParsedSymbol.TYPE_KEYWORD_FLAG) {
symb = lexer.lex();
switch (symb.type) {
case ParsedSymbol.TYPE_KEYWORD_SEALED:
instanceFlags |= InstanceInfo.CLASS_SEALED;
break;
case ParsedSymbol.TYPE_KEYWORD_FINAL:
instanceFlags |= InstanceInfo.CLASS_FINAL;
break;
case ParsedSymbol.TYPE_KEYWORD_INTERFACE:
instanceFlags |= InstanceInfo.CLASS_INTERFACE;
break;
case ParsedSymbol.TYPE_KEYWORD_PROTECTEDNS:
instanceFlags |= InstanceInfo.CLASS_PROTECTEDNS;
break;
case ParsedSymbol.TYPE_KEYWORD_NON_NULLABLE:
instanceFlags |= InstanceInfo.CLASS_NON_NULLABLE;
break;
default:
throw new AVM2ParseException("SEALED,FINAL,INTERFACE,PROTECTEDNS or NON_NULLABLE expected", lexer.yyline());
}
symb = lexer.lex();
}
int protectedns = 0;
if (symb.type == ParsedSymbol.TYPE_KEYWORD_PROTECTEDNS_BLOCK && ((instanceFlags & InstanceInfo.CLASS_PROTECTEDNS)==InstanceInfo.CLASS_PROTECTEDNS)) {
protectedns = parseNamespace(constants, lexer);
} else {
lexer.pushback(symb);
}
expectEnd(lexer); //instance
expectEnd(lexer); //class
expectEnd(lexer); //trait
InstanceInfo ii = abc.instance_info.get(tc.class_info);
ii.name_index = instance_name_index;
ii.super_index = super_index;
ii.interfaces = interfaces;
ii.flags = instanceFlags;
if ((instanceFlags & InstanceInfo.CLASS_PROTECTEDNS)==InstanceInfo.CLASS_PROTECTEDNS) {
ii.protectedNS = protectedns;
}
tc.slot_id = slotid;
return true;
}
public static boolean parseSlotConst(ABC abc, Reader reader, AVM2ConstantPool constants, TraitSlotConst tsc) throws IOException, AVM2ParseException {
Flasm3Lexer lexer = new Flasm3Lexer(reader);
return parseSlotConst(abc, lexer, constants, tsc);
@@ -961,7 +1051,7 @@ public class ASM3Parser {
lexer.pushback(parsedOperand);
operandsList.add(parseNamespace(constants, lexer));
break;
case AVM2Code.DAT_STRING_INDEX:
case AVM2Code.DAT_STRING_INDEX:
if (parsedOperand.type == ParsedSymbol.TYPE_KEYWORD_NULL) {
operandsList.add(0);
} else if (parsedOperand.type == ParsedSymbol.TYPE_STRING) {

View File

@@ -201,6 +201,23 @@ public class ParsedSymbol {
public static final int TYPE_KEYWORD_END = 88;
public static final int TYPE_KEYWORD_UNKNOWN = 89;
public static final int TYPE_KEYWORD_SEALED = 90;
public static final int TYPE_KEYWORD_INTERFACE = 91;
public static final int TYPE_KEYWORD_PROTECTEDNS = 92;
public static final int TYPE_KEYWORD_NON_NULLABLE = 93;
public static final int TYPE_KEYWORD_INSTANCE = 94;
public static final int TYPE_KEYWORD_EXTENDS = 95;
public static final int TYPE_KEYWORD_IMPLEMENTS = 96;
public static final int TYPE_KEYWORD_PROTECTEDNS_BLOCK = 97;
public ParsedSymbol(int type, Object value) {
this.type = type;

View File

@@ -130,12 +130,13 @@ public class TraitClass extends Trait implements TraitWithSlot {
String instanceInfoName = instanceInfoMultiname.getName(abc.constants, fullyQualifiedNames, false, true);
writer.startClass(class_info);
getMetaData(parent, convertData, abc, writer);
//class header
instanceInfo.getClassHeaderStr(writer, abc, fullyQualifiedNames, false);
writer.endTrait();
writer.startBlock();
writer.startClass(class_info);
//static variables & constants
ClassInfo classInfo = abc.class_info.get(class_info);
@@ -206,8 +207,8 @@ public class TraitClass extends Trait implements TraitWithSlot {
//instance methods
instanceInfo.instance_traits.toString(abcIndex, new Class[]{TraitClass.class, TraitFunction.class, TraitMethodGetterSetter.class}, this, convertData, path +/*packageName +*/ "/" + instanceInfoName, abc, false, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel, convertData.ignoreFrameScripts ? frameTraitNames : new ArrayList<>(), isInterface);
writer.endClass();
writer.endBlock(); // class
writer.endClass();
writer.newLine();
return writer;
}
@@ -343,12 +344,41 @@ public class TraitClass extends Trait implements TraitWithSlot {
@Override
public GraphTextWriter convertTraitHeader(ABC abc, GraphTextWriter writer) {
convertCommonHeaderFlags("class", abc, writer);
writer.appendNoHilight(" slotid ");
writer.newLine();
writer.appendNoHilight("slotid ");
writer.hilightSpecial(Integer.toString(slot_id), HighlightSpecialType.SLOT_ID);
writer.newLine();
/*writer.appendNoHilight("class_info "); //not in RAbcDasm
writer.appendNoHilight("" + class_info);
writer.newLine();*/
writer.appendNoHilight("class").newLine();
writer.indent();
InstanceInfo ii = abc.instance_info.get(class_info);
writer.appendNoHilight("instance ").hilightSpecial(abc.constants.multinameToString(ii.name_index), HighlightSpecialType.INSTANCE_NAME).newLine();
writer.indent();
writer.appendNoHilight("extends ").hilightSpecial(abc.constants.multinameToString(ii.super_index), HighlightSpecialType.EXTENDS).newLine();
for(int iface : ii.interfaces) {
writer.appendNoHilight("implements ").hilightSpecial(abc.constants.multinameToString(iface), HighlightSpecialType.IMPLEMENTS).newLine();
}
if ((ii.flags & InstanceInfo.CLASS_SEALED) == InstanceInfo.CLASS_SEALED) {
writer.appendNoHilight("flag SEALED").newLine();
}
if ((ii.flags & InstanceInfo.CLASS_FINAL) == InstanceInfo.CLASS_FINAL) {
writer.appendNoHilight("flag FINAL").newLine();
}
if ((ii.flags & InstanceInfo.CLASS_INTERFACE) == InstanceInfo.CLASS_INTERFACE) {
writer.appendNoHilight("flag INTERFACE").newLine();
}
if ((ii.flags & InstanceInfo.CLASS_PROTECTEDNS) == InstanceInfo.CLASS_PROTECTEDNS) {
writer.appendNoHilight("flag PROTECTEDNS").newLine();
}
if ((ii.flags & InstanceInfo.CLASS_NON_NULLABLE) == InstanceInfo.CLASS_NON_NULLABLE) {
writer.appendNoHilight("flag NON_NULLABLE").newLine();
}
if ((ii.flags & InstanceInfo.CLASS_PROTECTEDNS) == InstanceInfo.CLASS_PROTECTEDNS) {
writer.appendNoHilight("protectedns ").hilightSpecial(Multiname.namespaceToString(abc.constants, ii.protectedNS), HighlightSpecialType.PROTECTEDNS).newLine();
}
writer.unindent();
writer.appendNoHilight("end ; instance").newLine();
writer.unindent();
writer.appendNoHilight("end ; class").newLine();
return writer;
}

View File

@@ -229,21 +229,21 @@ public class Traits implements Cloneable, Serializable {
}
writer.newLine();
int h = abc.getGlobalTraitId(TraitType.METHOD /*non-initializer*/, isStatic, classIndex, t);
if (trait instanceof TraitClass) {
writer.startClass(((TraitClass) trait).class_info);
} else {
//if (trait instanceof TraitClass) {
// writer.startClass(((TraitClass) trait).class_info);
//} else {
writer.startTrait(h);
}
//}
if (makePackages) {
trait.toStringPackaged(abcIndex, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface);
} else {
trait.toString(abcIndex, parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, insideInterface);
}
if (trait instanceof TraitClass) {
writer.endClass();
} else {
//if (trait instanceof TraitClass) {
// writer.endClass();
//} else {
writer.endTrait();
}
//}
}
return writer;
}

View File

@@ -169,7 +169,6 @@ public class ClassActionItem extends ActionItem implements Block {
makePrintObfuscated(im);
}
writer.startClass(className.toStringNoQuotes(localData));
writer.append("class ");
className.toStringNoQuotes(writer, localData);
if (extendsOp != null) {
@@ -188,6 +187,7 @@ public class ClassActionItem extends ActionItem implements Block {
}
}
writer.startBlock();
writer.startClass(className.toStringNoQuotes(localData));
/*if (constructor != null) {
constructor.toString(writer, localData).newLine();
@@ -232,8 +232,8 @@ public class ClassActionItem extends ActionItem implements Block {
writer.append(v);
writer.append(";").newLine();
}
writer.endBlock();
writer.endClass();
writer.endBlock();
return writer;
}

View File

@@ -48,7 +48,6 @@ public class InterfaceActionItem extends ActionItem {
@Override
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
writer.startClass(name.toStringNoQuotes(localData));
writer.append("interface ");
name.toStringNoQuotes(writer, localData);
boolean first = true;
@@ -62,7 +61,10 @@ public class InterfaceActionItem extends ActionItem {
first = false;
Action.getWithoutGlobal(ti).toStringNoQuotes(writer, localData);
}
return writer.startBlock().endBlock().endClass();
writer.startBlock();
writer.startClass(name.toStringNoQuotes(localData));
writer.endClass();
return writer.endBlock();
}
@Override

View File

@@ -902,6 +902,11 @@ public final class Configuration {
@ConfigurationCategory("ui")
public static ConfigurationItem<Boolean> rememberFoldersScrollPos = null;
@ConfigurationDefaultBoolean(true)
@ConfigurationName("warning.initializers.class")
@ConfigurationCategory("script")
public static ConfigurationItem<Boolean> warningInitializersClass = null;
private enum OSId {
WINDOWS, OSX, UNIX

View File

@@ -31,5 +31,5 @@ public enum HighlightSpecialType {
TRY_TYPE, TRY_NAME,
TEXT,
ATTR_METADATA, ATTR_FINAL, ATTR_OVERRIDE, ATTR_0x8,
PROPERTY_TYPE
PROPERTY_TYPE, INSTANCE_NAME, IMPLEMENTS, EXTENDS, PROTECTEDNS
}