diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ParseException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ParseException.java index eb329bdcf..4b938f55b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ParseException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ParseException.java @@ -58,7 +58,7 @@ public abstract class ParseException extends Exception { * @param line Line number where the exception occurred */ public ParseException(String text, long line, long position) { - super(text + " on line " + line); + super(text + (line == -1 ? "" : " on line " + line)); this.line = line; this.text = text; this.position = position; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java index e98bce03b..25f12a018 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java @@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.simpleparser.Import; import com.jpexs.decompiler.flash.simpleparser.Namespace; import com.jpexs.decompiler.flash.simpleparser.SimpleParseException; import com.jpexs.decompiler.flash.simpleparser.SimpleParser; +import com.jpexs.decompiler.flash.simpleparser.TraitVarConstValueScope; import com.jpexs.decompiler.flash.simpleparser.Type; import com.jpexs.decompiler.flash.simpleparser.Variable; import com.jpexs.decompiler.flash.simpleparser.VariableOrScope; @@ -62,11 +63,11 @@ public class ActionScript3SimpleParser implements SimpleParser { return uniqLast; } - private void commands(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private void commands(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, int forinlevel, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { if (debugMode) { System.out.println("commands:"); } - while (command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables, abc)) { + while (command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forinlevel, true, variables, abc)) { } if (debugMode) { System.out.println("/commands"); @@ -85,12 +86,12 @@ public class ActionScript3SimpleParser implements SimpleParser { lexer.pushback(s); } - boolean t = name(errors, thisType, needsActivation, openedNamespaces, null, false, false, variables, importedClasses, abc); - applyType(errors, thisType, needsActivation, importedClasses, openedNamespaces, t, new HashMap<>(), false, false, variables, abc); + boolean t = name(errors, thisType, needsActivation, openedNamespaces, null, false, false, true, variables, importedClasses, abc); + applyType(errors, thisType, needsActivation, importedClasses, openedNamespaces, t, new HashMap<>(), false, false, true, variables, abc); return true; } - private boolean memberOrCall(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, boolean newcmds, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private boolean memberOrCall(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, boolean newcmds, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { if (debugMode) { System.out.println("memberOrCall:"); } @@ -103,16 +104,16 @@ public class ActionScript3SimpleParser implements SimpleParser { case NULL_DOT: case TYPENAME: lexer.pushback(s); - ret = member(errors, thisType, needsActivation, importedClasses, openedNamespaces, ret, registerVars, inFunction, inMethod, variables, abc); + ret = member(errors, thisType, needsActivation, importedClasses, openedNamespaces, ret, registerVars, inFunction, inMethod, isStatic, variables, abc); break; case FILTER: needsActivation.setVal(true); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, inMethod, variables, true, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, inMethod, variables, true, abc); expectedType(errors, SymbolType.PARENT_CLOSE); ret = true; break; case PARENT_OPEN: - call(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables, abc); + call(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, variables, abc); ret = true; break; case DESCENDANTS: @@ -149,7 +150,7 @@ public class ActionScript3SimpleParser implements SimpleParser { return ret; } - private boolean applyType(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, boolean obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private boolean applyType(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, boolean obj, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { boolean ret = obj; ParsedSymbol s = lex(); if (s.type == SymbolType.TYPENAME) { @@ -159,7 +160,7 @@ public class ActionScript3SimpleParser implements SimpleParser { //* } else { lexer.pushback(s); - expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, false, variables, abc); + expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, isStatic, false, variables, abc); } s = lex(); } while (s.type == SymbolType.COMMA); @@ -181,7 +182,7 @@ public class ActionScript3SimpleParser implements SimpleParser { return ret; } - private boolean member(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, boolean obj, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private boolean member(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, boolean obj, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { if (debugMode) { System.out.println("member:"); } @@ -202,11 +203,11 @@ public class ActionScript3SimpleParser implements SimpleParser { } if (s.type == SymbolType.TYPENAME) { lexer.pushback(s); - applyType(errors, thisType, needsActivation, importedClasses, openedNamespaces, ret, registerVars, inFunction, inMethod, variables, abc); + applyType(errors, thisType, needsActivation, importedClasses, openedNamespaces, ret, registerVars, inFunction, inMethod, isStatic, variables, abc); ret = true; s = lex(); } else if (s.type == SymbolType.BRACKET_OPEN) { - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); expectedType(errors, SymbolType.BRACKET_CLOSE); ret = true; s = lex(); @@ -222,7 +223,7 @@ public class ActionScript3SimpleParser implements SimpleParser { variables.add(new Variable(false, propName, propPosition)); s = lex(); if (s.type == SymbolType.BRACKET_OPEN) { - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); expectedType(errors, SymbolType.BRACKET_CLOSE); } else { expected(errors, s, lexer.yyline(), SymbolGroup.IDENTIFIER); @@ -246,7 +247,7 @@ public class ActionScript3SimpleParser implements SimpleParser { return ret; } - private boolean name(List errors, TypeItem thisType, Reference needsActivation, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, List importedClasses, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private boolean name(List errors, TypeItem thisType, Reference needsActivation, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, List variables, List importedClasses, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { ParsedSymbol s = lex(); String lastName = ""; @@ -309,7 +310,7 @@ public class ActionScript3SimpleParser implements SimpleParser { String nsprop = s.value.toString(); variables.add(new Variable(false, fullName + "::" + nsprop, s.position)); } else if (s.type == SymbolType.BRACKET_OPEN) { - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); expectedType(errors, SymbolType.BRACKET_CLOSE); } s = lex(); @@ -324,7 +325,7 @@ public class ActionScript3SimpleParser implements SimpleParser { lexer.pushback(new ParsedSymbol(s.position - 1, SymbolGroup.OPERATOR, SymbolType.ATTRIBUTE, "@")); lexer.pushback(new ParsedSymbol(s.position - 2, SymbolGroup.OPERATOR, SymbolType.DOT, ".")); } - ret = member(errors, thisType, needsActivation, importedClasses, openedNamespaces, ret, registerVars, inFunction, inMethod, variables, abc); + ret = member(errors, thisType, needsActivation, importedClasses, openedNamespaces, ret, registerVars, inFunction, inMethod, isStatic, variables, abc); } else { lexer.pushback(s); } @@ -373,14 +374,14 @@ public class ActionScript3SimpleParser implements SimpleParser { return ret; } - private void call(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private void call(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { //expected(SymbolType.PARENT_OPEN); //MUST BE HANDLED BY CALLER ParsedSymbol s = lex(); while (s.type != SymbolType.PARENT_CLOSE) { if (s.type != SymbolType.COMMA) { lexer.pushback(s); } - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); s = lex(); if (!expected(errors, s, lexer.yyline(), SymbolType.COMMA, SymbolType.PARENT_CLOSE)) { break; @@ -389,10 +390,10 @@ public class ActionScript3SimpleParser implements SimpleParser { } private void method(List errors, boolean outsidePackage, boolean isPrivate, boolean isInterface, boolean isNative, String customAccess, Reference needsActivation, List importedClasses, boolean override, boolean isFinal, TypeItem thisType, List openedNamespaces, boolean isStatic, String functionName, boolean isMethod, List variables, ABC abc, int methodNamePos) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { - function(errors, isInterface, isNative, needsActivation, importedClasses, thisType, openedNamespaces, functionName, isMethod, variables, abc, methodNamePos); + function(errors, isInterface, isNative, needsActivation, importedClasses, thisType, openedNamespaces, functionName, isMethod, variables, abc, methodNamePos, isStatic); } - private void function(List errors, boolean isInterface, boolean isNative, Reference needsActivation, List importedClasses, TypeItem thisType, List openedNamespaces, String functionName, boolean isMethod, List variables, ABC abc, int functionNamePos) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private void function(List errors, boolean isInterface, boolean isNative, Reference needsActivation, List importedClasses, TypeItem thisType, List openedNamespaces, String functionName, boolean isMethod, List variables, ABC abc, int functionNamePos, boolean isStatic) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { ParsedSymbol s; expectedType(errors, SymbolType.PARENT_OPEN); @@ -424,7 +425,7 @@ public class ActionScript3SimpleParser implements SimpleParser { //* } if (s.type == SymbolType.ASSIGN) { - expression(errors, thisType, new Reference<>(false), importedClasses, openedNamespaces, null, isMethod, isMethod, isMethod, variables, false, abc); + expression(errors, thisType, new Reference<>(false), importedClasses, openedNamespaces, null, isMethod, isMethod, isMethod, isStatic, variables, false, abc); s = lex(); } /*else if (!paramValues.isEmpty()) { @@ -464,13 +465,13 @@ public class ActionScript3SimpleParser implements SimpleParser { Reference needsActivation2 = new Reference<>(false); if (!isInterface && !isNative) { expectedType(errors, SymbolType.CURLY_OPEN); - commands(errors, thisType, needsActivation2, importedClasses, openedNamespaces, new Stack<>(), new HashMap<>(), new HashMap<>(), true, isMethod, 0, subvariables, abc); + commands(errors, thisType, needsActivation2, importedClasses, openedNamespaces, new Stack<>(), new HashMap<>(), new HashMap<>(), true, isMethod, isStatic, 0, subvariables, abc); expectedType(errors, SymbolType.CURLY_CLOSE); } else { expectedType(errors, SymbolType.SEMICOLON); } - FunctionScope fs = new FunctionScope(subvariables); + FunctionScope fs = new FunctionScope(subvariables, isStatic); variables.add(fs); } @@ -661,7 +662,7 @@ public class ActionScript3SimpleParser implements SimpleParser { } else { fname = s.value.toString(); } - traitVariables.add(new Variable(true, prefix + fname, fnamePos)); + traitVariables.add(new Variable(true, prefix + fname, fnamePos, isStatic)); if (fname.equals(classNameStr)) { //constructor if (isStatic) { errors.add(new SimpleParseException("Constructor cannot be static", lexer.yyline(), s.position)); @@ -722,7 +723,7 @@ public class ActionScript3SimpleParser implements SimpleParser { String nname = s.value.toString(); int npos = s.position; - traitVariables.add(new Variable(true, prefix + nname, npos)); + traitVariables.add(new Variable(true, prefix + nname, npos, isStatic)); s = lex(); if (s.type == SymbolType.ASSIGN) { @@ -753,7 +754,7 @@ public class ActionScript3SimpleParser implements SimpleParser { if (!expected(errors, s, lexer.yyline(), SymbolGroup.IDENTIFIER)) { break; } - traitVariables.add(new Variable(true, prefix + s.value.toString(), s.position)); + traitVariables.add(new Variable(true, prefix + s.value.toString(), s.position, isStatic)); s = lex(); if (s.type == SymbolType.NAMESPACESUFFIX) { @@ -769,7 +770,9 @@ public class ActionScript3SimpleParser implements SimpleParser { } if (s.type == SymbolType.ASSIGN) { - expression(errors, thisType, new Reference<>(false), importedClasses, openedNamespaces, new HashMap<>(), false, false, true, classVariables, false, abc); + List constVarVariables = new ArrayList<>(); + expression(errors, thisType, new Reference<>(false), importedClasses, openedNamespaces, new HashMap<>(), false, false, isStatic, true, constVarVariables, false, abc); + classVariables.add(new TraitVarConstValueScope(constVarVariables, isStatic)); s = lex(); } if (s.type != SymbolType.SEMICOLON) { @@ -782,7 +785,7 @@ public class ActionScript3SimpleParser implements SimpleParser { lexer.pushback(preSymbols.get(i)); } - boolean cmd = command(errors, null, cinitNeedsActivation, importedClasses, openedNamespaces, cinitLoops, cinitLoopLabels, new HashMap<>(), true, false, 0, false, classVariables, abc); + boolean cmd = command(errors, null, cinitNeedsActivation, importedClasses, openedNamespaces, cinitLoops, cinitLoopLabels, new HashMap<>(), true, false, true, 0, false, classVariables, abc); if (cmd) { //empty } else { @@ -1001,7 +1004,7 @@ public class ActionScript3SimpleParser implements SimpleParser { } if (s.type == SymbolType.ASSIGN) { - expression(errors, null, new Reference<>(false), importedClasses, openedNamespaces, new HashMap<>(), false, false, true, sinitVariables, false, abc); + expression(errors, null, new Reference<>(false), importedClasses, openedNamespaces, new HashMap<>(), false, false, true, true, sinitVariables, false, abc); s = lex(); } if (s.type != SymbolType.SEMICOLON) { @@ -1040,7 +1043,7 @@ public class ActionScript3SimpleParser implements SimpleParser { if (parseImportsUsages(errors, sinitVariables, importedClasses, openedNamespaces, abc)) { break; } - boolean cmd = command(errors, null, sinitNeedsActivation, importedClasses, openedNamespaces, sinitLoops, sinitLoopLabels, sinitRegisterVars, true, false, 0, false, sinitVariables, abc); + boolean cmd = command(errors, null, sinitNeedsActivation, importedClasses, openedNamespaces, sinitLoops, sinitLoopLabels, sinitRegisterVars, true, false, true, 0, false, sinitVariables, abc); if (cmd) { isEmpty = false; } else { @@ -1055,7 +1058,7 @@ public class ActionScript3SimpleParser implements SimpleParser { return !isEmpty; } - private void xmltag(List errors, TypeItem thisType, Reference usesVars, List openedTags, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private void xmltag(List errors, TypeItem thisType, Reference usesVars, List openedTags, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { ParsedSymbol s; StringBuilder sb = new StringBuilder(); loop: @@ -1066,7 +1069,7 @@ public class ActionScript3SimpleParser implements SimpleParser { switch (s.type) { case XML_ATTRNAMEVAR_BEGIN: // {...}= add usesVars.setVal(true); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); expectedType(errors, SymbolType.CURLY_CLOSE); expectedType(errors, SymbolType.ASSIGN); sb.append("="); @@ -1075,21 +1078,21 @@ public class ActionScript3SimpleParser implements SimpleParser { case XML_ATTRVALVAR_BEGIN: // ={...} esc_xattr usesVars.setVal(true); sb.append("\""); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); sb.append("\""); expectedType(errors, SymbolType.CURLY_CLOSE); lexer.yybegin(ActionScriptLexer.XMLOPENTAG); break; case XML_VAR_BEGIN: // {...} esc_xelem usesVars.setVal(true); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); expectedType(errors, SymbolType.CURLY_CLOSE); lexer.yybegin(ActionScriptLexer.XML); break; case XML_FINISHVARTAG_BEGIN: // add usesVars.setVal(true); sb.append(" add - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); expectedType(errors, SymbolType.CURLY_CLOSE); lexer.yybegin(ActionScriptLexer.XMLOPENTAG); sub.add("*"); sb.append("<"); - xmltag(errors, thisType, subusesvars, sub, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables, abc); + xmltag(errors, thisType, subusesvars, sub, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, variables, abc); break; case XML_STARTTAG_BEGIN: // sub.add(s.value.toString().trim().substring(1)); //remove < from beginning - xmltag(errors, thisType, subusesvars, sub, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables, abc); + xmltag(errors, thisType, subusesvars, sub, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, variables, abc); sb.append(s.value.toString()); break; case XML_FINISHTAG: @@ -1145,9 +1148,9 @@ public class ActionScript3SimpleParser implements SimpleParser { } while (!openedTags.isEmpty()); } - private boolean xml(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private boolean xml(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { List openedTags = new ArrayList<>(); - xmltag(errors, thisType, new Reference<>(false), openedTags, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables, abc); + xmltag(errors, thisType, new Reference<>(false), openedTags, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, variables, abc); lexer.setEnableWhiteSpace(true); lexer.begin(ActionScriptLexer.YYINITIAL); ParsedSymbol s = lexer.lex(); @@ -1160,7 +1163,7 @@ public class ActionScript3SimpleParser implements SimpleParser { return true; } - private boolean command(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, int forinlevel, boolean mustBeCommand, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private boolean command(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, Stack loops, Map loopLabels, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, int forinlevel, boolean mustBeCommand, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { LexBufferer buf = new LexBufferer(); lexer.addListener(buf); boolean ret = false; @@ -1192,7 +1195,7 @@ public class ActionScript3SimpleParser implements SimpleParser { } else { expectedType(errors, SymbolType.NAMESPACE); expectedType(errors, SymbolType.ASSIGN); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); ret = true; //TODO: use dxns for attribute namespaces instead of dxnslate } @@ -1206,14 +1209,14 @@ public class ActionScript3SimpleParser implements SimpleParser { case WITH: needsActivation.setVal(true); expectedType(errors, SymbolType.PARENT_OPEN); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); /*if (!isNameOrProp(wvar)) { errors.add(new SimpleParseException("Not a property or name", lexer.yyline())); }*/ expectedType(errors, SymbolType.PARENT_CLOSE); expectedType(errors, SymbolType.CURLY_OPEN); List withVars = new ArrayList<>(); - commands(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, withVars, abc); + commands(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forinlevel, withVars, abc); variables.addAll(withVars); expectedType(errors, SymbolType.CURLY_CLOSE); //FIXME? @@ -1223,7 +1226,7 @@ public class ActionScript3SimpleParser implements SimpleParser { s = lexer.lex(); expected(errors, s, lexer.yyline(), SymbolGroup.IDENTIFIER); needsActivation.setVal(true); - function(errors, false, false, needsActivation, importedClasses, thisType, openedNamespaces, s.value.toString(), false, variables, abc, s.position); + function(errors, false, false, needsActivation, importedClasses, thisType, openedNamespaces, s.value.toString(), false, variables, abc, s.position, true /*???*/); ret = true; break; case VAR: @@ -1244,7 +1247,7 @@ public class ActionScript3SimpleParser implements SimpleParser { } if (s.type == SymbolType.ASSIGN) { - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); variables.add(new Variable(true, varIdentifier, varPos)); ret = true; } else { @@ -1254,14 +1257,14 @@ public class ActionScript3SimpleParser implements SimpleParser { } break; case CURLY_OPEN: - commands(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables, abc); + commands(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forinlevel, variables, abc); expectedType(errors, SymbolType.CURLY_CLOSE); ret = true; break; case SUPER: //constructor call ParsedSymbol ss2 = lex(); if (ss2.type == SymbolType.PARENT_OPEN) { - call(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables, abc); + call(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, variables, abc); ret = true; } else { //no constructor call, but it could be calling parent methods... => handle in expression lexer.pushback(ss2); @@ -1270,12 +1273,12 @@ public class ActionScript3SimpleParser implements SimpleParser { break; case IF: expectedType(errors, SymbolType.PARENT_OPEN); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); expectedType(errors, SymbolType.PARENT_CLOSE); - command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables, abc); + command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forinlevel, true, variables, abc); s = lex(); if (s.type == SymbolType.ELSE) { - command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables, abc); + command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forinlevel, true, variables, abc); } else { lexer.pushback(s); } @@ -1283,14 +1286,14 @@ public class ActionScript3SimpleParser implements SimpleParser { break; case WHILE: expectedType(errors, SymbolType.PARENT_OPEN); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, true, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, true, abc); expectedType(errors, SymbolType.PARENT_CLOSE); Loop wloop = new Loop(uniqId(), null, null); if (loopLabel != null) { loopLabels.put(wloop, loopLabel); } loops.push(wloop); - command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables, abc); + command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forinlevel, true, variables, abc); loops.pop(); ret = true; break; @@ -1300,11 +1303,11 @@ public class ActionScript3SimpleParser implements SimpleParser { if (loopLabel != null) { loopLabels.put(dloop, loopLabel); } - command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables, abc); + command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forinlevel, true, variables, abc); expectedType(errors, SymbolType.WHILE); expectedType(errors, SymbolType.PARENT_OPEN); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, true, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, true, abc); expectedType(errors, SymbolType.PARENT_CLOSE); loops.pop(); ret = true; @@ -1317,7 +1320,7 @@ public class ActionScript3SimpleParser implements SimpleParser { s = lex(); } expected(errors, s, lexer.yyline(), SymbolType.PARENT_OPEN); - command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, false, variables, abc); + command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forinlevel, false, variables, abc); Loop floop = new Loop(uniqId(), null, null); loops.push(floop); if (loopLabel != null) { @@ -1327,15 +1330,15 @@ public class ActionScript3SimpleParser implements SimpleParser { s = lex(); if (!s.isType(SymbolType.PARENT_CLOSE)) { lexer.pushback(s); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); expectedType(errors, SymbolType.SEMICOLON); - command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables, abc); + command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forinlevel, true, variables, abc); } else { lexer.pushback(s); } } expectedType(errors, SymbolType.PARENT_CLOSE); - command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forin ? forinlevel + 1 : forinlevel, true, variables, abc); + command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forin ? forinlevel + 1 : forinlevel, true, variables, abc); loops.pop(); ret = true; break; @@ -1346,20 +1349,20 @@ public class ActionScript3SimpleParser implements SimpleParser { loopLabels.put(sloop, loopLabel); } expectedType(errors, SymbolType.PARENT_OPEN); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); expectedType(errors, SymbolType.PARENT_CLOSE); expectedType(errors, SymbolType.CURLY_OPEN); s = lex(); while (s.type == SymbolType.CASE || s.type == SymbolType.DEFAULT) { while (s.type == SymbolType.CASE || s.type == SymbolType.DEFAULT) { if (s.type != SymbolType.DEFAULT) { - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, true, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, true, abc); } expectedType(errors, SymbolType.COLON); s = lex(); } lexer.pushback(s); - commands(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, variables, abc); + commands(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forinlevel, variables, abc); s = lex(); } expected(errors, s, lexer.yyline(), SymbolType.CURLY_CLOSE); @@ -1425,12 +1428,12 @@ public class ActionScript3SimpleParser implements SimpleParser { ret = true; break; case RETURN: - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, true, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, true, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); ret = true; break; case TRY: needsActivation.setVal(true); - command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables, abc); + command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forinlevel, true, variables, abc); s = lex(); boolean found = false; while (s.type == SymbolType.CATCH) { @@ -1446,14 +1449,14 @@ public class ActionScript3SimpleParser implements SimpleParser { expectedType(errors, SymbolType.PARENT_CLOSE); List catchVars = new ArrayList<>(); expectedType(errors, SymbolType.CURLY_OPEN); - commands(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, catchVars, abc); + commands(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forinlevel, catchVars, abc); expectedType(errors, SymbolType.CURLY_CLOSE); variables.add(new CatchScope(new Variable(true, enamestr, ePos), catchVars)); s = lex(); found = true; } if (s.type == SymbolType.FINALLY) { - command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables, abc); + command(errors, thisType, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, isStatic, forinlevel, true, variables, abc); found = true; s = lex(); } @@ -1464,7 +1467,7 @@ public class ActionScript3SimpleParser implements SimpleParser { ret = true; break; case THROW: - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); ret = true; break; default: @@ -1472,7 +1475,7 @@ public class ActionScript3SimpleParser implements SimpleParser { return true; } lexer.pushback(s); - ret = expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, true, abc); + ret = expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, true, abc); if (debugMode) { System.out.println("/command"); } @@ -1484,7 +1487,7 @@ public class ActionScript3SimpleParser implements SimpleParser { lexer.removeListener(buf); if (!ret) { //can be popped expression buf.pushAllBack(lexer); - ret = expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + ret = expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); } s = lex(); if ((s != null) && (s.type != SymbolType.SEMICOLON)) { @@ -1495,7 +1498,7 @@ public class ActionScript3SimpleParser implements SimpleParser { } - private void brackets(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private void brackets(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { ParsedSymbol s = lex(); int arrCnt = 0; if (s.type == SymbolType.BRACKET_OPEN) { @@ -1506,7 +1509,7 @@ public class ActionScript3SimpleParser implements SimpleParser { lexer.pushback(s); } arrCnt++; - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); s = lex(); if (!s.isType(SymbolType.COMMA, SymbolType.BRACKET_CLOSE)) { expected(errors, s, lexer.yyline(), SymbolType.COMMA, SymbolType.BRACKET_CLOSE); @@ -1517,19 +1520,19 @@ public class ActionScript3SimpleParser implements SimpleParser { } } - private boolean expression(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables, boolean allowComma, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { - return expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, allowRemainder, variables, allowComma, abc); + private boolean expression(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, boolean allowRemainder, List variables, boolean allowComma, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + return expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, isStatic, allowRemainder, variables, allowComma, abc); } - private boolean expression(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables, boolean allowComma, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private boolean expression(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, boolean allowRemainder, List variables, boolean allowComma, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { ParsedSymbol symb; do { - boolean prim = expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, allowRemainder, variables, abc); + boolean prim = expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, isStatic, allowRemainder, variables, abc); if (!prim) { return false; } - expression1(errors, prim, GraphTargetItem.NOPRECEDENCE, thisType, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, allowRemainder, variables, abc); + expression1(errors, prim, GraphTargetItem.NOPRECEDENCE, thisType, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, isStatic, allowRemainder, variables, abc); symb = lex(); } while (allowComma && symb != null && symb.type == SymbolType.COMMA); if (symb != null) { @@ -1585,7 +1588,7 @@ public class ActionScript3SimpleParser implements SimpleParser { return lookahead; } - private boolean expression1(List errors, boolean lhs, int min_precedence, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private boolean expression1(List errors, boolean lhs, int min_precedence, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, boolean allowRemainder, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { if (debugMode) { System.out.println("expression1:"); } @@ -1606,14 +1609,14 @@ public class ActionScript3SimpleParser implements SimpleParser { if (debugMode) { System.out.println("ternar-middle:"); } - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, allowRemainder, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, allowRemainder, variables, false, abc); expectedType(errors, SymbolType.COLON); if (debugMode) { System.out.println("/ternar-middle"); } } - rhs = expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, allowRemainder, variables, abc); + rhs = expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, isStatic, allowRemainder, variables, abc); if (!rhs) { lexer.pushback(op); break; @@ -1622,7 +1625,7 @@ public class ActionScript3SimpleParser implements SimpleParser { lookahead = peekExprToken(); while ((lookahead.type.isBinary() && lookahead.type.getPrecedence() < /* > on wiki */ op.type.getPrecedence()) || (lookahead.type.isRightAssociative() && lookahead.type.getPrecedence() == op.type.getPrecedence())) { - rhs = expression1(errors, rhs, lookahead.type.getPrecedence(), thisType, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, allowRemainder, variables, abc); + rhs = expression1(errors, rhs, lookahead.type.getPrecedence(), thisType, needsActivation, importedClasses, openedNamespaces, allowEmpty, registerVars, inFunction, inMethod, isStatic, allowRemainder, variables, abc); lookahead = peekExprToken(); } @@ -1678,7 +1681,7 @@ public class ActionScript3SimpleParser implements SimpleParser { } //??? /*if (lhs instanceof ParenthesisItem) { - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, allowRemainder, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, allowRemainder, variables, false, abc); }*/ if (debugMode) { @@ -1687,7 +1690,7 @@ public class ActionScript3SimpleParser implements SimpleParser { return lhs; } - private boolean expressionPrimary(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean allowRemainder, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private boolean expressionPrimary(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, boolean allowEmpty, HashMap registerVars, boolean inFunction, boolean inMethod, boolean isStatic, boolean allowRemainder, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { if (debugMode) { System.out.println("primary:"); } @@ -1700,35 +1703,35 @@ public class ActionScript3SimpleParser implements SimpleParser { switch ("" + s.value) { //AS3 case "hasnext": - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); expectedType(errors, SymbolType.COMMA); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); ret = true; break; case "newactivation": ret = true; break; case "nextname": - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); expectedType(errors, SymbolType.COMMA); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); ret = true; allowMemberOrCall = true; break; case "nextvalue": - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); expectedType(errors, SymbolType.COMMA); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); ret = true; allowMemberOrCall = true; break; //Both ASs case "dup": - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); ret = true; break; case "push": - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); ret = true; break; case "pop": @@ -1756,19 +1759,19 @@ public class ActionScript3SimpleParser implements SimpleParser { case XML_CDATA: case XML_COMMENT: lexer.pushback(s); - ret = xml(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables, abc); + ret = xml(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, variables, abc); break; case STRING: ret = true; allowMemberOrCall = true; break; case NEGATE: - expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, false, variables, abc); + expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, isStatic, false, variables, abc); ret = true; break; case PLUS: - expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, true, variables, abc); + expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, isStatic, true, variables, abc); ret = true; break; case MINUS: @@ -1783,12 +1786,12 @@ public class ActionScript3SimpleParser implements SimpleParser { ret = true; } else { lexer.pushback(s); - expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, true, variables, abc); + expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, isStatic, true, variables, abc); ret = true; } break; case TYPEOF: - expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, false, variables, abc); + expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, isStatic, false, variables, abc); ret = true; break; case TRUE: @@ -1814,11 +1817,11 @@ public class ActionScript3SimpleParser implements SimpleParser { expected(errors, s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.STRING, SymbolType.INTEGER, SymbolType.DOUBLE, SymbolType.PARENT_OPEN); if (s.type == SymbolType.PARENT_OPEN) { //special for obfuscated SWFs - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, allowRemainder, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, allowRemainder, variables, false, abc); expectedType(errors, SymbolType.PARENT_CLOSE); } expectedType(errors, SymbolType.COLON); - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, allowRemainder, variables, false, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, allowRemainder, variables, false, abc); s = lex(); if (!s.isType(SymbolType.COMMA, SymbolType.CURLY_CLOSE)) { @@ -1830,7 +1833,7 @@ public class ActionScript3SimpleParser implements SimpleParser { break; case BRACKET_OPEN: //Array literal or just brackets lexer.pushback(s); - brackets(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables, abc); + brackets(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, variables, abc); ret = true; allowMemberOrCall = true; break; @@ -1845,7 +1848,7 @@ public class ActionScript3SimpleParser implements SimpleParser { lexer.pushback(s); } needsActivation.setVal(true); - function(errors, false, false, needsActivation, importedClasses, thisType, openedNamespaces, fname, false, variables, abc, fnamePos); + function(errors, false, false, needsActivation, importedClasses, thisType, openedNamespaces, fname, false, variables, abc, fnamePos, true /*???*/); ret = true; allowMemberOrCall = true; break; @@ -1881,30 +1884,30 @@ public class ActionScript3SimpleParser implements SimpleParser { //parse again as method call lexer.yypushbackstr(lexer.yytext().substring("float4".length())); lexer.pushback(new ParsedSymbol(lexer.yychar() /*???*/, SymbolGroup.IDENTIFIER, SymbolType.IDENTIFIER, "float4")); - ret = name(errors, thisType, needsActivation, openedNamespaces, registerVars, inFunction, inMethod, variables, importedClasses, abc); + ret = name(errors, thisType, needsActivation, openedNamespaces, registerVars, inFunction, inMethod, isStatic, variables, importedClasses, abc); } else { ret = true; //new Float4ValueAVM2Item(null, null, (Float4) s.value); } allowMemberOrCall = true; break; case DELETE: - expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, true, variables, abc); + expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, isStatic, true, variables, abc); ret = true; break; case INCREMENT: case DECREMENT: //preincrement - expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, false/*?*/, variables, abc); + expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, isStatic, false/*?*/, variables, abc); /*if (!isNameOrProp(varincdec)) { errors.add(new SimpleParseException("Not a property or name", lexer.yyline())); }*/ ret = true; break; case NOT: - expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, false, variables, abc); + expressionPrimary(errors, thisType, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, isStatic, false, variables, abc); ret = true; break; case PARENT_OPEN: - expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, true, abc); + expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, true, abc); expectedType(errors, SymbolType.PARENT_CLOSE); /*if (ret.value == null) { errors.add(new SimpleParseException("Expression in parenthesis expected", lexer.yyline())); @@ -1929,7 +1932,7 @@ public class ActionScript3SimpleParser implements SimpleParser { lexer.pushback(s); } needsActivation.setVal(true); - function(errors, false, false, needsActivation, importedClasses, thisType, openedNamespaces, ffname, false, variables, abc, ffnamePos); + function(errors, false, false, needsActivation, importedClasses, thisType, openedNamespaces, ffname, false, variables, abc, ffnamePos, isStatic); ret = true; } else if (s.type == SymbolType.LOWER_THAN) { type(errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc); @@ -1937,22 +1940,22 @@ public class ActionScript3SimpleParser implements SimpleParser { s = lex(); expected(errors, s, lexer.yyline(), SymbolType.BRACKET_OPEN); lexer.pushback(s); - brackets(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables, abc); + brackets(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, variables, abc); ret = true; } else if (s.type == SymbolType.PARENT_OPEN) { - boolean newvar = expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false, abc); - applyType(errors, thisType, needsActivation, importedClasses, openedNamespaces, newvar, registerVars, inFunction, inMethod, variables, abc); + boolean newvar = expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); + applyType(errors, thisType, needsActivation, importedClasses, openedNamespaces, newvar, registerVars, inFunction, inMethod, isStatic, variables, abc); expectedType(errors, SymbolType.PARENT_CLOSE); expectedType(errors, SymbolType.PARENT_OPEN); - call(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables, abc); + call(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, variables, abc); ret = true; } else { lexer.pushback(s); - boolean newvar = name(errors, thisType, needsActivation, openedNamespaces, registerVars, inFunction, inMethod, variables, importedClasses, abc); - applyType(errors, thisType, needsActivation, importedClasses, openedNamespaces, newvar, registerVars, inFunction, inMethod, variables, abc); + boolean newvar = name(errors, thisType, needsActivation, openedNamespaces, registerVars, inFunction, inMethod, isStatic, variables, importedClasses, abc); + applyType(errors, thisType, needsActivation, importedClasses, openedNamespaces, newvar, registerVars, inFunction, inMethod, isStatic, variables, abc); expectedType(errors, SymbolType.PARENT_OPEN); - call(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables, abc); + call(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, variables, abc); ret = true; } allowMemberOrCall = true; @@ -1962,14 +1965,14 @@ public class ActionScript3SimpleParser implements SimpleParser { case SUPER: case ATTRIBUTE: lexer.pushback(s); - ret = name(errors, thisType, needsActivation, openedNamespaces, registerVars, inFunction, inMethod, variables, importedClasses, abc); + ret = name(errors, thisType, needsActivation, openedNamespaces, registerVars, inFunction, inMethod, isStatic, variables, importedClasses, abc); allowMemberOrCall = true; break; default: lexer.pushback(s); } if (allowMemberOrCall && ret) { - ret = memberOrCall(errors, thisType, needsActivation, importedClasses, openedNamespaces, ret, registerVars, inFunction, inMethod, variables, abc); + ret = memberOrCall(errors, thisType, needsActivation, importedClasses, openedNamespaces, ret, registerVars, inFunction, inMethod, isStatic, variables, abc); } if (debugMode) { System.out.println("/primary"); @@ -2162,9 +2165,7 @@ public class ActionScript3SimpleParser implements SimpleParser { //Logger.getLogger(ActionScript3SimpleParser.class.getName()).log(Level.SEVERE, null, ex); throw new SimpleParseException(str, ex.line); } - Map varNameToDefinitionPosition = new LinkedHashMap<>(); - - SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, varNameToDefinitionPosition); + SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors); } /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java index 628ceac83..b4689dd75 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java @@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.simpleparser.ClassScope; import com.jpexs.decompiler.flash.simpleparser.FunctionScope; import com.jpexs.decompiler.flash.simpleparser.SimpleParseException; import com.jpexs.decompiler.flash.simpleparser.SimpleParser; +import com.jpexs.decompiler.flash.simpleparser.TraitVarConstValueScope; import com.jpexs.decompiler.flash.simpleparser.Type; import com.jpexs.decompiler.flash.simpleparser.Variable; import com.jpexs.decompiler.flash.simpleparser.VariableOrScope; @@ -160,7 +161,7 @@ public class ActionScript2SimpleParser implements SimpleParser { return ret; } - private FunctionScope function(List errors, boolean withBody, String functionName, int functionNamePosition, boolean isMethod, List variables, boolean inTellTarget, Reference hasEval) throws IOException, InterruptedException, SimpleParseException, ActionParseException { + private FunctionScope function(List errors, boolean withBody, String functionName, int functionNamePosition, boolean isMethod, List variables, boolean inTellTarget, Reference hasEval, boolean isStatic) throws IOException, InterruptedException, SimpleParseException, ActionParseException { ParsedSymbol s; expectedType(errors, SymbolType.PARENT_OPEN); s = lex(); @@ -185,7 +186,7 @@ public class ActionScript2SimpleParser implements SimpleParser { if (!s.isType(SymbolType.COMMA, SymbolType.PARENT_CLOSE)) { if (!expected(errors, s, lexer.yyline(), SymbolType.COMMA, SymbolType.PARENT_CLOSE)) { break; - } + } } } List subvariables = new ArrayList<>(); @@ -209,7 +210,7 @@ public class ActionScript2SimpleParser implements SimpleParser { hasEval.setVal(true); } - return new FunctionScope(subvariables); + return new FunctionScope(subvariables, isStatic); } private boolean traits(List errors, boolean isInterface, String className, List variables, boolean inTellTarget, Reference hasEval) throws IOException, InterruptedException, SimpleParseException, ActionParseException { @@ -217,7 +218,7 @@ public class ActionScript2SimpleParser implements SimpleParser { ParsedSymbol s; List traitVariables = new ArrayList<>(); - + looptrait: while (true) { boolean isStatic = false; @@ -240,14 +241,14 @@ public class ActionScript2SimpleParser implements SimpleParser { if (expectedIdentifier(errors, s, lexer.yyline())) { if (!isInterface) { - variables.add(function(errors, !isInterface, isStatic ? className + "." + s.value.toString() : "this." + s.value.toString(), isStatic ? -1 : s.position, true, traitVariables, inTellTarget, hasEval)); + variables.add(function(errors, !isInterface, isStatic ? className + "." + s.value.toString() : "this." + s.value.toString(), isStatic ? -1 : s.position, true, traitVariables, inTellTarget, hasEval, isStatic)); } } break; case VAR: s = lex(); if (expectedIdentifier(errors, s, lexer.yyline())) { - traitVariables.add(new Variable(true, isStatic ? className + "." + s.value.toString() : "this." + s.value.toString(), s.position)); + traitVariables.add(new Variable(true, isStatic ? className + "." + s.value.toString() : "this." + s.value.toString(), s.position, isStatic)); } s = lex(); if (s.type == SymbolType.COLON) { @@ -255,7 +256,9 @@ public class ActionScript2SimpleParser implements SimpleParser { s = lex(); } if (s.type == SymbolType.ASSIGN) { - expression(errors, false, false, false, true, variables, false, hasEval); + List subVariables = new ArrayList<>(); + expression(errors, false, false, false, true, subVariables, false, hasEval); + variables.add(new TraitVarConstValueScope(subVariables, isStatic)); s = lex(); } if (s.type != SymbolType.SEMICOLON) { @@ -268,7 +271,7 @@ public class ActionScript2SimpleParser implements SimpleParser { } } - + variables.addAll(0, traitVariables); return true; @@ -804,7 +807,7 @@ public class ActionScript2SimpleParser implements SimpleParser { case FUNCTION: s = lexer.lex(); if (expectedIdentifier(errors, s, lexer.yyline())) { - variables.add(function(errors, true, s.value.toString(), s.position, false, variables, inTellTarget, hasEval)); + variables.add(function(errors, true, s.value.toString(), s.position, false, variables, inTellTarget, hasEval, false)); } break; case VAR: @@ -1394,7 +1397,7 @@ public class ActionScript2SimpleParser implements SimpleParser { } else { lexer.pushback(s); } - variables.add(function(errors, true, fname, fnamePos, false, variables, inTellTarget, hasEval)); + variables.add(function(errors, true, fname, fnamePos, false, variables, inTellTarget, hasEval, false)); ret = true; allowMemberOrCall = true; break; @@ -1552,8 +1555,6 @@ public class ActionScript2SimpleParser implements SimpleParser { ) throws SimpleParseException, IOException, InterruptedException { List vars = new ArrayList<>(); - Map varNameToDefinitionPosition = new LinkedHashMap<>(); - try { lexer = new ActionScriptLexer(new StringReader(str)); if (swfVersion >= ActionScriptLexer.SWF_VERSION_CASE_SENSITIVE) { @@ -1628,20 +1629,20 @@ public class ActionScript2SimpleParser implements SimpleParser { inOnHandler = true; } else { lexer.pushback(symb); - } + } Reference hasEval = new Reference<>(false); commands(errors, false, false, 0, false, vars, hasEval); - + if (inOnHandler) { expectedType(errors, SymbolType.CURLY_CLOSE); - } + } if (lexer.lex().type != SymbolType.EOF) { errors.add(new SimpleParseException("Parsing finished before end of the file", lexer.yyline(), lexer.yychar())); } } catch (ActionParseException ex) { errors.add(new SimpleParseException(ex.getMessage(), ex.line, ex.position)); } - SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, varNameToDefinitionPosition); + SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors); } private void versionRequired(List errors, ParsedSymbol s, int min) throws SimpleParseException { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/FunctionScope.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/FunctionScope.java index 118f02d12..bb678267b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/FunctionScope.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/FunctionScope.java @@ -26,9 +26,15 @@ import java.util.List; public class FunctionScope implements Scope { private final List privateItems; + private final boolean isStatic; - public FunctionScope(List functionBody) { + public FunctionScope(List functionBody, boolean isStatic) { this.privateItems = functionBody; + this.isStatic = isStatic; + } + + public boolean isStatic() { + return isStatic; } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/SimpleParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/SimpleParser.java index 451f3bd93..eddd8c30d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/SimpleParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/SimpleParser.java @@ -51,60 +51,132 @@ public interface SimpleParser { List sharedVariables, Map> definitionPosToReferences, Map referenceToDefinition, - Map parentVarNameToDefinitionPosition + List errors + ) { + parseVariablesList(privateVariables, sharedVariables, definitionPosToReferences, referenceToDefinition, new LinkedHashMap<>(), new LinkedHashMap<>(), new LinkedHashMap<>(), true, errors); + } + + public static void parseVariablesList( + List privateVariables, + List sharedVariables, + Map> definitionPosToReferences, + Map referenceToDefinition, + Map parentVarFullNameToDefinitionPosition, + Map parentVarNameToDefinitionPosition, + Map positionToStatic, + boolean isStatic, + List errors ) { Map privateVarNameToDefinitionPosition = new LinkedHashMap<>(); privateVarNameToDefinitionPosition.putAll(parentVarNameToDefinitionPosition); + Map privateVarFullNameToDefinitionPosition = new LinkedHashMap<>(); + privateVarFullNameToDefinitionPosition.putAll(parentVarFullNameToDefinitionPosition); + for (VariableOrScope vt : privateVariables) { if (vt instanceof Variable) { Variable v = (Variable) vt; if (v.definition) { - privateVarNameToDefinitionPosition.put(v.name, v.position); + privateVarFullNameToDefinitionPosition.put(v.name, v.position); + privateVarNameToDefinitionPosition.put(v.getLastName(), v.position); definitionPosToReferences.put(v.position, new ArrayList<>()); + positionToStatic.put(v.position, v.isStatic != null ? v.isStatic : isStatic); } else { - if (!privateVarNameToDefinitionPosition.containsKey(v.name)) { - parentVarNameToDefinitionPosition.put(v.name, -v.position - 1); - privateVarNameToDefinitionPosition.put(v.name, -v.position - 1); + if (!privateVarFullNameToDefinitionPosition.containsKey(v.name) + && !privateVarNameToDefinitionPosition.containsKey(v.getFirstName())) { + parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); + parentVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1); + privateVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); + privateVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1); definitionPosToReferences.put(-v.position - 1, new ArrayList<>()); definitionPosToReferences.get(-v.position - 1).add(v.position); referenceToDefinition.put(v.position, -v.position - 1); } else { - int definitionPos = privateVarNameToDefinitionPosition.get(v.name); - definitionPosToReferences.get(definitionPos).add(v.position); - referenceToDefinition.put(v.position, definitionPos); + + if ("this".equals(v.name) && isStatic) { + errors.add(new SimpleParseException("Cannot use this in static context", -1, v.position)); + } else { + int definitionPos; + if (privateVarFullNameToDefinitionPosition.containsKey(v.name)) { + definitionPos = privateVarFullNameToDefinitionPosition.get(v.name); + } else { + definitionPos = privateVarNameToDefinitionPosition.get(v.getFirstName()); + } + boolean staticDefinition = definitionPos >= 0 ? positionToStatic.get(definitionPos) : true; + if (!(!staticDefinition && isStatic)) { + definitionPosToReferences.get(definitionPos).add(v.position); + referenceToDefinition.put(v.position, definitionPos); + } else { + errors.add(new SimpleParseException("Cannot reference instance variable from static context", -1, v.position)); + } + } } } } if (vt instanceof Scope) { Scope vs = (Scope) vt; - parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarNameToDefinitionPosition); + boolean subStatic = isStatic; + if (vs instanceof FunctionScope) { + subStatic = ((FunctionScope) vs).isStatic(); + } + if (vs instanceof TraitVarConstValueScope) { + subStatic = ((TraitVarConstValueScope) vs).isStatic(); + } + parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors); } } for (VariableOrScope vt : sharedVariables) { if (vt instanceof Variable) { Variable v = (Variable) vt; if (v.definition) { - parentVarNameToDefinitionPosition.put(v.name, v.position); - privateVarNameToDefinitionPosition.put(v.name, v.position); + parentVarFullNameToDefinitionPosition.put(v.name, v.position); + parentVarNameToDefinitionPosition.put(v.getLastName(), v.position); + privateVarFullNameToDefinitionPosition.put(v.name, v.position); + privateVarNameToDefinitionPosition.put(v.getLastName(), v.position); definitionPosToReferences.put(v.position, new ArrayList<>()); + positionToStatic.put(v.position, v.isStatic != null ? v.isStatic : isStatic); } else { - if (!privateVarNameToDefinitionPosition.containsKey(v.name)) { - parentVarNameToDefinitionPosition.put(v.name, -v.position - 1); - privateVarNameToDefinitionPosition.put(v.name, -v.position - 1); + if (!privateVarFullNameToDefinitionPosition.containsKey(v.name) + && !privateVarNameToDefinitionPosition.containsKey(v.getFirstName())) { + parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); + parentVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1); + privateVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); + privateVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1); definitionPosToReferences.put(-v.position - 1, new ArrayList<>()); definitionPosToReferences.get(-v.position - 1).add(v.position); referenceToDefinition.put(v.position, -v.position - 1); } else { - int definitionPos = privateVarNameToDefinitionPosition.get(v.name); - definitionPosToReferences.get(definitionPos).add(v.position); - referenceToDefinition.put(v.position, definitionPos); + + if ("this".equals(v.name) && isStatic) { + errors.add(new SimpleParseException("Cannot use this in static context", -1, v.position)); + } else { + int definitionPos; + if (privateVarFullNameToDefinitionPosition.containsKey(v.name)) { + definitionPos = privateVarFullNameToDefinitionPosition.get(v.name); + } else { + definitionPos = privateVarNameToDefinitionPosition.get(v.getFirstName()); + } + boolean staticDefinition = definitionPos >= 0 ? positionToStatic.get(definitionPos) : true; + if (!(!staticDefinition && isStatic)) { + definitionPosToReferences.get(definitionPos).add(v.position); + referenceToDefinition.put(v.position, definitionPos); + } else { + errors.add(new SimpleParseException("Cannot reference instance variable from static context", -1, v.position)); + } + } } } } if (vt instanceof Scope) { Scope vs = (Scope) vt; - parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarNameToDefinitionPosition); + boolean subStatic = isStatic; + if (vs instanceof FunctionScope) { + subStatic = ((FunctionScope) vs).isStatic(); + } + if (vs instanceof TraitVarConstValueScope) { + subStatic = ((TraitVarConstValueScope) vs).isStatic(); + } + parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors); } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/TraitVarConstValueScope.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/TraitVarConstValueScope.java new file mode 100644 index 000000000..3a91c23c5 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/TraitVarConstValueScope.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010-2025 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.simpleparser; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class TraitVarConstValueScope implements Scope { + + private List sharedItems; + private final boolean isStatic; + + public TraitVarConstValueScope(List sharedItems, boolean isStatic) { + this.sharedItems = sharedItems; + this.isStatic = isStatic; + } + + public boolean isStatic() { + return isStatic; + } + + @Override + public List getSharedItems() { + return sharedItems; + } + + @Override + public List getPrivateItems() { + return new ArrayList<>(); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/Variable.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/Variable.java index a68190206..c4bd28625 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/Variable.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/Variable.java @@ -25,15 +25,35 @@ public class Variable implements VariableOrScope { public boolean definition; public String name; public int position; + public Boolean isStatic; public Variable(boolean definition, String name, int position) { + this(definition, name, position, null); + } + + public Variable(boolean definition, String name, int position, Boolean isStatic) { this.definition = definition; this.name = name; this.position = position; + this.isStatic = isStatic; } - + @Override public String toString() { - return (definition ? "definition of " : "") + name + " at " + position; + return (definition ? "definition of " : "") + (isStatic ? "static " : "") + name + " at " + position; } + + public String getLastName() { + if (name.contains(".")) { + return name.substring(name.lastIndexOf(".") + 1); + } + return name; + } + + public String getFirstName() { + if (name.contains(".")) { + return name.substring(0, name.indexOf(".")); + } + return name; + } } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index 886cb88dc..3fe6add6c 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -1240,6 +1240,9 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener multinameIndexRef = new Reference<>(0); Reference classTrait = new Reference<>(false); Reference usedAbcRef = new Reference<>(null); + if (getSwf() == null) { + return false; + } if (decompiledTextArea.getPropertyTypeAtPos(getSwf().getAbcIndex(), pos, abcIndex, classIndex, traitIndex, classTrait, multinameIndexRef, usedAbcRef)) { return true; } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java b/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java index 7c749f8ac..19fc71f85 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java @@ -156,8 +156,8 @@ public class UsageFrame extends AppDialog implements MouseListener { }; Main.getMainFrame().getPanel().setLoadingScrollPosEnabled(false); - if (decompiledTextArea.getScriptIndex() == icu.getScriptIndex() && - (decompiledTextArea.getClassIndex() == icu.getClassIndex() || icu.getClassIndex() == -1) && abcPanel.abc == newAbc) { + if (decompiledTextArea.getScriptIndex() == icu.getScriptIndex() + && (decompiledTextArea.getClassIndex() == icu.getClassIndex() || icu.getClassIndex() == -1) && abcPanel.abc == newAbc) { setTrait.run(); } else { decompiledTextArea.addScriptListener(setTrait); diff --git a/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java b/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java index e8e6fa8fa..c080163ad 100644 --- a/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java @@ -362,11 +362,7 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan return t; } return null; - } - - public Token getTokenUnderCursor() { - return tokenAtPos(lastCursorPos); - } + } public void setLinkHandler(LinkHandler linkHandler) { diff --git a/src/com/jpexs/decompiler/flash/gui/editor/VariableMarker.java b/src/com/jpexs/decompiler/flash/gui/editor/VariableMarker.java index 278e97dd5..1e26ed254 100644 --- a/src/com/jpexs/decompiler/flash/gui/editor/VariableMarker.java +++ b/src/com/jpexs/decompiler/flash/gui/editor/VariableMarker.java @@ -491,7 +491,7 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC private void editorMouseMoved(MouseEvent e) { if (pane instanceof LineMarkedEditorPane) { - Token token = ((LineMarkedEditorPane) pane).getTokenUnderCursor(); + Token token = ((LineMarkedEditorPane) pane).tokenAtPos(e.getPoint()); if (token != null) { String err = errors.get(token.start); pane.setToolTipText(err);