From 575239be5c92215559889d2fdcb903a441f45db6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Fri, 29 Sep 2023 14:34:53 +0200 Subject: [PATCH] ABC Explorer - methodinfo --- .../flash/abc/types/MethodInfo.java | 2 - .../flash/gui/abc/ABCExplorerDialog.java | 658 ++++++++++++++---- 2 files changed, 510 insertions(+), 150 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java index 68852ab79..57d8e560d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java @@ -19,8 +19,6 @@ package com.jpexs.decompiler.flash.abc.types; import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCExplorerDialog.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCExplorerDialog.java index 215071674..2b48aa0ff 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCExplorerDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCExplorerDialog.java @@ -19,13 +19,17 @@ package com.jpexs.decompiler.flash.gui.abc; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.Float4; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.abc.types.Multiname; 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.ecma.EcmaScript; import com.jpexs.decompiler.flash.gui.AppDialog; import com.jpexs.decompiler.flash.gui.FasterScrollPane; import com.jpexs.decompiler.flash.gui.View; +import com.jpexs.decompiler.flash.helpers.CodeFormatting; +import com.jpexs.decompiler.flash.helpers.StringBuilderTextWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.DoABC2Tag; import com.jpexs.decompiler.flash.tags.ShowFrameTag; @@ -62,14 +66,14 @@ import javax.swing.tree.TreePath; * @author JPEXS */ public class ABCExplorerDialog extends AppDialog { - + private final List abcContainers = new ArrayList<>(); private final JComboBox abcComboBox; private final JLabel tagInfoLabel; private final List abcFrames = new ArrayList<>(); - private final JTabbedPane mainTabbedPane; + private final JTabbedPane mainTabbedPane; private final JTabbedPane cpTabbedPane; - + public ABCExplorerDialog(Window owner, SWF swf, ABC abc) { super(owner); Container cnt = getContentPane(); @@ -82,15 +86,15 @@ public class ABCExplorerDialog extends AppDialog { frame++; } if (t instanceof ABCContainerTag) { - abcContainers.add((ABCContainerTag)t); + abcContainers.add((ABCContainerTag) t); abcFrames.add(frame); } } String[] abcComboBoxData = new String[abcContainers.size()]; for (int i = 0; i < abcContainers.size(); i++) { - abcComboBoxData[i] = "tag" + (i+1); + abcComboBoxData[i] = "tag" + (i + 1); if (abcContainers.get(i) instanceof DoABC2Tag) { - DoABC2Tag doa2 = (DoABC2Tag)abcContainers.get(i); + DoABC2Tag doa2 = (DoABC2Tag) abcContainers.get(i); if (doa2.name != null && !doa2.name.isEmpty()) { abcComboBoxData[i] += " (\"" + Helper.escapePCodeString(doa2.name) + "\")"; } @@ -101,32 +105,30 @@ public class ABCExplorerDialog extends AppDialog { abcComboBox.setMinimumSize(abcComboBoxSize); abcComboBox.setPreferredSize(abcComboBoxSize); topPanel.add(abcComboBox); - + tagInfoLabel = new JLabel(); topPanel.add(tagInfoLabel); - - + abcComboBox.addActionListener(this::abcComboBoxActionPerformed); - - mainTabbedPane = new JTabbedPane(); + + mainTabbedPane = new JTabbedPane(); cpTabbedPane = new JTabbedPane(); - + cnt.add(topPanel, BorderLayout.NORTH); cnt.add(mainTabbedPane, BorderLayout.CENTER); - - abcComboBoxActionPerformed(null); + + abcComboBoxActionPerformed(null); setSize(800, 600); setTitle(translate("title")); View.setWindowIcon(this); View.centerScreen(this); } - + private ABC getSelectedAbc() { return abcContainers.get(abcComboBox.getSelectedIndex()).getABC(); } - - private void abcComboBoxActionPerformed(ActionEvent e) - { + + private void abcComboBoxActionPerformed(ActionEvent e) { int index = abcComboBox.getSelectedIndex(); ABC abc = abcContainers.get(index).getABC(); tagInfoLabel.setText( @@ -138,11 +140,9 @@ public class ABCExplorerDialog extends AppDialog { .replace("%size%", Helper.formatFileSize(abc.getDataSize())) .replace("%frame%", "" + abcFrames.get(index)) ); - - + cpTabbedPane.removeAll(); - - + cpTabbedPane.addTab("int (" + abc.constants.getIntCount() + ")", makeTreePanel(abc, TreeType.CONSTANT_INT)); cpTabbedPane.addTab("uint (" + abc.constants.getUIntCount() + ")", makeTreePanel(abc, TreeType.CONSTANT_UINT)); cpTabbedPane.addTab("dbl (" + abc.constants.getDoubleCount() + ")", makeTreePanel(abc, TreeType.CONSTANT_DOUBLE)); @@ -157,30 +157,30 @@ public class ABCExplorerDialog extends AppDialog { cpTabbedPane.addTab("ns (" + abc.constants.getNamespaceCount() + ")", makeTreePanel(abc, TreeType.CONSTANT_NAMESPACE)); cpTabbedPane.addTab("nss (" + abc.constants.getNamespaceSetCount() + ")", makeTreePanel(abc, TreeType.CONSTANT_NAMESPACE_SET)); cpTabbedPane.addTab("mn (" + abc.constants.getMultinameCount() + ")", makeTreePanel(abc, TreeType.CONSTANT_MULTINAME)); - + mainTabbedPane.removeAll(); - + JPanel cpPanel = new JPanel(new BorderLayout()); cpPanel.add(cpTabbedPane, BorderLayout.CENTER); - - int cpCount = abc.constants.getIntCount() - 1 + - abc.constants.getUIntCount() - 1 + - abc.constants.getDoubleCount() - 1 + - abc.constants.getStringCount() - 1 + - abc.constants.getNamespaceCount() - 1 + - abc.constants.getNamespaceSetCount() - 1 + - abc.constants.getMultinameCount() - 1 + - (abc.hasDecimalSupport() ? abc.constants.getDecimalCount() - 1 : 0) + - (abc.hasFloatSupport()? abc.constants.getFloatCount() - 1 + abc.constants.getFloat4Count() - 1 : 0); + + int cpCount = abc.constants.getIntCount() - 1 + + abc.constants.getUIntCount() - 1 + + abc.constants.getDoubleCount() - 1 + + abc.constants.getStringCount() - 1 + + abc.constants.getNamespaceCount() - 1 + + abc.constants.getNamespaceSetCount() - 1 + + abc.constants.getMultinameCount() - 1 + + (abc.hasDecimalSupport() ? abc.constants.getDecimalCount() - 1 : 0) + + (abc.hasFloatSupport() ? abc.constants.getFloatCount() - 1 + abc.constants.getFloat4Count() - 1 : 0); mainTabbedPane.addTab("cp (" + cpCount + ")", cpPanel); mainTabbedPane.addTab("mi (" + abc.method_info.size() + ")", makeTreePanel(abc, TreeType.METHOD_INFO)); mainTabbedPane.addTab("md (" + abc.metadata_info.size() + ")", makeTreePanel(abc, TreeType.METADATA)); mainTabbedPane.addTab("ii (" + abc.instance_info.size() + ")", makeTreePanel(abc, TreeType.INSTANCE_INFO)); mainTabbedPane.addTab("ci (" + abc.class_info.size() + ")", makeTreePanel(abc, TreeType.CLASS_INFO)); mainTabbedPane.addTab("si (" + abc.script_info.size() + ")", makeTreePanel(abc, TreeType.SCRIPT_INFO)); - mainTabbedPane.addTab("mb (" + abc.bodies.size() + ")", makeTreePanel(abc, TreeType.METHOD_BODY)); + mainTabbedPane.addTab("mb (" + abc.bodies.size() + ")", makeTreePanel(abc, TreeType.METHOD_BODY)); } - + private JPanel makeTreePanel(ABC abc, TreeType type) { JTree tree = new JTree(new ExplorerTreeModel(abc, type)); if (View.isOceanic()) { @@ -194,33 +194,33 @@ public class ABCExplorerDialog extends AppDialog { } } }); - + JPanel treePanel = new JPanel(new BorderLayout()); treePanel.add(new FasterScrollPane(tree), BorderLayout.CENTER); return treePanel; } - + private enum TreeType { - CONSTANT_INT("Integers","int"), - CONSTANT_UINT("UnsignedIntegers","uint"), + CONSTANT_INT("Integers", "int"), + CONSTANT_UINT("UnsignedIntegers", "uint"), CONSTANT_DOUBLE("Doubles", "dbl"), - CONSTANT_DECIMAL("Decimals","dc"), //needs ABC decimal support - CONSTANT_FLOAT("Floats","fl"), //needs ABC float support - CONSTANT_FLOAT_4("Floats4","fl4"), //needs ABC float support - CONSTANT_STRING("Strings","str"), + CONSTANT_DECIMAL("Decimals", "dc"), //needs ABC decimal support + CONSTANT_FLOAT("Floats", "fl"), //needs ABC float support + CONSTANT_FLOAT_4("Floats4", "fl4"), //needs ABC float support + CONSTANT_STRING("Strings", "str"), CONSTANT_NAMESPACE("Namespaces", "ns"), - CONSTANT_NAMESPACE_SET("NamespaceSets","nss"), - CONSTANT_MULTINAME("Multinames","mn"), - METHOD_INFO("MethodInfos","mi"), - METADATA("MetadataInfos","md"), - INSTANCE_INFO("InstanceInfos","ii"), - CLASS_INFO("ClassInfos","ci"), - SCRIPT_INFO("ScriptInfos","si"), - METHOD_BODY("MethodBodys","mb"); - + CONSTANT_NAMESPACE_SET("NamespaceSets", "nss"), + CONSTANT_MULTINAME("Multinames", "mn"), + METHOD_INFO("MethodInfos", "mi"), + METADATA("MetadataInfos", "md"), + INSTANCE_INFO("InstanceInfos", "ii"), + CLASS_INFO("ClassInfos", "ci"), + SCRIPT_INFO("ScriptInfos", "si"), + METHOD_BODY("MethodBodys", "mb"); + private final String name; private final String abbreviation; - + TreeType(String name, String abbreviation) { this.name = name; this.abbreviation = abbreviation; @@ -229,7 +229,7 @@ public class ABCExplorerDialog extends AppDialog { public String getName() { return name; } - + public String getAbbreviation() { return abbreviation; } @@ -237,24 +237,173 @@ public class ABCExplorerDialog extends AppDialog { @Override public String toString() { return name; - } + } } - - private class ValueWithIndex { + + private class SimpleValue { + + private final int currentLevelIndex; + private final Object parent; + private final String title; + + public SimpleValue(Object parent, int currentLevelIndex, String title) { + this.currentLevelIndex = currentLevelIndex; + this.parent = parent; + this.title = title; + } + + public int getCurrentLevelIndex() { + return currentLevelIndex; + } + + public Object getParent() { + return parent; + } + + @Override + public String toString() { + return title; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 47 * hash + this.currentLevelIndex; + hash = 47 * hash + Objects.hashCode(this.parent); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final SimpleValue other = (SimpleValue) obj; + if (this.currentLevelIndex != other.currentLevelIndex) { + return false; + } + return Objects.equals(this.parent, other.parent); + } + + } + + private class SubValue { + + private final int currentLevelIndex; + private final Object parent; + private final Object parentValue; + private final String property; + private final String title; private final int index; + + public SubValue(Object parent, int currentLevelIndex, Object parentValue, String property, String title) { + this.currentLevelIndex = currentLevelIndex; + this.parent = parent; + this.parentValue = parentValue; + this.property = property; + this.title = title; + this.index = -1; + } + + public SubValue(Object parent, int currentLevelIndex, int index, Object parentValue, String property, String title) { + this.currentLevelIndex = currentLevelIndex; + this.index = index; + this.parent = parent; + this.parentValue = parentValue; + this.property = property; + this.title = title; + } + + public int getIndex() { + return index; + } + + public int getCurrentLevelIndex() { + return currentLevelIndex; + } + + @Override + public String toString() { + return title; + } + + public Object getParent() { + return parent; + } + + public Object getParentValue() { + return parentValue; + } + + public String getProperty() { + return property; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 41 * hash + this.currentLevelIndex; + hash = 41 * hash + Objects.hashCode(this.parent); + hash = 41 * hash + Objects.hashCode(this.property); + hash = 41 * hash + this.index; + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final SubValue other = (SubValue) obj; + if (this.currentLevelIndex != other.currentLevelIndex) { + return false; + } + if (this.index != other.index) { + return false; + } + if (!Objects.equals(this.property, other.property)) { + return false; + } + return Objects.equals(this.parent, other.parent); + } + + } + + private class ValueWithIndex { + + private final Object parent; + private final int index; + private final int currentLevelIndex; private final TreeType type; private final Object value; private final String title; private final String prefix; - public ValueWithIndex(int index, TreeType type, Object value, String title) { + public ValueWithIndex(Object parent, int currentLevelIndex, int index, TreeType type, Object value, String title) { + this.parent = parent; + this.currentLevelIndex = currentLevelIndex; this.index = index; this.type = type; this.value = value; this.title = title; this.prefix = ""; - } - public ValueWithIndex(int index, TreeType type, Object value, String title, String prefix) { + } + + public ValueWithIndex(Object parent, int currentLevelIndex, int index, TreeType type, Object value, String title, String prefix) { + this.parent = parent; + this.currentLevelIndex = currentLevelIndex; this.index = index; this.type = type; this.value = value; @@ -262,13 +411,21 @@ public class ABCExplorerDialog extends AppDialog { this.prefix = prefix; } + public int getCurrentLevelIndex() { + return currentLevelIndex; + } + + public Object getParent() { + return parent; + } + public int getIndex() { return index; } public TreeType getType() { return type; - } + } @Override public String toString() { @@ -284,15 +441,15 @@ public class ABCExplorerDialog extends AppDialog { implicit = true; } } - - return prefix + (implicit ? "[" : "") +type.getAbbreviation() + index + (implicit ? "]" : "") + ": " + title; - } + + return prefix + (implicit ? "[" : "") + type.getAbbreviation() + index + (implicit ? "]" : "") + ": " + title; + } @Override public int hashCode() { - int hash = 7; - hash = 23 * hash + this.index; - hash = 23 * hash + Objects.hashCode(this.type); + int hash = 3; + hash = 31 * hash + Objects.hashCode(this.parent); + hash = 31 * hash + this.currentLevelIndex; return hash; } @@ -308,134 +465,278 @@ public class ABCExplorerDialog extends AppDialog { return false; } final ValueWithIndex other = (ValueWithIndex) obj; - if (this.index != other.index) { + if (this.currentLevelIndex != other.currentLevelIndex) { return false; } - return this.type == other.type; + return Objects.equals(this.parent, other.parent); } - - + } - + private class ExplorerTreeModel implements TreeModel { private TreeType type; private ABC abc; - + public ExplorerTreeModel(ABC abc, TreeType type) { this.type = type; this.abc = abc; } - + @Override public Object getRoot() { return type; } - private ValueWithIndex createValueWithIndex(int index, TreeType valueType, String prefix) { + private ValueWithIndex createValueWithIndex(Object parent, int currentLevelIndex, int index, TreeType valueType, String prefix) { if (index == 0) { - switch(valueType) { - case CONSTANT_INT: - case CONSTANT_UINT: - case CONSTANT_DOUBLE: - case CONSTANT_STRING: - case CONSTANT_NAMESPACE: - case CONSTANT_MULTINAME: - return new ValueWithIndex(index, valueType, null, "null", prefix); - } - } - switch(valueType) { + switch (valueType) { case CONSTANT_INT: - return new ValueWithIndex(index, valueType, abc.constants.getInt(index), "" + abc.constants.getInt(index), prefix); case CONSTANT_UINT: - return new ValueWithIndex(index, valueType, abc.constants.getUInt(index), "" + abc.constants.getUInt(index), prefix); case CONSTANT_DOUBLE: - return new ValueWithIndex(index, valueType, abc.constants.getDouble(index), EcmaScript.toString(abc.constants.getDouble(index)), prefix); - case CONSTANT_DECIMAL: - return new ValueWithIndex(index, valueType, abc.constants.getDecimal(index), "" + abc.constants.getDecimal(index), prefix); - case CONSTANT_FLOAT: - return new ValueWithIndex(index, valueType, abc.constants.getFloat(index), EcmaScript.toString(abc.constants.getFloat(index)), prefix); - case CONSTANT_FLOAT_4: - Float4 f4 = abc.constants.getFloat4(index); - return new ValueWithIndex(index, valueType, f4, - EcmaScript.toString(f4.values[0]) + " " + - EcmaScript.toString(f4.values[1]) + " " + - EcmaScript.toString(f4.values[2]) + " " + - EcmaScript.toString(f4.values[3]), - prefix - ); case CONSTANT_STRING: - return new ValueWithIndex(index, valueType, abc.constants.getString(index), "\"" + Helper.escapePCodeString(abc.constants.getString(index)) +"\"", prefix); case CONSTANT_NAMESPACE: - return new ValueWithIndex(index, valueType, abc.constants.getNamespace(index), Multiname.namespaceToString(abc.constants, index), prefix); - case CONSTANT_NAMESPACE_SET: - return new ValueWithIndex(index, valueType, abc.constants.getNamespaceSet(index), Multiname.namespaceSetToString(abc.constants, index), prefix); case CONSTANT_MULTINAME: - Multiname multiname = abc.constants.getMultiname(index); - return new ValueWithIndex(index, valueType, multiname, multiname.toString(abc.constants, new ArrayList()), prefix); - default: - return new ValueWithIndex(index, valueType, null, "", prefix); + return new ValueWithIndex(parent, currentLevelIndex, index, valueType, null, "null", prefix); } + } + switch (valueType) { + case CONSTANT_INT: + return new ValueWithIndex(parent, currentLevelIndex, index, valueType, abc.constants.getInt(index), "" + abc.constants.getInt(index), prefix); + case CONSTANT_UINT: + return new ValueWithIndex(parent, currentLevelIndex, index, valueType, abc.constants.getUInt(index), "" + abc.constants.getUInt(index), prefix); + case CONSTANT_DOUBLE: + return new ValueWithIndex(parent, currentLevelIndex, index, valueType, abc.constants.getDouble(index), EcmaScript.toString(abc.constants.getDouble(index)), prefix); + case CONSTANT_DECIMAL: + return new ValueWithIndex(parent, currentLevelIndex, index, valueType, abc.constants.getDecimal(index), "" + abc.constants.getDecimal(index), prefix); + case CONSTANT_FLOAT: + return new ValueWithIndex(parent, currentLevelIndex, index, valueType, abc.constants.getFloat(index), EcmaScript.toString(abc.constants.getFloat(index)), prefix); + case CONSTANT_FLOAT_4: + Float4 f4 = abc.constants.getFloat4(index); + return new ValueWithIndex(parent, currentLevelIndex, index, valueType, f4, + EcmaScript.toString(f4.values[0]) + " " + + EcmaScript.toString(f4.values[1]) + " " + + EcmaScript.toString(f4.values[2]) + " " + + EcmaScript.toString(f4.values[3]), + prefix + ); + case CONSTANT_STRING: + return new ValueWithIndex(parent, currentLevelIndex, index, valueType, abc.constants.getString(index), "\"" + Helper.escapePCodeString(abc.constants.getString(index)) + "\"", prefix); + case CONSTANT_NAMESPACE: + return new ValueWithIndex(parent, currentLevelIndex, index, valueType, abc.constants.getNamespace(index), Multiname.namespaceToString(abc.constants, index), prefix); + case CONSTANT_NAMESPACE_SET: + return new ValueWithIndex(parent, currentLevelIndex, index, valueType, abc.constants.getNamespaceSet(index), Multiname.namespaceSetToString(abc.constants, index), prefix); + case CONSTANT_MULTINAME: + Multiname multiname = abc.constants.getMultiname(index); + return new ValueWithIndex(parent, currentLevelIndex, index, valueType, multiname, multiname.toString(abc.constants, new ArrayList()), prefix); + case METHOD_INFO: + MethodInfo mi = abc.method_info.get(index); + StringBuilder miStrSb = new StringBuilder(); + miStrSb.append("("); + StringBuilderTextWriter miParamStrSbW = new StringBuilderTextWriter(new CodeFormatting(), miStrSb); + mi.getParamStr(miParamStrSbW, abc.constants, null, abc, new ArrayList<>()); + miStrSb.append("): "); + String miReturnType = mi.getReturnTypeRaw(abc.constants, new ArrayList<>()); + miStrSb.append(miReturnType); + return new ValueWithIndex(parent, currentLevelIndex, index, valueType, mi, miStrSb.toString(), prefix); + default: + return new ValueWithIndex(parent, currentLevelIndex, index, valueType, null, "", prefix); + } } - + @Override public Object getChild(Object parent, int index) { if (parent == type) { - return createValueWithIndex(index, type, ""); + return createValueWithIndex(parent, index, index, type, ""); } if (parent instanceof ValueWithIndex) { - ValueWithIndex vwi = (ValueWithIndex)parent; + ValueWithIndex vwi = (ValueWithIndex) parent; if (vwi.value instanceof NamespaceSet) { NamespaceSet nss = (NamespaceSet) vwi.value; int ns = nss.namespaces[index]; - return new ValueWithIndex(ns, TreeType.CONSTANT_NAMESPACE, abc.constants.getNamespace(ns), Multiname.namespaceToString(abc.constants, ns)); + return new ValueWithIndex(parent, index, ns, TreeType.CONSTANT_NAMESPACE, abc.constants.getNamespace(ns), Multiname.namespaceToString(abc.constants, ns)); } if (vwi.value instanceof Namespace) { Namespace ns = (Namespace) vwi.value; switch (index) { case 0: - return "kind: " + Namespace.kindToStr(ns.kind); + return new SimpleValue(parent, index, "kind: " + Namespace.kindToStr(ns.kind)); case 1: - return createValueWithIndex(ns.name_index, TreeType.CONSTANT_STRING, "name: "); + return createValueWithIndex(parent, index, ns.name_index, TreeType.CONSTANT_STRING, "name: "); } } if (vwi.value instanceof Multiname) { - Multiname m = (Multiname)vwi.value; + Multiname m = (Multiname) vwi.value; if (index == 0) { - return "kind: " + m.getKindStr(); + return new SimpleValue(parent, index, "kind: " + m.getKindStr()); } int kind = m.kind; if ((kind == Multiname.QNAME) || (kind == Multiname.QNAMEA)) { switch (index) { case 1: - return createValueWithIndex(m.namespace_index, TreeType.CONSTANT_NAMESPACE, "namespace: "); + return createValueWithIndex(parent, index, m.namespace_index, TreeType.CONSTANT_NAMESPACE, "namespace: "); case 2: - return createValueWithIndex(m.name_index, TreeType.CONSTANT_STRING, "name: "); - } + return createValueWithIndex(parent, index, m.name_index, TreeType.CONSTANT_STRING, "name: "); + } } else if ((kind == Multiname.RTQNAME) || (kind == Multiname.RTQNAMEA)) { if (index == 1) { - return createValueWithIndex(m.name_index, TreeType.CONSTANT_STRING, "name: "); + return createValueWithIndex(parent, index, m.name_index, TreeType.CONSTANT_STRING, "name: "); } } else if ((kind == Multiname.RTQNAMEL) || (kind == Multiname.RTQNAMELA)) { //ignore } else if ((kind == Multiname.MULTINAME) || (kind == Multiname.MULTINAMEA)) { switch (index) { case 1: - return createValueWithIndex(m.name_index, TreeType.CONSTANT_STRING, "name: "); + return createValueWithIndex(parent, index, m.name_index, TreeType.CONSTANT_STRING, "name: "); case 2: - return createValueWithIndex(m.namespace_set_index, TreeType.CONSTANT_NAMESPACE_SET, "namespace_set: "); - } + return createValueWithIndex(parent, index, m.namespace_set_index, TreeType.CONSTANT_NAMESPACE_SET, "namespace_set: "); + } } else if ((kind == Multiname.MULTINAMEL) || (kind == Multiname.MULTINAMELA)) { if (index == 1) { - return createValueWithIndex(m.namespace_set_index, TreeType.CONSTANT_NAMESPACE_SET, "namespace_set: "); + return createValueWithIndex(parent, index, m.namespace_set_index, TreeType.CONSTANT_NAMESPACE_SET, "namespace_set: "); } } else if (kind == Multiname.TYPENAME) { if (index == 1) { - return createValueWithIndex(m.qname_index, TreeType.CONSTANT_MULTINAME, "qname: "); + return createValueWithIndex(parent, index, m.qname_index, TreeType.CONSTANT_MULTINAME, "qname: "); } if (index >= 2 && index - 2 < m.params.length) { - return createValueWithIndex(m.params[index - 2], TreeType.CONSTANT_MULTINAME, "param" + (index - 1) + ": "); - } + return createValueWithIndex(parent, index, m.params[index - 2], TreeType.CONSTANT_MULTINAME, "param" + (index - 2) + ": "); + } + } + } + if (vwi.value instanceof MethodInfo) { + MethodInfo mi = (MethodInfo) vwi.value; + switch (index) { + case 0: + return new SubValue(parent, index, mi, "param_types", "param_types"); + case 1: + return createValueWithIndex(parent, index, mi.ret_type, TreeType.CONSTANT_MULTINAME, "return_type: "); + case 2: + return createValueWithIndex(parent, index, mi.name_index, TreeType.CONSTANT_STRING, "name: "); + case 3: + List flagList = new ArrayList<>(); + if (mi.flagNative()) { + flagList.add("NATIVE"); + } + if (mi.flagHas_optional()) { + flagList.add("HAS_OPTIONAL"); + } + if (mi.flagHas_paramnames()) { + flagList.add("HAS_PARAM_NAMES"); + } + if (mi.flagIgnore_rest()) { + flagList.add("IGNORE_REST"); + } + if (mi.flagNeed_activation()) { + flagList.add("NEED_ACTIVATION"); + } + if (mi.flagNeed_arguments()) { + flagList.add("NEED_ARGUMENTS"); + } + if (mi.flagNeed_rest()) { + flagList.add("NEED_REST"); + } + if (mi.flagSetsdxns()) { + flagList.add("SET_DXNS"); + } + + return new SimpleValue(parent, index, "flags: " + String.format("0x%02X", mi.flags) + (!flagList.isEmpty() ? " (" + String.join(", ", flagList) + ")": "")); + } + + int currentIndex = 4; + + if (mi.flagHas_optional()) { + if (index == currentIndex) { + return new SubValue(parent, index, mi, "optional", "optional"); + } + currentIndex++; + } + + if (mi.flagHas_paramnames()) { + if (index == currentIndex) { + return new SubValue(parent, index, mi, "param_names", "param_names"); + } + } + } + } + if (parent instanceof SubValue) { + SubValue sv = (SubValue) parent; + if (sv.getParentValue() instanceof MethodInfo) { + MethodInfo mi = (MethodInfo) sv.getParentValue(); + switch (sv.getProperty()) { + case "param_types": + return createValueWithIndex(parent, index, mi.param_types[index], TreeType.CONSTANT_MULTINAME, "pt" + index + ": "); + case "optional": + if (sv.getIndex() > -1) { + if (index == 0) { + switch (mi.optional[sv.getIndex()].value_kind) { + case ValueKind.CONSTANT_Int: + return new SimpleValue(parent, index, "value_kind: Integer"); + case ValueKind.CONSTANT_UInt: + return new SimpleValue(parent, index, "value_kind: UInteger"); + case ValueKind.CONSTANT_Double: + return new SimpleValue(parent, index, "value_kind: Double"); + case ValueKind.CONSTANT_DecimalOrFloat: //?? or float ?? + return new SimpleValue(parent, index, "value_kind: Decimal"); + case ValueKind.CONSTANT_Utf8: + return new SimpleValue(parent, index, "value_kind: String"); + case ValueKind.CONSTANT_True: + return new SimpleValue(parent, index, "value_kind: True"); + case ValueKind.CONSTANT_False: + return new SimpleValue(parent, index, "value_kind: False"); + case ValueKind.CONSTANT_Null: + return new SimpleValue(parent, index, "value_kind: Null"); + case ValueKind.CONSTANT_Undefined: + return new SimpleValue(parent, index, "value_kind: Undefined"); + case ValueKind.CONSTANT_Namespace: + return new SimpleValue(parent, index, "value_kind: Namespace"); + case ValueKind.CONSTANT_PackageInternalNs: + return new SimpleValue(parent, index, "value_kind: PackageInternalNs"); + case ValueKind.CONSTANT_ProtectedNamespace: + return new SimpleValue(parent, index, "value_kind: ProtectedNamespace"); + case ValueKind.CONSTANT_ExplicitNamespace: + return new SimpleValue(parent, index, "value_kind: ExplicitNamespace"); + case ValueKind.CONSTANT_StaticProtectedNs: + return new SimpleValue(parent, index, "value_kind: StaticProtectedNs"); + case ValueKind.CONSTANT_PrivateNs: + return new SimpleValue(parent, index, "value_kind: PrivateNamespace"); + } + } + if (index == 1) { + int value_index = mi.optional[sv.getIndex()].value_index; + switch (mi.optional[sv.getIndex()].value_kind) { + case ValueKind.CONSTANT_Int: + return createValueWithIndex(parent, index, value_index, TreeType.CONSTANT_INT, "value_index: "); + case ValueKind.CONSTANT_UInt: + return createValueWithIndex(parent, index, value_index, TreeType.CONSTANT_UINT, "value_index: "); + case ValueKind.CONSTANT_Double: + return createValueWithIndex(parent, index, value_index, TreeType.CONSTANT_DOUBLE, "value_index: "); + case ValueKind.CONSTANT_DecimalOrFloat: //?? or float ?? + return createValueWithIndex(parent, index, value_index, TreeType.CONSTANT_DECIMAL, "value_index: "); + case ValueKind.CONSTANT_Utf8: + return createValueWithIndex(parent, index, value_index, TreeType.CONSTANT_STRING, "value_index: "); + case ValueKind.CONSTANT_True: + break; + case ValueKind.CONSTANT_False: + break; + case ValueKind.CONSTANT_Null: + break; + case ValueKind.CONSTANT_Undefined: + break; + case ValueKind.CONSTANT_Namespace: + case ValueKind.CONSTANT_PackageInternalNs: + case ValueKind.CONSTANT_ProtectedNamespace: + case ValueKind.CONSTANT_ExplicitNamespace: + case ValueKind.CONSTANT_StaticProtectedNs: + case ValueKind.CONSTANT_PrivateNs: + return createValueWithIndex(parent, index, value_index, TreeType.CONSTANT_NAMESPACE, "value_index: "); + } + } + } else { + return new SubValue(parent, index, index, mi, "optional", "op" + index + ": " + mi.optional[index].toASMString(abc.constants)); + } + case "param_names": + return createValueWithIndex(parent, index, mi.paramNames[index], TreeType.CONSTANT_STRING, "pn" + index + ": "); } } } @@ -445,7 +746,7 @@ public class ABCExplorerDialog extends AppDialog { @Override public int getChildCount(Object parent) { if (parent == type) { - switch(type) { + switch (type) { case CONSTANT_INT: return abc.constants.getIntCount(); case CONSTANT_UINT: @@ -477,11 +778,11 @@ public class ABCExplorerDialog extends AppDialog { case SCRIPT_INFO: return abc.script_info.size(); case METHOD_BODY: - return abc.bodies.size(); + return abc.bodies.size(); } } if (parent instanceof ValueWithIndex) { - ValueWithIndex vwi = (ValueWithIndex)parent; + ValueWithIndex vwi = (ValueWithIndex) parent; if (vwi.value instanceof NamespaceSet) { NamespaceSet nss = (NamespaceSet) vwi.value; return nss.namespaces.length; @@ -491,12 +792,12 @@ public class ABCExplorerDialog extends AppDialog { return 2; } if (vwi.value instanceof Multiname) { - Multiname m = (Multiname)vwi.value; + Multiname m = (Multiname) vwi.value; int kind = m.kind; if ((kind == Multiname.QNAME) || (kind == Multiname.QNAMEA)) { - return 1 + 2; + return 1 + 2; } else if ((kind == Multiname.RTQNAME) || (kind == Multiname.RTQNAMEA)) { - return 1 + 1; + return 1 + 1; } else if ((kind == Multiname.RTQNAMEL) || (kind == Multiname.RTQNAMELA)) { return 1; } else if ((kind == Multiname.MULTINAME) || (kind == Multiname.MULTINAMEA)) { @@ -507,6 +808,56 @@ public class ABCExplorerDialog extends AppDialog { return 1 + 1 + m.params.length; } } + if (vwi.value instanceof MethodInfo) { + MethodInfo mi = (MethodInfo) vwi.value; + + int count = 4; + if (mi.flagHas_optional()) { + count++; + } + if (mi.flagHas_paramnames()) { + count++; + } + return count; + } + } + if (parent instanceof SubValue) { + SubValue sv = (SubValue) parent; + if (sv.getParentValue() instanceof MethodInfo) { + MethodInfo mi = (MethodInfo) sv.getParentValue(); + switch (sv.getProperty()) { + case "param_types": + return mi.param_types.length; + case "optional": + if (sv.getIndex() > -1) { + int index = sv.getIndex(); + int value_index = mi.optional[index].value_index; + switch (mi.optional[index].value_kind) { + case ValueKind.CONSTANT_True: + case ValueKind.CONSTANT_False: + case ValueKind.CONSTANT_Null: + case ValueKind.CONSTANT_Undefined: + return 1; + case ValueKind.CONSTANT_Int: + case ValueKind.CONSTANT_UInt: + case ValueKind.CONSTANT_Double: + case ValueKind.CONSTANT_DecimalOrFloat: //?? or float ?? + case ValueKind.CONSTANT_Utf8: + case ValueKind.CONSTANT_Namespace: + case ValueKind.CONSTANT_PackageInternalNs: + case ValueKind.CONSTANT_ProtectedNamespace: + case ValueKind.CONSTANT_ExplicitNamespace: + case ValueKind.CONSTANT_StaticProtectedNs: + case ValueKind.CONSTANT_PrivateNs: + return 2; + } + return 0; + } + return mi.optional.length; + case "param_names": + return mi.paramNames.length; + } + } } return 0; } @@ -522,33 +873,45 @@ public class ABCExplorerDialog extends AppDialog { @Override public int getIndexOfChild(Object parent, Object child) { + System.err.println("getting index of child " + child + " in parent " + parent); if (child instanceof ValueWithIndex) { - ValueWithIndex vwi = (ValueWithIndex)child; - if (vwi.getType() == type) { - return vwi.index; + ValueWithIndex vwi = (ValueWithIndex) child; + if (vwi.getParent() == parent) { + return vwi.getCurrentLevelIndex(); + } + } + if (child instanceof SubValue) { + SubValue sv = (SubValue) child; + if (sv.parent == parent) { + return sv.getCurrentLevelIndex(); + } + } + if (child instanceof SimpleValue) { + SimpleValue sv = (SimpleValue) child; + if (sv.parent == parent) { + return sv.getCurrentLevelIndex(); } } return -1; } @Override - public void addTreeModelListener(TreeModelListener l) { + public void addTreeModelListener(TreeModelListener l) { } @Override public void removeTreeModelListener(TreeModelListener l) { - } + } } - + public static class ExplorerTreeCellRenderer extends DefaultTreeCellRenderer { - public ExplorerTreeCellRenderer() { setUI(new BasicLabelUI()); setOpaque(false); if (View.isOceanic()) { setBackgroundNonSelectionColor(Color.white); - } + } } @Override @@ -575,19 +938,18 @@ public class ABCExplorerDialog extends AppDialog { boolean leaf, int row, boolean hasFocus) { - + super.getTreeCellRendererComponent( tree, value, sel, expanded, leaf, row, - hasFocus); - + hasFocus); + if (View.isOceanic()) { setForeground(Color.BLACK); } setToolTipText(null); //semitransparent = true; - return this; } }