AS1/2: Ctrl+click to declaration of variables, registers. Hilighting methods and classes

AS1/2: Debugger - Show registers
Fixed ctrl+click underline position
This commit is contained in:
Jindra Petřík
2015-12-05 10:53:43 +01:00
parent 8b7e754247
commit ec666b60e4
20 changed files with 321 additions and 64 deletions

View File

@@ -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<Highlighting> hilights = writer.instructionHilights;
List<Highlighting> methodHilights = writer.methodHilights;
List<Highlighting> classHilights = writer.classHilights;
List<Highlighting> 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<ScriptPack> 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<SWD.DebugRegisters> 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<Integer> curRegIndexes = new ArrayList<>(regNames.keySet());
List<String> 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<Integer> curRegIndexes = new ArrayList<>(regNames.keySet());
List<String> 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);

View File

@@ -29,9 +29,15 @@ public class CachedScript implements Serializable {
public String text;
public List<Highlighting> hilights;
public List<Highlighting> methodHilights;
public List<Highlighting> classHilights;
public List<Highlighting> specialHilights;
public CachedScript(String text, List<Highlighting> hilights) {
public CachedScript(String text, List<Highlighting> hilights, List<Highlighting> methodHilights, List<Highlighting> classHilights, List<Highlighting> specialHilights) {
this.text = text;
this.hilights = hilights;
this.methodHilights = methodHilights;
this.classHilights = classHilights;
this.specialHilights = specialHilights;
}
}

View File

@@ -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<GraphTargetItem> 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 {

View File

@@ -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 {

View File

@@ -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

View File

@@ -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<String> paramNames;
public Map<Integer, String> 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<String> paramNames, List<GraphTargetItem> actions, List<String> constants, int regStart, List<VariableActionItem> variables) {
public FunctionActionItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, String functionName, List<String> paramNames, Map<Integer, String> regNames, List<GraphTargetItem> actions, List<String> constants, int regStart, List<VariableActionItem> 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<String, Integer> 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

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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(" = ");

View File

@@ -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

View File

@@ -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

View File

@@ -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<GraphTargetItem> implementsStr, List<VariableActionItem> variables) throws IOException, ActionParseException {

View File

@@ -154,7 +154,7 @@ public class ActionDefineFunction extends Action implements GraphSourceItemConta
@Override
public void translateContainer(List<List<GraphTargetItem>> content, GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> 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);

View File

@@ -294,7 +294,7 @@ public class ActionDefineFunction2 extends Action implements GraphSourceItemCont
@Override
public void translateContainer(List<List<GraphTargetItem>> content, GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> 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);
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -190,6 +190,17 @@ public class Highlighting implements Serializable {
return ret;
}
public static List<Highlighting> searchAllLocalNames(List<Highlighting> list, String localName) {
List<Highlighting> 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
*