AS3 Highligter - highlight external properties

This commit is contained in:
Jindra Petřík
2025-06-10 00:23:36 +02:00
parent 05a3b511ab
commit c25cb07eed
11 changed files with 497 additions and 158 deletions

View File

@@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.simpleparser.ClassScope;
import com.jpexs.decompiler.flash.simpleparser.ClassTrait;
import com.jpexs.decompiler.flash.simpleparser.FunctionScope;
import com.jpexs.decompiler.flash.simpleparser.Import;
import com.jpexs.decompiler.flash.simpleparser.LinkHandler;
import com.jpexs.decompiler.flash.simpleparser.MethodScope;
import com.jpexs.decompiler.flash.simpleparser.Namespace;
import com.jpexs.decompiler.flash.simpleparser.SimpleParseException;
@@ -2273,7 +2274,10 @@ public class ActionScript3SimpleParser implements SimpleParser {
List<SimpleParseException> errors,
List<String> externalTypes,
Map<Integer, Integer> referenceToExternalTypeIndex,
Map<Integer, List<Integer>> externalTypeIndexToReference
Map<Integer, List<Integer>> externalTypeIndexToReference,
LinkHandler linkHandler,
Map<Integer, String> referenceToExternalTraitKey,
Map<String, List<Integer>> externalTraitKeyToReference
) throws SimpleParseException, IOException, InterruptedException {
List<List<NamespaceItem>> allOpenedNamespaces = new ArrayList<>();
Reference<Boolean> sinitNeedsActivation = new Reference<>(false);
@@ -2293,7 +2297,7 @@ public class ActionScript3SimpleParser implements SimpleParser {
//Logger.getLogger(ActionScript3SimpleParser.class.getName()).log(Level.SEVERE, null, ex);
throw new SimpleParseException(str, ex.line);
}
SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors, true, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference);
SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors, true, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference, linkHandler, referenceToExternalTraitKey, externalTraitKeyToReference);
}
/**

View File

@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.action.parser.ActionParseException;
import com.jpexs.decompiler.flash.simpleparser.CatchScope;
import com.jpexs.decompiler.flash.simpleparser.ClassScope;
import com.jpexs.decompiler.flash.simpleparser.FunctionScope;
import com.jpexs.decompiler.flash.simpleparser.LinkHandler;
import com.jpexs.decompiler.flash.simpleparser.MethodScope;
import com.jpexs.decompiler.flash.simpleparser.SimpleParseException;
import com.jpexs.decompiler.flash.simpleparser.SimpleParser;
@@ -1576,7 +1577,10 @@ public class ActionScript2SimpleParser implements SimpleParser {
List<SimpleParseException> errors,
List<String> externalTypes,
Map<Integer, Integer> referenceToExternalTypeIndex,
Map<Integer, List<Integer>> externalTypeIndexToReference
Map<Integer, List<Integer>> externalTypeIndexToReference,
LinkHandler linkHandler,
Map<Integer, String> referenceToExternalTraitKey,
Map<String, List<Integer>> externalTraitKeyToReference
) throws SimpleParseException, IOException, InterruptedException {
List<VariableOrScope> vars = new ArrayList<>();
@@ -1667,7 +1671,7 @@ public class ActionScript2SimpleParser implements SimpleParser {
} catch (ActionParseException ex) {
errors.add(new SimpleParseException(ex.getMessage(), ex.line, ex.position));
}
SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors, false, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference);
SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors, false, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference, linkHandler, referenceToExternalTraitKey, externalTraitKeyToReference);
}
private void versionRequired(List<SimpleParseException> errors, ParsedSymbol s, int min) throws SimpleParseException {

View File

@@ -0,0 +1,40 @@
/*
* 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;
/**
* @author JPEXS
*/
public interface LinkHandler {
public LinkType getClassLinkType(String className);
public boolean traitExists(String className, String traitName);
public String getTraitType(String className, String traitName);
public String getTraitSubType(String className, String traitName, int level);
public String getTraitCallType(String className, String traitName);
public String getTraitCallSubType(String className, String traitName, int level);
public void handleClassLink(String className);
public void handleTraitLink(String className, String traitName);
}

View File

@@ -0,0 +1,28 @@
/*
* 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;
/**
*
* @author JPEXS
*/
public enum LinkType {
NO_LINK,
LINK_THIS_SCRIPT,
LINK_OTHER_SCRIPT,
LINK_OTHER_FILE;
}

View File

@@ -48,7 +48,10 @@ public interface SimpleParser {
List<SimpleParseException> errors,
List<String> externalTypes,
Map<Integer, Integer> referenceToExternalTypeIndex,
Map<Integer, List<Integer>> externalTypeIndexToReference
Map<Integer, List<Integer>> externalTypeIndexToReference,
LinkHandler linkHandler,
Map<Integer, String> referenceToExternalTraitKey,
Map<String, List<Integer>> externalTraitKeyToReference
) throws SimpleParseException, IOException, InterruptedException;
public static void parseVariablesList(
@@ -60,11 +63,17 @@ public interface SimpleParser {
boolean innerFunctionCanUseTraits,
List<String> externalTypes,
Map<Integer, Integer> referenceToExternalTypeIndex,
Map<Integer, List<Integer>> externalTypeIndexToReference
Map<Integer, List<Integer>> externalTypeIndexToReference,
LinkHandler linkHandler,
Map<Integer, String> referenceToExternalTraitKey,
Map<String, List<Integer>> externalTraitKeyToReference
) {
List<String> externalSimpleTypes = new ArrayList<>();
Map<String, String> simpleExternalClassNameToFullClassName = new LinkedHashMap<>();
for (String type : externalTypes) {
externalSimpleTypes.add(type.contains(".") ? type.substring(type.lastIndexOf(".") + 1) : type);
String simpleName = type.contains(".") ? type.substring(type.lastIndexOf(".") + 1) : type;
externalSimpleTypes.add(simpleName);
simpleExternalClassNameToFullClassName.put(simpleName, type);
}
Map<Integer, String> definitionToType = new LinkedHashMap<>();
@@ -77,7 +86,7 @@ public interface SimpleParser {
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, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition);
parseVariablesList(privateVariables, sharedVariables, definitionPosToReferences, referenceToDefinition, new LinkedHashMap<>(), new LinkedHashMap<>(), positionToStatic, true, errors, null, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, linkHandler, simpleExternalClassNameToFullClassName, referenceToExternalTraitKey, externalTraitKeyToReference);
for (Map.Entry<Integer, Integer> entry : referenceToExternalTypeIndex.entrySet()) {
if (!externalTypeIndexToReference.containsKey(entry.getValue())) {
externalTypeIndexToReference.put(entry.getValue(), new ArrayList<>());
@@ -104,7 +113,11 @@ public interface SimpleParser {
Map<Integer, String> definitionToCallType,
Map<Integer, Variable> definitionToSubType,
Map<Integer, Variable> definitionToCallSubType,
Map<String, Integer> traitFullNameToDefinition
Map<String, Integer> traitFullNameToDefinition,
LinkHandler linkHandler,
Map<String, String> simpleExternalClassNameToFullClassName,
Map<Integer, String> referenceToExternalTraitKey,
Map<String, List<Integer>> externalTraitKeyToReference
) {
Map<String, Integer> privateVarNameToDefinitionPosition = new LinkedHashMap<>();
privateVarNameToDefinitionPosition.putAll(parentVarNameToDefinitionPosition);
@@ -135,7 +148,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, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, definitionPosToReferences, referenceToDefinition);
boolean traitFound = searchTrait(v, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, definitionPosToReferences, referenceToDefinition, linkHandler, simpleExternalClassNameToFullClassName, referenceToExternalTraitKey, externalTraitKeyToReference);
if (!traitFound) {
parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
parentVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1);
@@ -199,7 +212,7 @@ public interface SimpleParser {
}
}
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, subPrivateVarFullNameToDefinitionPosition, subPrivateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition);
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, subPrivateVarFullNameToDefinitionPosition, subPrivateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, linkHandler, simpleExternalClassNameToFullClassName, referenceToExternalTraitKey, externalTraitKeyToReference);
}
}
for (VariableOrScope vt : sharedVariables) {
@@ -227,7 +240,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, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, definitionPosToReferences, referenceToDefinition);
boolean traitFound = searchTrait(v, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, definitionPosToReferences, referenceToDefinition, linkHandler, simpleExternalClassNameToFullClassName, referenceToExternalTraitKey, externalTraitKeyToReference);
if (!traitFound) {
parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
parentVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1);
@@ -291,7 +304,7 @@ public interface SimpleParser {
}
}
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition);
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, linkHandler, simpleExternalClassNameToFullClassName, referenceToExternalTraitKey, externalTraitKeyToReference);
}
}
}
@@ -343,12 +356,16 @@ public interface SimpleParser {
Map<Integer, Variable> definitionToCallSubType,
Map<String, Integer> traitFullNameToDefinition,
Map<Integer, List<Integer>> definitionPosToReferences,
Map<Integer, Integer> referenceToDefinition
Map<Integer, Integer> referenceToDefinition,
LinkHandler linkHandler,
Map<String, String> simpleExternalClassNameToFullClassName,
Map<Integer, String> referenceToExternalTraitKey,
Map<String, List<Integer>> externalTraitKeyToReference
) {
boolean traitFound = false;
if (v.hasParent()) {
List<String> parts = v.getParts();
Integer definitionPos = null;
String firstName = parts.get(0);
if (privateVarFullNameToDefinitionPosition.containsKey(firstName)) {
@@ -361,34 +378,88 @@ public interface SimpleParser {
String type = definitionToType.get(definitionPos);
traitFound = true;
Variable lastSubType = null;
String traitKey = null;
String externalCallType = null;
List<String> externalSubTypes = new ArrayList<>();
List<String> externalCallSubTypes = new ArrayList<>();
String part = null;
for (int p = 1; p < parts.size(); p++) {
String part = parts.get(p);
part = parts.get(p);
if (part.equals("()")) {
if (parts.get(p - 1).equals("[]")) {
traitFound = false;
break;
}
type = definitionToCallType.get(definitionPos);
if (definitionPos == null) {
type = externalCallType;
externalSubTypes.clear();
externalSubTypes.addAll(externalCallSubTypes);
} else {
type = definitionToCallType.get(definitionPos);
}
lastSubType = null;
} else if (part.equals("[]")) {
if (lastSubType != null) {
lastSubType = lastSubType.subType;
} else if (parts.get(p - 1).equals("()")) {
lastSubType = definitionToCallSubType.get(definitionPos);
} else {
lastSubType = definitionToSubType.get(definitionPos);
if (definitionPos != null) {
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 {
if (externalSubTypes.isEmpty()) {
traitFound = false;
break;
}
type = externalSubTypes.remove(0);
}
if (lastSubType == null) {
traitFound = false;
break;
}
type = lastSubType.name;
} else {
String traitKey = type + "/" + part;
traitKey = type + "/" + part;
if (!traitFullNameToDefinition.containsKey(traitKey)) {
traitFound = false;
break;
if (simpleExternalClassNameToFullClassName.containsKey(type)) {
type = simpleExternalClassNameToFullClassName.get(type);
}
traitKey = type + "/" + part;
String newType = linkHandler.getTraitType(type, part);
if (newType == null) {
traitFound = false;
break;
}
externalSubTypes.clear();
int i = 1;
while (true) {
String st = linkHandler.getTraitSubType(type, part, i);
if (st == null) {
break;
}
externalSubTypes.add(st);
i++;
}
externalCallType = linkHandler.getTraitCallType(type, part);
externalCallSubTypes.clear();
i = 1;
while (true) {
String st = linkHandler.getTraitCallSubType(type, part, i);
if (st == null) {
break;
}
externalCallSubTypes.add(st);
i++;
}
type = newType;
definitionPos = null;
lastSubType = null;
continue;
}
externalCallSubTypes.clear();
externalSubTypes.clear();
externalCallType = null;
definitionPos = traitFullNameToDefinition.get(traitKey);
type = definitionToType.get(definitionPos);
lastSubType = null;
@@ -396,8 +467,16 @@ public interface SimpleParser {
}
if (traitFound) {
definitionPosToReferences.get(definitionPos).add(v.position);
referenceToDefinition.put(v.position, definitionPos);
if (definitionPos != null) {
definitionPosToReferences.get(definitionPos).add(v.position);
referenceToDefinition.put(v.position, definitionPos);
} else if (part != null) {
if (!externalTraitKeyToReference.containsKey(traitKey)) {
externalTraitKeyToReference.put(traitKey, new ArrayList<>());
}
externalTraitKeyToReference.get(traitKey).add(v.position);
referenceToExternalTraitKey.put(v.position, traitKey);
}
}
}
}