mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-15 14:50:19 +00:00
AS3 p-code editing - metadata read/write support
This commit is contained in:
@@ -68,6 +68,7 @@ import com.jpexs.helpers.utf8.Utf8PrintWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -157,6 +158,29 @@ public class ABC {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets id of metadata/add metadata
|
||||
*
|
||||
* @param newMetadata
|
||||
* @param add Add if not found?
|
||||
* @return New index or -1 if not found (add=false)
|
||||
*/
|
||||
public int getMetadataId(MetadataInfo newMetadata, boolean add) {
|
||||
for (int m = 0; m < metadata_info.size(); m++) {
|
||||
MetadataInfo metadata = metadata_info.get(m);
|
||||
if (metadata.name_index == newMetadata.name_index && Arrays.equals(metadata.keys, newMetadata.keys) && Arrays.equals(metadata.values, newMetadata.values)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
if (add) {
|
||||
int newIndex = metadata_info.size();
|
||||
metadata_info.add(newMetadata);
|
||||
((Tag) parentTag).setModified(true);
|
||||
return newIndex;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public TraitMethodGetterSetter addMethod(int classId, String name, boolean isStatic) {
|
||||
Multiname multiname = new Multiname();
|
||||
multiname.kind = Multiname.QNAME;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2.parser.pcode;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
@@ -26,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.MetadataInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodBody;
|
||||
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
|
||||
import com.jpexs.decompiler.flash.abc.types.Multiname;
|
||||
@@ -40,10 +42,13 @@ import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -85,8 +90,8 @@ public class ASM3Parser {
|
||||
}
|
||||
}
|
||||
|
||||
public static AVM2Code parse(Reader reader, AVM2ConstantPool constants, Trait trait, MethodBody body, MethodInfo info) throws IOException, AVM2ParseException, InterruptedException {
|
||||
return parse(reader, constants, trait, null, body, info);
|
||||
public static AVM2Code parse(ABC abc, Reader reader, Trait trait, MethodBody body, MethodInfo info) throws IOException, AVM2ParseException, InterruptedException {
|
||||
return parse(abc, reader, trait, null, body, info);
|
||||
}
|
||||
|
||||
private static int checkMultinameIndex(AVM2ConstantPool constants, int index, int line) throws AVM2ParseException {
|
||||
@@ -109,60 +114,109 @@ public class ASM3Parser {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean parseSlotConst(Reader reader, AVM2ConstantPool constants, TraitSlotConst tsc) throws IOException, AVM2ParseException {
|
||||
Flasm3Lexer lexer = new Flasm3Lexer(reader);
|
||||
expected(ParsedSymbol.TYPE_KEYWORD_TRAIT, "trait", lexer);
|
||||
int name_index = parseMultiName(constants, lexer);
|
||||
private static void parseTraitParams(ABC abc, Flasm3Lexer lexer, Trait t) throws IOException, AVM2ParseException {
|
||||
ParsedSymbol symb;// = lexer.lex();
|
||||
|
||||
ParsedSymbol symb = lexer.lex();
|
||||
List<Map.Entry<String, Map<String, String>>> metadata = new ArrayList<>();
|
||||
|
||||
int flags = 0;
|
||||
while (symb.type == ParsedSymbol.TYPE_KEYWORD_FLAG) {
|
||||
while (true) {
|
||||
symb = lexer.lex();
|
||||
switch (symb.type) {
|
||||
case ParsedSymbol.TYPE_KEYWORD_FINAL:
|
||||
flags |= Trait.ATTR_Final;
|
||||
break;
|
||||
case ParsedSymbol.TYPE_KEYWORD_OVERRIDE:
|
||||
flags |= Trait.ATTR_Override;
|
||||
break;
|
||||
case ParsedSymbol.TYPE_KEYWORD_METADATA:
|
||||
flags |= Trait.ATTR_Metadata;
|
||||
break;
|
||||
default:
|
||||
throw new AVM2ParseException("Invalid trait flag", lexer.yyline());
|
||||
if (symb.type == ParsedSymbol.TYPE_KEYWORD_FLAG) {
|
||||
symb = lexer.lex();
|
||||
switch (symb.type) {
|
||||
case ParsedSymbol.TYPE_KEYWORD_FINAL:
|
||||
flags |= Trait.ATTR_Final;
|
||||
break;
|
||||
case ParsedSymbol.TYPE_KEYWORD_OVERRIDE:
|
||||
flags |= Trait.ATTR_Override;
|
||||
break;
|
||||
case ParsedSymbol.TYPE_KEYWORD_METADATA:
|
||||
flags |= Trait.ATTR_Metadata;
|
||||
break;
|
||||
default:
|
||||
throw new AVM2ParseException("Invalid trait flag", lexer.yyline());
|
||||
}
|
||||
} else if (symb.type == ParsedSymbol.TYPE_KEYWORD_METADATA_BLOCK) {
|
||||
symb = lexer.lex();
|
||||
expected(symb, ParsedSymbol.TYPE_STRING, "string metadata");
|
||||
String mkey = (String) symb.value;
|
||||
symb = lexer.lex();
|
||||
Map<String, String> items = new HashMap<>();
|
||||
while (symb.type == ParsedSymbol.TYPE_KEYWORD_ITEM) {
|
||||
symb = lexer.lex();
|
||||
expected(symb, ParsedSymbol.TYPE_STRING, "string key");
|
||||
String key = (String) symb.value;
|
||||
symb = lexer.lex();
|
||||
expected(symb, ParsedSymbol.TYPE_STRING, "string value");
|
||||
String val = (String) symb.value;
|
||||
items.put(key, val);
|
||||
symb = lexer.lex();
|
||||
}
|
||||
expected(symb, ParsedSymbol.TYPE_KEYWORD_END, "end");
|
||||
symb = lexer.lex();
|
||||
if (symb.type != ParsedSymbol.TYPE_COMMENT) {
|
||||
lexer.pushback(symb);
|
||||
}
|
||||
metadata.add(new AbstractMap.SimpleEntry<>(mkey, items));
|
||||
} else {
|
||||
lexer.pushback(symb);
|
||||
break;
|
||||
}
|
||||
symb = lexer.lex();
|
||||
}
|
||||
|
||||
switch (symb.type) {
|
||||
case ParsedSymbol.TYPE_KEYWORD_SLOT:
|
||||
case ParsedSymbol.TYPE_KEYWORD_CONST:
|
||||
expected(ParsedSymbol.TYPE_KEYWORD_SLOTID, "slotid", lexer);
|
||||
symb = lexer.lex();
|
||||
expected(symb, ParsedSymbol.TYPE_INTEGER, "Integer");
|
||||
int slotid = (int) (long) (Long) symb.value;
|
||||
expected(ParsedSymbol.TYPE_KEYWORD_TYPE, "type", lexer);
|
||||
int type = parseMultiName(constants, lexer);
|
||||
expected(ParsedSymbol.TYPE_KEYWORD_VALUE, "value", lexer);
|
||||
ValueKind val = parseValue(constants, lexer);
|
||||
tsc.slot_id = slotid;
|
||||
tsc.type_index = type;
|
||||
tsc.value_kind = val.value_kind;
|
||||
tsc.value_index = val.value_index;
|
||||
tsc.kindFlags = flags;
|
||||
break;
|
||||
/*case ParsedSymbol.TYPE_KEYWORD_CLASS:
|
||||
break;
|
||||
case ParsedSymbol.TYPE_KEYWORD_FUNCTION:
|
||||
break;
|
||||
case ParsedSymbol.TYPE_KEYWORD_METHOD:
|
||||
case ParsedSymbol.TYPE_KEYWORD_GETTER:
|
||||
case ParsedSymbol.TYPE_KEYWORD_SETTER:
|
||||
break;*/
|
||||
default:
|
||||
throw new AVM2ParseException("Unexpected trait type", lexer.yyline());
|
||||
t.kindFlags = flags;
|
||||
if ((flags & Trait.ATTR_Metadata) > 0) {
|
||||
int metadataArray[] = new int[metadata.size()];
|
||||
for (int i = 0; i < metadata.size(); i++) {
|
||||
Map.Entry<String, Map<String, String>> entry = metadata.get(i);
|
||||
int mkey = abc.constants.getStringId(entry.getKey(), true);
|
||||
Map<String, String> items = entry.getValue();
|
||||
int keys[] = new int[items.size()];
|
||||
int vals[] = new int[items.size()];
|
||||
|
||||
int pos = 0;
|
||||
for (String key : items.keySet()) {
|
||||
int ikey = abc.constants.getStringId(key, true);
|
||||
int ival = abc.constants.getStringId(items.get(key), true);
|
||||
keys[pos] = ikey;
|
||||
vals[pos] = ival;
|
||||
pos++;
|
||||
}
|
||||
MetadataInfo mi = new MetadataInfo(mkey, keys, vals);
|
||||
metadataArray[i] = abc.getMetadataId(mi, true);
|
||||
}
|
||||
t.metadata = metadataArray;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static boolean parseSlotConst(ABC abc, Reader reader, AVM2ConstantPool constants, TraitSlotConst tsc) throws IOException, AVM2ParseException {
|
||||
Flasm3Lexer lexer = new Flasm3Lexer(reader);
|
||||
expected(ParsedSymbol.TYPE_KEYWORD_TRAIT, "trait", lexer);
|
||||
ParsedSymbol symb = lexer.lex();
|
||||
if (symb.type == ParsedSymbol.TYPE_KEYWORD_SLOT) {
|
||||
tsc.kindType = Trait.TRAIT_SLOT;
|
||||
} else if (symb.type == ParsedSymbol.TYPE_KEYWORD_CONST) {
|
||||
tsc.kindType = Trait.TRAIT_CONST;
|
||||
} else {
|
||||
throw new AVM2ParseException("slot or const expected", lexer.yyline());
|
||||
}
|
||||
int name_index = parseMultiName(constants, lexer);
|
||||
parseTraitParams(abc, lexer, tsc);
|
||||
|
||||
expected(ParsedSymbol.TYPE_KEYWORD_SLOTID, "slotid", lexer);
|
||||
symb = lexer.lex();
|
||||
expected(symb, ParsedSymbol.TYPE_INTEGER, "Integer");
|
||||
int slotid = (int) (long) (Long) symb.value;
|
||||
expected(ParsedSymbol.TYPE_KEYWORD_TYPE, "type", lexer);
|
||||
int type = parseMultiName(constants, lexer);
|
||||
expected(ParsedSymbol.TYPE_KEYWORD_VALUE, "value", lexer);
|
||||
ValueKind val = parseValue(constants, lexer);
|
||||
tsc.slot_id = slotid;
|
||||
tsc.type_index = type;
|
||||
tsc.value_kind = val.value_kind;
|
||||
tsc.value_index = val.value_index;
|
||||
tsc.name_index = name_index;
|
||||
return true;
|
||||
}
|
||||
@@ -515,7 +569,8 @@ public class ASM3Parser {
|
||||
return new ValueKind(value_index, value_kind);
|
||||
}
|
||||
|
||||
public static AVM2Code parse(Reader reader, AVM2ConstantPool constants, Trait trait, MissingSymbolHandler missingHandler, MethodBody body, MethodInfo info) throws IOException, AVM2ParseException, InterruptedException {
|
||||
public static AVM2Code parse(ABC abc, Reader reader, Trait trait, MissingSymbolHandler missingHandler, MethodBody body, MethodInfo info) throws IOException, AVM2ParseException, InterruptedException {
|
||||
AVM2ConstantPool constants = abc.constants;
|
||||
AVM2Code code = new AVM2Code();
|
||||
|
||||
List<OffsetItem> offsetItems = new ArrayList<>();
|
||||
@@ -566,6 +621,7 @@ public class ASM3Parser {
|
||||
break;
|
||||
}
|
||||
tm.name_index = parseMultiName(constants, lexer);
|
||||
parseTraitParams(abc, lexer, trait);
|
||||
expected(ParsedSymbol.TYPE_KEYWORD_DISPID, "dispid", lexer);
|
||||
symb = lexer.lex();
|
||||
expected(symb, ParsedSymbol.TYPE_INTEGER, "Integer");
|
||||
@@ -576,6 +632,9 @@ public class ASM3Parser {
|
||||
if (!(trait instanceof TraitFunction)) {
|
||||
throw new AVM2ParseException("Unxpected trait type", lexer.yyline());
|
||||
}
|
||||
|
||||
//NAME
|
||||
parseTraitParams(abc, lexer, trait);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -196,6 +196,10 @@ public class ParsedSymbol {
|
||||
|
||||
public static final int TYPE_KEYWORD_OVERRIDE = 85;
|
||||
|
||||
public static final int TYPE_KEYWORD_METADATA_BLOCK = 86;
|
||||
public static final int TYPE_KEYWORD_ITEM = 87;
|
||||
public static final int TYPE_KEYWORD_END = 88;
|
||||
|
||||
public ParsedSymbol(int type, Object value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
|
||||
@@ -33,6 +33,7 @@ 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;
|
||||
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.helpers.Helper;
|
||||
@@ -76,6 +77,8 @@ public abstract class Trait implements Cloneable, Serializable {
|
||||
|
||||
public static final int ATTR_Metadata = 0x4;
|
||||
|
||||
public static final int ATTR_0x8 = 0x8; //unknown
|
||||
|
||||
public static final int TRAIT_SLOT = 0;
|
||||
|
||||
public static final int TRAIT_METHOD = 1;
|
||||
@@ -381,6 +384,62 @@ public abstract class Trait implements Cloneable, Serializable {
|
||||
public void convert(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 {
|
||||
}
|
||||
|
||||
public abstract GraphTextWriter convertTraitHeader(ABC abc, GraphTextWriter writer);
|
||||
|
||||
public GraphTextWriter convertCommonHeaderFlags(String traitType, ABC abc, GraphTextWriter writer) {
|
||||
writer.appendNoHilight("trait ");
|
||||
writer.hilightSpecial(traitType, HighlightSpecialType.TRAIT_TYPE);
|
||||
writer.appendNoHilight(" ");
|
||||
writer.hilightSpecial(abc.constants.multinameToString(name_index), HighlightSpecialType.TRAIT_NAME);
|
||||
|
||||
if ((kindFlags & ATTR_Final) > 0) {
|
||||
writer.append(" flag ");
|
||||
writer.hilightSpecial("FINAL", HighlightSpecialType.ATTR_FINAL);
|
||||
}
|
||||
if ((kindFlags & ATTR_Override) > 0) {
|
||||
writer.append(" flag ");
|
||||
writer.hilightSpecial("OVERRIDE", HighlightSpecialType.ATTR_OVERRIDE);
|
||||
}
|
||||
if ((kindFlags & ATTR_Metadata) > 0) {
|
||||
writer.append(" flag ");
|
||||
writer.hilightSpecial("METADATA", HighlightSpecialType.ATTR_METADATA);
|
||||
}
|
||||
if ((kindFlags & ATTR_0x8) > 0) {
|
||||
writer.append(" flag ");
|
||||
writer.hilightSpecial("0x8", HighlightSpecialType.ATTR_0x8);
|
||||
}
|
||||
if ((kindFlags & ATTR_Metadata) > 0) {
|
||||
writer.newLine();
|
||||
for (int m : metadata) {
|
||||
writer.append("metadata");
|
||||
writer.append("\"");
|
||||
writer.append(Helper.escapeActionScriptString(abc.constants.getString(abc.metadata_info.get(m).name_index)));
|
||||
writer.append("\"");
|
||||
writer.newLine();
|
||||
if (m >= 0 && m < abc.metadata_info.size()) {
|
||||
for (int i = 0; i < abc.metadata_info.get(m).keys.length; i++) {
|
||||
int key = abc.metadata_info.get(m).keys[i];
|
||||
int val = abc.metadata_info.get(m).values[i];
|
||||
writer.append("item ");
|
||||
|
||||
writer.append("\"");
|
||||
writer.append(Helper.escapeActionScriptString(abc.constants.getString(key)));
|
||||
writer.append("\"");
|
||||
|
||||
writer.append(" ");
|
||||
|
||||
writer.append("\"");
|
||||
writer.append(Helper.escapeActionScriptString(abc.constants.getString(val)));
|
||||
writer.append("\"");
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
writer.append("end ;metadata");
|
||||
}
|
||||
}
|
||||
return writer;
|
||||
}
|
||||
|
||||
public GraphTextWriter toStringPackaged(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 {
|
||||
Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants);
|
||||
if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) {
|
||||
|
||||
@@ -30,6 +30,7 @@ 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;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.decompiler.graph.ScopeStack;
|
||||
import com.jpexs.decompiler.graph.TypeItem;
|
||||
@@ -265,4 +266,13 @@ public class TraitClass extends Trait implements TraitWithSlot {
|
||||
TraitClass ret = (TraitClass) super.clone();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter convertTraitHeader(ABC abc, GraphTextWriter writer) {
|
||||
convertCommonHeaderFlags("class", abc, writer);
|
||||
writer.appendNoHilight(" slotid ");
|
||||
writer.hilightSpecial(Integer.toString(slot_id), HighlightSpecialType.SLOT_ID);
|
||||
writer.newLine();
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,4 +135,13 @@ public class TraitFunction extends Trait implements TraitWithSlot {
|
||||
DependencyParser.parseDependenciesFromMethodInfo(customNs, abc, method_info, dependencies, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter convertTraitHeader(ABC abc, GraphTextWriter writer) {
|
||||
convertCommonHeaderFlags("function", abc, writer);
|
||||
writer.newLine();
|
||||
writer.appendNoHilight("slotid ");
|
||||
writer.hilightSpecial(Integer.toString(slot_id), HighlightSpecialType.SLOT_ID);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +138,9 @@ public class TraitMethodGetterSetter extends Trait {
|
||||
} else {
|
||||
writer.startBlock();
|
||||
if (exportMode != ScriptExportMode.AS_METHOD_STUBS) {
|
||||
if (exportMode != ScriptExportMode.AS) {
|
||||
convertTraitHeader(abc, writer);
|
||||
}
|
||||
if (bodyIndex != -1) {
|
||||
abc.bodies.get(bodyIndex).toString(path, exportMode, abc, this, writer, fullyQualifiedNames);
|
||||
}
|
||||
@@ -202,4 +205,24 @@ public class TraitMethodGetterSetter extends Trait {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter convertTraitHeader(ABC abc, GraphTextWriter writer) {
|
||||
|
||||
switch (kindType) {
|
||||
case Trait.TRAIT_METHOD:
|
||||
convertCommonHeaderFlags("method", abc, writer);
|
||||
break;
|
||||
case Trait.TRAIT_GETTER:
|
||||
convertCommonHeaderFlags("getter", abc, writer);
|
||||
break;
|
||||
case Trait.TRAIT_SETTER:
|
||||
convertCommonHeaderFlags("setter", abc, writer);
|
||||
break;
|
||||
}
|
||||
writer.newLine();
|
||||
writer.appendNoHilight("dispid ");
|
||||
writer.hilightSpecial("" + disp_id, HighlightSpecialType.DISP_ID);
|
||||
writer.newLine();
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,4 +228,19 @@ public class TraitSlotConst extends Trait implements TraitWithSlot {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter convertTraitHeader(ABC abc, GraphTextWriter writer) {
|
||||
convertCommonHeaderFlags(isConst() ? "const" : "slot", abc, writer);
|
||||
writer.newLine();
|
||||
writer.appendNoHilight("slotid ");
|
||||
writer.hilightSpecial(Integer.toString(slot_id), HighlightSpecialType.SLOT_ID);
|
||||
writer.appendNoHilight(" type ");
|
||||
writer.hilightSpecial(abc.constants.multinameToString(type_index), HighlightSpecialType.TRAIT_TYPE_NAME);
|
||||
writer.appendNoHilight(" value ");
|
||||
writer.hilightSpecial((new ValueKind(value_index, value_kind).toASMString(abc.constants)), HighlightSpecialType.TRAIT_VALUE);
|
||||
writer.newLine();
|
||||
return writer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,5 +29,6 @@ public enum HighlightSpecialType {
|
||||
FLAG_NEED_REST, FLAG_EXPLICIT, FLAG_HAS_OPTIONAL, FLAG_HAS_PARAM_NAMES,
|
||||
FLAG_IGNORE_REST, FLAG_NEED_ACTIVATION, FLAG_NEED_ARGUMENTS, FLAG_SET_DXNS,
|
||||
TRY_TYPE, TRY_NAME,
|
||||
TEXT
|
||||
TEXT,
|
||||
ATTR_METADATA, ATTR_FINAL, ATTR_OVERRIDE, ATTR_0x8
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user