From ec666b60e4f84564d103dd42f43b9aae21acc775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 5 Dec 2015 10:53:43 +0100 Subject: [PATCH] AS1/2: Ctrl+click to declaration of variables, registers. Hilighting methods and classes AS1/2: Debugger - Show registers Fixed ctrl+click underline position --- .../src/com/jpexs/decompiler/flash/SWF.java | 64 ++++++++----- .../decompiler/flash/action/CachedScript.java | 8 +- .../action/model/CallFunctionActionItem.java | 7 +- .../action/model/DefineLocalActionItem.java | 5 ++ .../action/model/DirectValueActionItem.java | 8 +- .../action/model/FunctionActionItem.java | 34 ++++++- .../action/model/GetVariableActionItem.java | 8 +- .../action/model/SetVariableActionItem.java | 7 ++ .../action/model/StoreRegisterActionItem.java | 8 ++ .../action/model/clauses/ClassActionItem.java | 5 +- .../model/clauses/InterfaceActionItem.java | 3 +- .../parser/script/ActionScript2Parser.java | 2 +- .../action/swf5/ActionDefineFunction.java | 2 +- .../action/swf7/ActionDefineFunction2.java | 2 +- .../flash/helpers/GraphTextWriter.java | 18 ++++ .../flash/helpers/HighlightedTextWriter.java | 19 ++++ .../flash/helpers/hilight/Highlighting.java | 11 +++ .../decompiler/flash/gui/abc/ABCPanel.java | 4 +- .../flash/gui/action/ActionPanel.java | 90 +++++++++++++++++++ .../gui/editor/LineMarkedEditorPane.java | 80 ++++++++++------- 20 files changed, 321 insertions(+), 64 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 5aa048815..542c78a6b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -2385,10 +2385,16 @@ public final class SWF implements SWFContainerItem, Timelined { } HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); + writer.startFunction("!script"); Action.actionsToSource(src, actions, src.toString()/*FIXME?*/, writer); + writer.endFunction(); List hilights = writer.instructionHilights; + List methodHilights = writer.methodHilights; + List classHilights = writer.classHilights; + List specialHilights = writer.specialHilights; + String srcNoHex = writer.toString(); - CachedScript res = new CachedScript(srcNoHex, hilights); + CachedScript res = new CachedScript(srcNoHex, hilights, methodHilights, classHilights, specialHilights); swf.as2Cache.put(src, res); return res; } @@ -3114,29 +3120,36 @@ public final class SWF implements SWFContainerItem, Timelined { } /** - * Enables debugging. Adds tags to enable debugging and injects debugline - * and debugfile instructions to AS3 code + * Enables debugging. Adds tags to enable debugging and optinally injects + * debugline and debugfile instructions to AS3 code by decompiling it first * - * @param injectCode Modify AS3 code with debugfile / debugline ? + * @param injectAS3Code Modify AS3 code with debugfile / debugline ? * @param decompileDir Directory to virtual decompile (will affect * debugfile) */ - public void enableDebugging(boolean injectCode, File decompileDir) { - enableDebugging(injectCode, decompileDir, false); + public void enableDebugging(boolean injectAS3Code, File decompileDir) { + enableDebugging(injectAS3Code, decompileDir, false); + } + + /** + * Enables debugging. Adds tags to enable debugging. + */ + public void enableDebugging() { + enableDebugging(false, null, false); } /** * Enables debugging. Adds tags to enable debugging and injects debugline * and debugfile instructions to AS3 code. Optionally enables Telemetry * - * @param injectCode Modify AS3 code with debugfile / debugline ? + * @param injectAS3Code Modify AS3 code with debugfile / debugline ? * @param decompileDir Directory to virtual decompile (will affect * debugfile) * @param telemetry Enable telemetry info? */ - public void enableDebugging(boolean injectCode, File decompileDir, boolean telemetry) { + public void enableDebugging(boolean injectAS3Code, File decompileDir, boolean telemetry) { - if (injectCode) { + if (injectAS3Code) { List packs = getAS3Packs(); for (ScriptPack s : packs) { if (s.isSimple) { @@ -3181,9 +3194,14 @@ public final class SWF implements SWFContainerItem, Timelined { } } - addDebugId(); + getOrAddDebugId(); } + /** + * Finds DebugID tag + * + * @return the tag or null if not found + */ public DebugIDTag getDebugId() { for (Tag t : tags) { if (t instanceof DebugIDTag) { @@ -3193,7 +3211,12 @@ public final class SWF implements SWFContainerItem, Timelined { return null; } - public DebugIDTag addDebugId() { + /** + * Finds DebugID tag and generates new one if none exists + * + * @return the tag or null if there is not debugging enabled in the swf file + */ + public DebugIDTag getOrAddDebugId() { DebugIDTag r = getDebugId(); if (r == null) { for (int i = 0; i < tags.size(); i++) { @@ -3229,6 +3252,7 @@ public final class SWF implements SWFContainerItem, Timelined { Collections.sort(names); //Collections.reverse(names); for (String name : names) { + List regitems = new ArrayList<>(); moduleId++; CachedScript cs; try { @@ -3246,18 +3270,17 @@ public final class SWF implements SWFContainerItem, Timelined { if (h != null) { int firstLineOffset = (int) h.getProperties().firstLineOffset; - if (firstLineOffset != -1) { - if (h.getProperties().declaration && h.getProperties().regIndex > -1) { - regNames.put(h.getProperties().regIndex, h.getProperties().localName); + if (firstLineOffset > -1 && h.getProperties().declaration && h.getProperties().regIndex > -1 && (!regNames.containsKey(h.getProperties().regIndex) || !regNames.get(h.getProperties().regIndex).equals(h.getProperties().localName))) { + regNames.put(h.getProperties().regIndex, h.getProperties().localName); - /*List curRegIndexes = new ArrayList<>(regNames.keySet()); - List curRegNames = new ArrayList<>(); - for (int i = 0; i < curRegIndexes.size(); i++) { - curRegNames.add(regNames.get(i)); - } - items.add(new SWD.DebugRegisters((int) h.getProperties().firstLineOffset, curRegIndexes, curRegNames));*/ + List curRegIndexes = new ArrayList<>(regNames.keySet()); + List curRegNames = new ArrayList<>(); + for (int i = 0; i < curRegIndexes.size(); i++) { + curRegNames.add(regNames.get(curRegIndexes.get(i))); } + regitems.add(new SWD.DebugRegisters((int) h.getProperties().firstLineOffset, curRegIndexes, curRegNames)); } + if (firstLineOffset != -1 && !lineToOffset.containsKey(line)) { lineToOffset.put(line, firstLineOffset); } @@ -3321,6 +3344,7 @@ public final class SWF implements SWFContainerItem, Timelined { } } } + items.addAll(regitems); //moduleId++; } //items.addAll(swdOffsets); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/CachedScript.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/CachedScript.java index 408da4ab6..3c8d5f577 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/CachedScript.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/CachedScript.java @@ -29,9 +29,15 @@ public class CachedScript implements Serializable { public String text; public List hilights; + public List methodHilights; + public List classHilights; + public List specialHilights; - public CachedScript(String text, List hilights) { + public CachedScript(String text, List hilights, List methodHilights, List classHilights, List specialHilights) { this.text = text; this.hilights = hilights; + this.methodHilights = methodHilights; + this.classHilights = classHilights; + this.specialHilights = specialHilights; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/CallFunctionActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/CallFunctionActionItem.java index 60f57a5b5..193d8f388 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/CallFunctionActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/CallFunctionActionItem.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphSourceItemPos; @@ -44,13 +45,17 @@ public class CallFunctionActionItem extends ActionItem { } public CallFunctionActionItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem functionName, List arguments) { - super(instruction, lineStartIns, PRECEDENCE_PRIMARY); + super(instruction, lineStartIns, PRECEDENCE_PRIMARY); this.functionName = functionName; this.arguments = arguments; } @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + + HighlightData srcData = getSrcData(); + srcData.localName = functionName.toStringNoQuotes(localData); + if (functionName instanceof DirectValueActionItem) { writer.append(IdentifiersDeobfuscation.printIdentifier(false, (functionName).toStringNoQuotes(localData))); } else { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DefineLocalActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DefineLocalActionItem.java index 2874c87ef..a594ed6a6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DefineLocalActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DefineLocalActionItem.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal; import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal2; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphSourceItemPos; @@ -74,8 +75,12 @@ public class DefineLocalActionItem extends ActionItem implements SetTypeActionIt @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.append("var "); + HighlightData srcData = getSrcData(); + srcData.localName = name.toStringNoQuotes(localData); + srcData.declaration = true; if (((name instanceof DirectValueActionItem)) && (((DirectValueActionItem) name).isString()) && (!IdentifiersDeobfuscation.isValidName(false, ((DirectValueActionItem) name).toStringNoQuotes(localData), "this", "super"))) { IdentifiersDeobfuscation.appendObfuscatedIdentifier(((DirectValueActionItem) name).toStringNoQuotes(localData), writer); } else { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DirectValueActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DirectValueActionItem.java index 0485d8a6d..2fb7af95b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DirectValueActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DirectValueActionItem.java @@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.ecma.EcmaScript; import com.jpexs.decompiler.flash.ecma.Null; import com.jpexs.decompiler.flash.ecma.Undefined; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -171,7 +172,12 @@ public class DirectValueActionItem extends ActionItem implements SimpleValue { return writer.append("\"").append(Helper.escapeActionScriptString(this.constants.get(((ConstantIndex) value).index))).append("\""); } if (value instanceof RegisterNumber) { - return writer.append(((RegisterNumber) value).translate()); + + HighlightData srcData = getSrcData(); + srcData.localName = ((RegisterNumber) value).translate(); + srcData.regIndex = ((RegisterNumber) value).number; + + return writer.appendWithData(((RegisterNumber) value).translate(), srcData); } //return writer.append(value.toString()); return writer.append(EcmaScript.toString(value, true)); // todo, use this line diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java index 75a23bc31..22933cfea 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java @@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphSourceItem; @@ -36,8 +37,10 @@ import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.helpers.Helper; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; public class FunctionActionItem extends ActionItem { @@ -50,6 +53,8 @@ public class FunctionActionItem extends ActionItem { public List paramNames; + public Map regNames; + public GraphTargetItem calculatedFunctionName; private int regStart; @@ -79,18 +84,26 @@ public class FunctionActionItem extends ActionItem { super(null, null, PRECEDENCE_PRIMARY); } - public FunctionActionItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, String functionName, List paramNames, List actions, List constants, int regStart, List variables) { + public FunctionActionItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, String functionName, List paramNames, Map regNames, List actions, List constants, int regStart, List variables) { super(instruction, lineStartIns, PRECEDENCE_PRIMARY); this.actions = actions; this.constants = constants; this.functionName = functionName; this.paramNames = paramNames; + this.regNames = regNames; this.regStart = regStart; this.variables = variables; } @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + String n = calculatedFunctionName != null ? calculatedFunctionName.toStringNoQuotes(localData) : functionName; + writer.startFunction(n); + HighlightData srcData = getSrcData(); + if (n != null) { + srcData.localName = n; + srcData.declaration = true; + } writer.append("function"); if (calculatedFunctionName != null) { writer.append(" "); @@ -111,6 +124,11 @@ public class FunctionActionItem extends ActionItem { writer.spaceBeforeCallParenthesies(paramNames.size()); writer.append("("); + Map n2r = new HashMap<>(); + for (int r : regNames.keySet()) { + n2r.put(regNames.get(r), r); + } + for (int p = 0; p < paramNames.size(); p++) { if (p > 0) { writer.append(", "); @@ -119,16 +137,26 @@ public class FunctionActionItem extends ActionItem { if (pname == null || pname.isEmpty()) { pname = new RegisterNumber(regStart + p).translate(); } + HighlightData d = getSrcData(); + d.localName = pname; + if (n2r.containsKey(pname)) { + d.regIndex = n2r.get(pname); + } + d.declaration = true; + if (!IdentifiersDeobfuscation.isValidName(false, pname)) { IdentifiersDeobfuscation.appendObfuscatedIdentifier(pname, writer); + } else { + writer.append(pname); } - writer.append(pname); } writer.append(")").startBlock(); Graph.graphToString(actions, writer, localData); - return writer.endBlock(); + writer.endBlock(); + writer.endMethod(); + return writer; } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/GetVariableActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/GetVariableActionItem.java index c98bb60a1..193c44fdc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/GetVariableActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/GetVariableActionItem.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; import com.jpexs.decompiler.flash.ecma.Undefined; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphSourceItemPos; @@ -57,7 +58,7 @@ public class GetVariableActionItem extends ActionItem { } public GetVariableActionItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem value) { - super(instruction, lineStartIns, PRECEDENCE_PRIMARY); + super(instruction, lineStartIns, PRECEDENCE_PRIMARY); this.name = value; } @@ -65,12 +66,17 @@ public class GetVariableActionItem extends ActionItem { public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { if (((name instanceof DirectValueActionItem)) && (((DirectValueActionItem) name).isString()) && (!IdentifiersDeobfuscation.isValidNameWithDot(false, ((DirectValueActionItem) name).toStringNoQuotes(localData), "this", "super"))) { + HighlightData srcData = getSrcData(); + srcData.localName = name.toStringNoQuotes(localData); + return IdentifiersDeobfuscation.appendObfuscatedIdentifier(((DirectValueActionItem) name).toStringNoQuotes(localData), writer); } else if ((!(name instanceof DirectValueActionItem)) || (!((DirectValueActionItem) name).isString())) { writer.append("eval("); name.appendTo(writer, localData); return writer.append(")"); } + HighlightData srcData = getSrcData(); + srcData.localName = name.toStringNoQuotes(localData); return stripQuotes(name, localData, writer); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetVariableActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetVariableActionItem.java index 0bf3427df..b1d18fdba 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetVariableActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetVariableActionItem.java @@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphPart; import com.jpexs.decompiler.graph.GraphSourceItem; @@ -74,6 +75,9 @@ public class SetVariableActionItem extends ActionItem implements SetTypeActionIt @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { if (((name instanceof DirectValueActionItem)) && (((DirectValueActionItem) name).isString()) && (!IdentifiersDeobfuscation.isValidName(false, ((DirectValueActionItem) name).toStringNoQuotes(localData), "this", "super"))) { + HighlightData srcData = getSrcData(); + srcData.localName = name.toStringNoQuotes(localData); + IdentifiersDeobfuscation.appendObfuscatedIdentifier(((DirectValueActionItem) name).toStringNoQuotes(localData), writer); writer.append(" = "); return value.toString(writer, localData); @@ -86,6 +90,9 @@ public class SetVariableActionItem extends ActionItem implements SetTypeActionIt value.toString(writer, localData); return writer.append(")"); } + HighlightData srcData = getSrcData(); + srcData.localName = name.toStringNoQuotes(localData); + stripQuotes(name, localData, writer); writer.append(" = "); return value.toString(writer, localData); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/StoreRegisterActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/StoreRegisterActionItem.java index 4b2860223..6d5a3aaef 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/StoreRegisterActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/StoreRegisterActionItem.java @@ -20,7 +20,9 @@ import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphPart; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphSourceItemPos; @@ -77,7 +79,13 @@ public class StoreRegisterActionItem extends ActionItem implements SetTypeAction if (temporary) { value.toString(writer, localData); } else { + HighlightData srcData = getSrcData(); + srcData.localName = register.translate(); + srcData.regIndex = register.number; + if (define) { + srcData.declaration = true; + srcData.declaredType = DottedChain.ALL; writer.append("var "); } writer.append(register.translate()).append(" = "); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ClassActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ClassActionItem.java index eb2dc190c..4ee5ebc08 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ClassActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ClassActionItem.java @@ -153,6 +153,7 @@ public class ClassActionItem extends ActionItem implements Block { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.startClass(className.toStringNoQuotes(localData)); writer.append("class "); className.toStringNoQuotes(writer, localData); if (extendsOp != null) { @@ -204,7 +205,9 @@ public class ClassActionItem extends ActionItem implements Block { f.toString(writer, localData).newLine(); } - return writer.endBlock(); + writer.endBlock(); + writer.endClass(); + return writer; } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/InterfaceActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/InterfaceActionItem.java index 438c3e5d4..9790e8d50 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/InterfaceActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/InterfaceActionItem.java @@ -47,6 +47,7 @@ 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; @@ -60,7 +61,7 @@ public class InterfaceActionItem extends ActionItem { first = false; Action.getWithoutGlobal(ti).toStringNoQuotes(writer, localData); } - return writer.startBlock().endBlock(); + return writer.startBlock().endBlock().endClass(); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java index 8276ce747..679b5f4d5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java @@ -300,7 +300,7 @@ public class ActionScript2Parser { expectedType(SymbolType.CURLY_CLOSE); } - return new FunctionActionItem(null, null, functionName, paramNames, body, constantPool, -1, subvariables); + return new FunctionActionItem(null, null, functionName, paramNames, new HashMap<>() /*?*/, body, constantPool, -1, subvariables); } private GraphTargetItem traits(boolean isInterface, GraphTargetItem nameStr, GraphTargetItem extendsStr, List implementsStr, List variables) throws IOException, ActionParseException { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineFunction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineFunction.java index ef645b520..c36e4c5aa 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineFunction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineFunction.java @@ -154,7 +154,7 @@ public class ActionDefineFunction extends Action implements GraphSourceItemConta @Override public void translateContainer(List> content, GraphSourceItem lineStartItem, TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions) { - FunctionActionItem fti = new FunctionActionItem(this, lineStartItem, functionName, paramNames, content.get(0), constantPool, 1, new ArrayList<>()); + FunctionActionItem fti = new FunctionActionItem(this, lineStartItem, functionName, paramNames, getRegNames(), content.get(0), constantPool, 1, new ArrayList<>()); //ActionGraph.translateViaGraph(regNames, variables, functions, code, version) stack.push(fti); functions.put(functionName, fti); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf7/ActionDefineFunction2.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf7/ActionDefineFunction2.java index 8a15f0041..d1a8c27b4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf7/ActionDefineFunction2.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf7/ActionDefineFunction2.java @@ -294,7 +294,7 @@ public class ActionDefineFunction2 extends Action implements GraphSourceItemCont @Override public void translateContainer(List> content, GraphSourceItem lineStartItem, TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions) { - FunctionActionItem fti = new FunctionActionItem(this, lineStartItem, functionName, paramNames, content.get(0), constantPool, getFirstRegister(), new ArrayList<>()); + FunctionActionItem fti = new FunctionActionItem(this, lineStartItem, functionName, paramNames, getRegNames(), content.get(0), constantPool, getFirstRegister(), new ArrayList<>()); functions.put(functionName, fti); stack.push(fti); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/GraphTextWriter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/GraphTextWriter.java index ba8491cdb..3c3715559 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/GraphTextWriter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/GraphTextWriter.java @@ -77,10 +77,24 @@ public abstract class GraphTextWriter { return this; } + /** + * Highlights specified text as method/function + * + * @param name Function name + * @return GraphTextWriter + */ + public GraphTextWriter startFunction(String name) { + return this; + } + public GraphTextWriter endMethod() { return this; } + public GraphTextWriter endFunction() { + return this; + } + /** * Highlights specified text as class * @@ -91,6 +105,10 @@ public abstract class GraphTextWriter { return this; } + public GraphTextWriter startClass(String className) { + return this; + } + public GraphTextWriter endClass() { return this; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/HighlightedTextWriter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/HighlightedTextWriter.java index 3c095c8c4..be4f44013 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/HighlightedTextWriter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/HighlightedTextWriter.java @@ -114,11 +114,23 @@ public class HighlightedTextWriter extends GraphTextWriter { return start(data, HighlightType.METHOD); } + @Override + public HighlightedTextWriter startFunction(String name) { + HighlightData data = new HighlightData(); + data.localName = name; + return start(data, HighlightType.METHOD); + } + @Override public HighlightedTextWriter endMethod() { return end(HighlightType.METHOD); } + @Override + public HighlightedTextWriter endFunction() { + return end(HighlightType.METHOD); + } + /** * Highlights specified text as class by adding special tags * @@ -132,6 +144,13 @@ public class HighlightedTextWriter extends GraphTextWriter { return start(data, HighlightType.CLASS); } + @Override + public HighlightedTextWriter startClass(String className) { + HighlightData data = new HighlightData(); + data.localName = className; + return start(data, HighlightType.CLASS); + } + @Override public HighlightedTextWriter endClass() { return end(HighlightType.CLASS); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/hilight/Highlighting.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/hilight/Highlighting.java index 0095995d3..609f7c947 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/hilight/Highlighting.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/hilight/Highlighting.java @@ -190,6 +190,17 @@ public class Highlighting implements Serializable { return ret; } + public static List searchAllLocalNames(List list, String localName) { + List ret = new ArrayList<>(); + for (Highlighting h : list) { + if (localName.equals(h.getProperties().localName)) { + ret.add(h); + } + } + + return ret; + } + /** * Returns a string representation of the object * diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index 40cc70650..f031d922e 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -358,12 +358,12 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener decompiledHilights = new ArrayList<>(); + public List specialHighlights = new ArrayList<>(); + public List classHighlights = new ArrayList<>(); + public List methodHighlights = new ArrayList<>(); public List disassembledHilights = new ArrayList<>(); @@ -467,6 +474,9 @@ public class ActionPanel extends JPanel implements SearchListener tms = Highlighting.searchAllPos(methodHighlights, pos); + if (tms.isEmpty()) { + return -1; + } + for (Highlighting tm : tms) { + + List tm_tms = Highlighting.searchAllLocalNames(methodHighlights, tm.getProperties().localName); + //is it already declaration? + if (h.getProperties().declaration || (sh != null && sh.getProperties().declaration)) { + return -1; //no jump + } + + String lname = h.getProperties().localName; + if ("this".equals(lname)) { + Highlighting ch = Highlighting.searchPos(classHighlights, pos); + // int cindex = (int) ch.getProperties().index; + return ch.startPos; + } + + HighlightData hData = h.getProperties(); + HighlightData search = new HighlightData(); + search.declaration = hData.declaration; + //search.declaredType = hData.declaredType; + search.localName = hData.localName; + //search.specialValue = hData.specialValue; + if (search.isEmpty()) { + return -1; + } + search.declaration = true; + + for (Highlighting tm1 : tm_tms) { + Highlighting rh = Highlighting.search(decompiledHilights, search, tm1.startPos, tm1.startPos + tm1.len); + if (rh != null) { + return rh.startPos; + } + } + } + + return -1; + } + public ActionPanel(MainPanel mainPanel) { this.mainPanel = mainPanel; editor = new LineMarkedEditorPane(); editor.setEditable(false); decompiledEditor = new DebuggableEditorPane(); decompiledEditor.setEditable(false); + decompiledEditor.setLinkHandler(new LinkHandler() { + + @Override + public boolean isLink(Token token) { + int pos = token.start; + Highlighting h = Highlighting.searchPos(decompiledHilights, pos); + if (h != null) { + if (h.getProperties().localName != null && !h.getProperties().declaration) { + return getLocalDeclarationOfPos(pos) != -1; + } + } + return false; + } + + @Override + public void handleLink(Token token) { + int pos = token.start; + int tpos = getLocalDeclarationOfPos(pos); + if (tpos > -1) { + //System.err.println("goto " + tpos); + decompiledEditor.setCaretPosition(tpos); + } else { + //System.err.println("cannot handle"); + } + } + + @Override + public Highlighter.HighlightPainter linkPainter() { + return decompiledEditor.linkPainter(); + } + }); searchPanel = new SearchPanel<>(new FlowLayout(), this); diff --git a/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java b/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java index c5b2d51e3..fb98ef537 100644 --- a/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java @@ -39,6 +39,8 @@ import java.util.Map; import java.util.Objects; import java.util.SortedSet; import java.util.TreeSet; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; import javax.swing.plaf.TextUI; @@ -291,6 +293,37 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan } + public Token tokenAtPos(Point lastPos) { + Document d = getDocument(); + if (d instanceof SyntaxDocument) { + SyntaxDocument sd = (SyntaxDocument) d; + + //correction of token last character + int pos = viewToModel(lastPos); + Rectangle r; + try { + r = modelToView(pos); + if (lastPos.x < r.x) { + pos--; + } + } catch (BadLocationException ex) { + //ignore + } + Token t = sd.getTokenAt(pos); + + //Correction of token of length 1 character + if (pos > 0 && pos < d.getLength() - 1 && t != null && t.length == 1) { + Token tprev = sd.getTokenAt(pos - 1); + if (tprev == t) { + t = sd.getTokenAt(pos + 1); + } + } + + return t; + } + return null; + } + private class LinkAdapter extends MouseAdapter implements KeyListener { private Point lastPos = new Point(0, 0); @@ -320,38 +353,30 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan private void update() { if (ctrlDown) { - Document d = getDocument(); - if (d instanceof SyntaxDocument) { - SyntaxDocument sd = (SyntaxDocument) d; - int pos = viewToModel(lastPos); - if (pos <= 0) { - return; - } - Token t = sd.getTokenAt(pos); - if (t != lastUnderlined) { - if (t == null || lastUnderlined == null || !t.equals(lastUnderlined)) { - MyMarkers.removeMarkers(LineMarkedEditorPane.this, underLinePainter); + Token t = tokenAtPos(lastPos); - if (t != null && linkHandler.isLink(t)) { - lastUnderlined = t; - setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + if (t != lastUnderlined) { + if (t == null || lastUnderlined == null || !t.equals(lastUnderlined)) { + MyMarkers.removeMarkers(LineMarkedEditorPane.this, underLinePainter); + + if (t != null && linkHandler.isLink(t)) { + lastUnderlined = t; + setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - } else { - lastUnderlined = null; - } } else { lastUnderlined = null; } - } - - if (lastUnderlined != null) { - MyMarkers.markToken(LineMarkedEditorPane.this, lastUnderlined, underLinePainter); } else { - setCursor(Cursor.getDefaultCursor()); + lastUnderlined = null; } - repaint(); - } + + if (lastUnderlined != null) { + MyMarkers.markToken(LineMarkedEditorPane.this, lastUnderlined, underLinePainter); + } else { + setCursor(Cursor.getDefaultCursor()); + } + repaint(); } else { lastUnderlined = null; MyMarkers.removeMarkers(LineMarkedEditorPane.this, underLinePainter); @@ -363,12 +388,7 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan @Override public void mouseClicked(MouseEvent e) { if (ctrlDown) { - SyntaxDocument sd = (SyntaxDocument) getDocument(); - int pos = viewToModel(e.getPoint()); - if (pos < 0) { - return; - } - Token t = sd.getTokenAt(pos + 1); + Token t = tokenAtPos(lastPos); if (t != null && linkHandler.isLink(t)) { linkHandler.handleLink(t); }