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 6baa44fb4..fb93beb21 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 @@ -75,8 +75,9 @@ public class ActionScript3SimpleParser implements SimpleParser { } } - private String type(List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private String type(Reference subTypeRef, List errors, TypeItem thisType, Reference needsActivation, List importedClasses, List openedNamespaces, List variables, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { ParsedSymbol s = lex(); + subTypeRef.setVal(null); if (s.type == SymbolType.MULTIPLY) { variables.add(new Type(false, "*", s.position)); return "*"; @@ -87,14 +88,59 @@ public class ActionScript3SimpleParser implements SimpleParser { lexer.pushback(s); } - int varLenBefore = variables.size(); boolean t = true; - 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); - if (variables.size() > varLenBefore && variables.get(variables.size() - 1) instanceof Variable) { - return ((Variable) variables.get(variables.size() - 1)).name; + List nameVars = new ArrayList<>(); + name(errors, thisType, needsActivation, openedNamespaces, null, false, false, true, nameVars, importedClasses, abc); + String ret = "*"; + Variable nameVar = null; + if (!nameVars.isEmpty() && nameVars.get(nameVars.size() - 1) instanceof Variable) { + nameVar = (Variable) nameVars.get(nameVars.size() - 1); + ret = nameVar.name; } - return "*"; + + List applyVars = new ArrayList<>(); + applyTypeType(errors, thisType, needsActivation, importedClasses, openedNamespaces, t, new HashMap<>(), false, false, true, applyVars, abc); + if (nameVar != null && !applyVars.isEmpty() && applyVars.get(applyVars.size() - 1) instanceof Variable) { + subTypeRef.setVal((Variable) applyVars.get(applyVars.size() - 1)); + nameVar.subType = (Variable) applyVars.get(applyVars.size() - 1); + } + variables.addAll(applyVars); + variables.addAll(nameVars); + return ret; + } + + private boolean applyTypeType(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) { + boolean first = true; + do { + s = lex(); + if (s.isType(SymbolType.MULTIPLY)) { + //* + } else { + lexer.pushback(s); + Reference subTypeRef = new Reference<>(null); + type(subTypeRef, errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc); + } + first = false; + s = lex(); + } while (s.type == SymbolType.COMMA); + if (s.type == SymbolType.USHIFT_RIGHT) { + s = new ParsedSymbol(s.position + 2, SymbolGroup.OPERATOR, SymbolType.GREATER_THAN); + lexer.pushback(s); + s = new ParsedSymbol(s.position + 1, SymbolGroup.OPERATOR, SymbolType.GREATER_THAN); + lexer.pushback(s); + } + if (s.type == SymbolType.SHIFT_RIGHT) { + s = new ParsedSymbol(s.position + 1, SymbolGroup.OPERATOR, SymbolType.GREATER_THAN); + lexer.pushback(s); + } + expected(errors, s, lexer.yyline(), SymbolType.GREATER_THAN); + } else { + lexer.pushback(s); + } + return ret; } private String memberOrCall(String lastVarName, 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 { @@ -183,7 +229,6 @@ public class ActionScript3SimpleParser implements SimpleParser { lexer.pushback(s); } expected(errors, s, lexer.yyline(), SymbolType.GREATER_THAN); - ret = true; } else { lexer.pushback(s); } @@ -403,11 +448,11 @@ 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, Reference returnTypeRef) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { - function(errors, isInterface, isNative, needsActivation, importedClasses, thisType, openedNamespaces, functionName, isMethod, variables, abc, methodNamePos, isStatic, returnTypeRef); + 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, Reference returnTypeRef, Reference returnSubTypeRef) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + function(errors, isInterface, isNative, needsActivation, importedClasses, thisType, openedNamespaces, functionName, isMethod, variables, abc, methodNamePos, isStatic, returnTypeRef, returnSubTypeRef); } - 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, Reference returnTypeRef) 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, Reference returnTypeRef, Reference returnSubTypeRef) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { ParsedSymbol s; expectedType(errors, SymbolType.PARENT_OPEN); @@ -415,6 +460,8 @@ public class ActionScript3SimpleParser implements SimpleParser { List paramNames = new ArrayList<>(); List paramPositions = new ArrayList<>(); List paramTypes = new ArrayList<>(); + List paramSubTypes = new ArrayList<>(); + boolean hasRest = false; while (s.type != SymbolType.PARENT_CLOSE) { if (s.type != SymbolType.COMMA) { @@ -434,10 +481,13 @@ public class ActionScript3SimpleParser implements SimpleParser { s = lex(); if (!hasRest) { if (s.type == SymbolType.COLON) { - paramTypes.add(type(errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc)); + Reference subTypeRef = new Reference<>(null); + paramTypes.add(type(subTypeRef, errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc)); + paramSubTypes.add(subTypeRef.getVal()); s = lex(); } else { paramTypes.add("*"); + paramSubTypes.add(null); } if (s.type == SymbolType.ASSIGN) { expression(errors, thisType, new Reference<>(false), importedClasses, openedNamespaces, null, isMethod, isMethod, isMethod, isStatic, variables, false, abc); @@ -461,9 +511,10 @@ public class ActionScript3SimpleParser implements SimpleParser { } s = lex(); if (s.type == SymbolType.COLON) { - returnTypeRef.setVal(type(errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc)); + returnTypeRef.setVal(type(returnSubTypeRef, errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc)); } else { returnTypeRef.setVal("*"); + returnSubTypeRef.setVal(null); lexer.pushback(s); } List subvariables = new ArrayList<>(); @@ -471,7 +522,7 @@ public class ActionScript3SimpleParser implements SimpleParser { subvariables.add(new Variable(true, functionName, functionNamePos)); } for (int i = 0; i < paramNames.size() - (hasRest ? 1 : 0); i++) { - subvariables.add(new Variable(true, paramNames.get(i), paramPositions.get(i), null, paramTypes.get(i), null)); + subvariables.add(new Variable(true, paramNames.get(i), paramPositions.get(i), null, paramTypes.get(i), null, paramSubTypes.get(i), null)); } if (hasRest) { subvariables.add(new Variable(true, paramNames.get(paramNames.size() - 1), paramPositions.get(paramNames.size() - 1), null, "Array", null)); @@ -693,7 +744,7 @@ public class ActionScript3SimpleParser implements SimpleParser { if (isInterface) { errors.add(new SimpleParseException("Interface cannot have constructor", lexer.yyline(), s.position)); } - method(errors, outsidePackage, isPrivate, false, false, customNs, iinitNeedsActivation, importedClasses, false, false, thisType, openedNamespaces, false, "", true, classVariables, abc, fnamePos, new Reference<>(null)); + method(errors, outsidePackage, isPrivate, false, false, customNs, iinitNeedsActivation, importedClasses, false, false, thisType, openedNamespaces, false, "", true, classVariables, abc, fnamePos, new Reference<>(null), new Reference<>(null)); } else { if (classNameStr == null) { isStatic = true; @@ -707,9 +758,10 @@ public class ActionScript3SimpleParser implements SimpleParser { } Reference returnTypeRef = new Reference<>(null); - method(errors, outsidePackage, isPrivate, isInterface, isNative, customNs, new Reference<>(false), importedClasses, isOverride, isFinal, thisType, openedNamespaces, isStatic, fname, true, classVariables, abc, fnamePos, returnTypeRef); + Reference returnSubTypeRef = new Reference<>(null); + method(errors, outsidePackage, isPrivate, isInterface, isNative, customNs, new Reference<>(false), importedClasses, isOverride, isFinal, thisType, openedNamespaces, isStatic, fname, true, classVariables, abc, fnamePos, returnTypeRef, returnSubTypeRef); - traitVariables.add(new ClassTrait(fullClassName, fname, customNs, fnamePos, isStatic, "Function", returnTypeRef.getVal())); + traitVariables.add(new ClassTrait(fullClassName, fname, customNs, fnamePos, isStatic, "Function", returnTypeRef.getVal(), null, returnSubTypeRef.getVal())); /* if (isGetter) { @@ -743,7 +795,7 @@ public class ActionScript3SimpleParser implements SimpleParser { String nname = s.value.toString(); int npos = s.position; - traitVariables.add(new ClassTrait(fullClassName, nname, customNs, npos, isStatic, "Namespace", null)); + traitVariables.add(new ClassTrait(fullClassName, nname, customNs, npos, isStatic, "Namespace", null, null, null)); s = lex(); if (s.type == SymbolType.ASSIGN) { @@ -782,15 +834,14 @@ public class ActionScript3SimpleParser implements SimpleParser { s = lex(); } + Reference subTypeRef = new Reference<>(null); String traitType = "*"; if (s.type == SymbolType.COLON) { - traitType = type(errors, thisType, new Reference<>(false), importedClasses, openedNamespaces, classVariables, abc); + traitType = type(subTypeRef, errors, thisType, new Reference<>(false), importedClasses, openedNamespaces, classVariables, abc); s = lex(); - } else { - //* } - traitVariables.add(new ClassTrait(fullClassName, nameSymbol.value.toString(), customNs, nameSymbol.position, isStatic, traitType, "Function".equals(traitType) ? "*" : null)); + traitVariables.add(new ClassTrait(fullClassName, nameSymbol.value.toString(), customNs, nameSymbol.position, isStatic, traitType, "Function".equals(traitType) ? "*" : null, subTypeRef.getVal(), null)); if (s.type == SymbolType.ASSIGN) { List constVarVariables = new ArrayList<>(); @@ -988,12 +1039,12 @@ public class ActionScript3SimpleParser implements SimpleParser { if (!isInterface) { if (s.type == SymbolType.EXTENDS) { - type(errors, null, new Reference<>(false), importedClasses, openedNamespaces, sinitVariables, abc); + type(new Reference<>(null), errors, null, new Reference<>(false), importedClasses, openedNamespaces, sinitVariables, abc); s = lex(); } if (s.type == SymbolType.IMPLEMENTS) { do { - type(errors, null, new Reference<>(false), importedClasses, openedNamespaces, sinitVariables, abc); + type(new Reference<>(null), errors, null, new Reference<>(false), importedClasses, openedNamespaces, sinitVariables, abc); s = lex(); } while (s.type == SymbolType.COMMA); } @@ -1001,7 +1052,7 @@ public class ActionScript3SimpleParser implements SimpleParser { } else { if (s.type == SymbolType.EXTENDS) { do { - type(errors, null, new Reference<>(false), importedClasses, openedNamespaces, sinitVariables, abc); + type(new Reference<>(null), errors, null, new Reference<>(false), importedClasses, openedNamespaces, sinitVariables, abc); s = lex(); } while (s.type == SymbolType.COMMA); } @@ -1026,9 +1077,10 @@ public class ActionScript3SimpleParser implements SimpleParser { String fname = s.value.toString(); Reference returnTypeRef = new Reference<>(null); - method(errors, !inPackage, false, false, isNative, null, new Reference<>(false), importedClasses, false, isFinal, null, openedNamespaces, true, "", true, sinitVariables, abc, s.position, returnTypeRef); + Reference returnSubTypeRef = new Reference<>(null); + method(errors, !inPackage, false, false, isNative, null, new Reference<>(false), importedClasses, false, isFinal, null, openedNamespaces, true, "", true, sinitVariables, abc, s.position, returnTypeRef, returnSubTypeRef); - sinitTraitVariables.add(new Variable(true, fname, s.position, true, "Function", returnTypeRef.getVal())); + sinitTraitVariables.add(new Variable(true, fname, s.position, true, "Function", returnTypeRef.getVal(), null, returnSubTypeRef.getVal())); break; case CONST: case VAR: @@ -1045,11 +1097,12 @@ public class ActionScript3SimpleParser implements SimpleParser { ParsedSymbol traitSymb = s; s = lex(); String traitType = "*"; + Reference subTypeRef = new Reference<>(null); if (s.type == SymbolType.COLON) { - traitType = type(errors, null, new Reference<>(false), importedClasses, openedNamespaces, sinitVariables, abc); + traitType = type(subTypeRef, errors, null, new Reference<>(false), importedClasses, openedNamespaces, sinitVariables, abc); s = lex(); } - sinitTraitVariables.add(new Variable(true, traitSymb.value.toString(), traitSymb.position, null, traitType, traitType.equals("Function") ? "*" : null)); + sinitTraitVariables.add(new Variable(true, traitSymb.value.toString(), traitSymb.position, null, traitType, traitType.equals("Function") ? "*" : null, subTypeRef.getVal(), null)); if (s.type == SymbolType.ASSIGN) { expression(errors, null, new Reference<>(false), importedClasses, openedNamespaces, new HashMap<>(), false, false, true, true, sinitVariables, false, abc); @@ -1253,7 +1306,7 @@ public class ActionScript3SimpleParser implements SimpleParser { switch (s.type) { case USE: expectedType(errors, SymbolType.NAMESPACE); - type(errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc); + type(new Reference<>(null), errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc); break; case WITH: needsActivation.setVal(true); @@ -1275,7 +1328,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, false, new Reference<>(null)); + function(errors, false, false, needsActivation, importedClasses, thisType, openedNamespaces, s.value.toString(), false, variables, abc, s.position, false, new Reference<>(null), new Reference<>(null)); ret = true; break; case VAR: @@ -1288,17 +1341,18 @@ public class ActionScript3SimpleParser implements SimpleParser { int varPos = s.position; s = lex(); String varType = "*"; + Reference varSubTypeRef = new Reference<>(null); if (s.type == SymbolType.COLON) { - varType = type(errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc); + varType = type(varSubTypeRef, errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc); s = lex(); } if (s.type == SymbolType.ASSIGN) { expression(errors, thisType, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, isStatic, true, variables, false, abc); - variables.add(new Variable(true, varIdentifier, varPos, null, varType, null)); + variables.add(new Variable(true, varIdentifier, varPos, null, varType, null, varSubTypeRef.getVal(), null)); ret = true; } else { - variables.add(new Variable(true, varIdentifier, varPos, null, varType, null)); + variables.add(new Variable(true, varIdentifier, varPos, null, varType, null, varSubTypeRef.getVal(), null)); lexer.pushback(s); ret = true; } @@ -1492,13 +1546,14 @@ public class ActionScript3SimpleParser implements SimpleParser { String enamestr = s.value.toString(); int ePos = s.position; expectedType(errors, SymbolType.COLON); - type(errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc); + Reference catchSubType = new Reference<>(null); + String catchType = type(catchSubType, errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc); 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, isStatic, forinlevel, catchVars, abc); expectedType(errors, SymbolType.CURLY_CLOSE); - variables.add(new CatchScope(new Variable(true, enamestr, ePos), catchVars)); + variables.add(new CatchScope(new Variable(true, enamestr, ePos, null, catchType, null, catchSubType.getVal(), null), catchVars)); s = lex(); found = true; } @@ -1903,7 +1958,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, false, new Reference<>(null)); + function(errors, false, false, needsActivation, importedClasses, thisType, openedNamespaces, fname, false, variables, abc, fnamePos, false, new Reference<>(null), new Reference<>(null)); ret = true; allowMemberOrCall = true; break; @@ -1988,10 +2043,10 @@ public class ActionScript3SimpleParser implements SimpleParser { lexer.pushback(s); } needsActivation.setVal(true); - function(errors, false, false, needsActivation, importedClasses, thisType, openedNamespaces, ffname, false, variables, abc, ffnamePos, false, new Reference<>(null)); + function(errors, false, false, needsActivation, importedClasses, thisType, openedNamespaces, ffname, false, variables, abc, ffnamePos, false, new Reference<>(null), new Reference<>(null)); ret = true; } else if (s.type == SymbolType.LOWER_THAN) { - type(errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc); + type(new Reference<>(null), errors, thisType, needsActivation, importedClasses, openedNamespaces, variables, abc); expectedType(errors, SymbolType.GREATER_THAN); s = lex(); expected(errors, s, lexer.yyline(), SymbolType.BRACKET_OPEN); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/ClassTrait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/ClassTrait.java index 01e3fb9f4..37e156dd0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/ClassTrait.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/ClassTrait.java @@ -34,9 +34,11 @@ public class ClassTrait extends Variable { * @param isStatic True = static * @param type Type * @param callType Call type + * @param subType Sub type + * @param callSubType Call sub type */ - public ClassTrait(String classFullName, String name, String customNs, int position, boolean isStatic, String type, String callType) { - super(true, isStatic ? classFullName + "." + name : "this." + (customNs != null ? customNs + "::" : "") + name, position, isStatic, type, callType); + public ClassTrait(String classFullName, String name, String customNs, int position, boolean isStatic, String type, String callType, Variable subType, Variable callSubType) { + super(true, isStatic ? classFullName + "." + name : "this." + (customNs != null ? customNs + "::" : "") + name, position, isStatic, type, callType, subType, callSubType); this.classFullName = classFullName; this.customNs = customNs; this.simpleName = name; 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 626ca540d..9b340f2ac 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 @@ -69,13 +69,15 @@ public interface SimpleParser { Map definitionToType = new LinkedHashMap<>(); Map definitionToCallType = new LinkedHashMap<>(); + Map definitionToSubType = new LinkedHashMap<>(); + Map definitionToCallSubType = new LinkedHashMap<>(); Map traitFullNameToDefinition = new LinkedHashMap<>(); Map positionToStatic = new LinkedHashMap<>(); - findClassTraits(privateVariables, traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType); - findClassTraits(sharedVariables, traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType); + findClassTraits(privateVariables, traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType); + findClassTraits(sharedVariables, traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType); - parseVariablesList(privateVariables, sharedVariables, definitionPosToReferences, referenceToDefinition, new LinkedHashMap<>(), new LinkedHashMap<>(), positionToStatic, true, errors, null, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, traitFullNameToDefinition); + parseVariablesList(privateVariables, sharedVariables, definitionPosToReferences, referenceToDefinition, new LinkedHashMap<>(), new LinkedHashMap<>(), positionToStatic, true, errors, null, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition); for (Map.Entry entry : referenceToExternalTypeIndex.entrySet()) { if (!externalTypeIndexToReference.containsKey(entry.getValue())) { externalTypeIndexToReference.put(entry.getValue(), new ArrayList<>()); @@ -100,6 +102,8 @@ public interface SimpleParser { Map referenceToExternalTypeIndex, Map definitionToType, Map definitionToCallType, + Map definitionToSubType, + Map definitionToCallSubType, Map traitFullNameToDefinition ) { Map privateVarNameToDefinitionPosition = new LinkedHashMap<>(); @@ -121,6 +125,9 @@ public interface SimpleParser { if (v.type != null) { definitionToType.put(v.position, v.type); } + if (v.subType != null) { + definitionToSubType.put(v.position, v.subType); + } } else { if (!privateVarFullNameToDefinitionPosition.containsKey(v.name) && !privateVarNameToDefinitionPosition.containsKey(v.name)) { @@ -128,7 +135,7 @@ public interface SimpleParser { if (externalSimpleTypes.contains(v.name)) { referenceToExternalTypeIndex.put(v.position, externalSimpleTypes.indexOf(v.name)); } else { - boolean traitFound = searchTrait(v, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, definitionToType, definitionToCallType, traitFullNameToDefinition, definitionPosToReferences, referenceToDefinition); + boolean traitFound = searchTrait(v, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, definitionPosToReferences, referenceToDefinition); if (!traitFound) { parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); parentVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1); @@ -192,7 +199,7 @@ public interface SimpleParser { } } - parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, subPrivateVarFullNameToDefinitionPosition, subPrivateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, traitFullNameToDefinition); + parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, subPrivateVarFullNameToDefinitionPosition, subPrivateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition); } } for (VariableOrScope vt : sharedVariables) { @@ -210,6 +217,9 @@ public interface SimpleParser { if (v.type != null) { definitionToType.put(v.position, v.type); } + if (v.subType != null) { + definitionToSubType.put(v.position, v.subType); + } } else { if (!privateVarFullNameToDefinitionPosition.containsKey(v.name) && !privateVarNameToDefinitionPosition.containsKey(v.name)) { @@ -217,7 +227,7 @@ public interface SimpleParser { if (externalSimpleTypes.contains(v.name)) { referenceToExternalTypeIndex.put(v.position, externalSimpleTypes.indexOf(v.name)); } else { - boolean traitFound = searchTrait(v, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, definitionToType, definitionToCallType, traitFullNameToDefinition, definitionPosToReferences, referenceToDefinition); + boolean traitFound = searchTrait(v, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, definitionPosToReferences, referenceToDefinition); if (!traitFound) { parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); parentVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1); @@ -281,7 +291,7 @@ public interface SimpleParser { } } - parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, traitFullNameToDefinition); + parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition); } } } @@ -292,7 +302,9 @@ public interface SimpleParser { Map> definitionPosToReferences, Map positionToStatic, Map definitionToType, - Map definitionToCallType + Map definitionToCallType, + Map definitionToSubType, + Map definitionToCallSubType ) { for (VariableOrScope v : variables) { if (v instanceof ClassTrait) { @@ -305,12 +317,18 @@ public interface SimpleParser { if (ct.callType != null) { definitionToCallType.put(ct.position, ct.callType); } + if (ct.subType != null) { + definitionToSubType.put(ct.position, ct.subType); + } + if (ct.callSubType != null) { + definitionToCallSubType.put(ct.position, ct.callSubType); + } traitFullNameToDefinition.put(ct.getFullIdentifier(), ((ClassTrait) v).position); } if (v instanceof Scope) { Scope s = (Scope) v; - findClassTraits(s.getPrivateItems(), traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType); - findClassTraits(s.getSharedItems(), traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType); + findClassTraits(s.getPrivateItems(), traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType); + findClassTraits(s.getSharedItems(), traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType); } } } @@ -321,6 +339,8 @@ public interface SimpleParser { Map privateVarNameToDefinitionPosition, Map definitionToType, Map definitionToCallType, + Map definitionToSubType, + Map definitionToCallSubType, Map traitFullNameToDefinition, Map> definitionPosToReferences, Map referenceToDefinition @@ -340,12 +360,29 @@ public interface SimpleParser { if (definitionToType.containsKey(definitionPos)) { String type = definitionToType.get(definitionPos); traitFound = true; + Variable lastSubType = null; for (int p = 1; p < parts.size(); p++) { String part = parts.get(p); if (part.equals("()")) { + if (parts.get(p - 1).equals("[]")) { + traitFound = false; + break; + } type = definitionToCallType.get(definitionPos); + lastSubType = null; } else if (part.equals("[]")) { - type = "*"; + if (lastSubType != null) { + lastSubType = lastSubType.subType; + } else if (parts.get(p - 1).equals("()")) { + lastSubType = definitionToCallSubType.get(definitionPos); + } else { + lastSubType = definitionToSubType.get(definitionPos); + } + if (lastSubType == null) { + traitFound = false; + break; + } + type = lastSubType.name; } else { String traitKey = type + "/" + part; if (!traitFullNameToDefinition.containsKey(traitKey)) { @@ -354,6 +391,7 @@ public interface SimpleParser { } definitionPos = traitFullNameToDefinition.get(traitKey); type = definitionToType.get(definitionPos); + lastSubType = null; } } 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 41770c102..47aeb43ce 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 @@ -16,11 +16,8 @@ */ package com.jpexs.decompiler.flash.simpleparser; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * @@ -33,7 +30,9 @@ public class Variable implements VariableOrScope { public int position; public Boolean isStatic; public String type; - public final String callType; + public String callType; + public Variable subType; + public Variable callSubType; public Variable(boolean definition, String name, int position) { this(definition, name, position, null); @@ -44,12 +43,18 @@ public class Variable implements VariableOrScope { } public Variable(boolean definition, String name, int position, Boolean isStatic, String type, String callType) { + this(definition, name, position, isStatic, type, callType, null, null); + } + + public Variable(boolean definition, String name, int position, Boolean isStatic, String type, String callType, Variable subType, Variable callSubType) { this.definition = definition; this.name = name; this.position = position; this.isStatic = isStatic; this.type = type; this.callType = callType; + this.subType = subType; + this.callSubType = callSubType; } @Override