Variables code completion

This commit is contained in:
Jindra Petřík
2025-06-15 18:16:06 +02:00
parent 53b8279ce5
commit aecef68d7b
14 changed files with 395 additions and 225 deletions

View File

@@ -469,8 +469,9 @@ public class ActionScript3SimpleParser implements SimpleParser {
private void function(List<SimpleParseException> errors, boolean isInterface, boolean isNative, Reference<Boolean> needsActivation, List<DottedChain> importedClasses, TypeItem thisType, List<NamespaceItem> openedNamespaces, Path functionName, boolean isMethod, List<VariableOrScope> variables, ABC abc, int functionNamePos, boolean isStatic, Reference<Path> returnTypeRef, Reference<Variable> returnSubTypeRef) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException {
ParsedSymbol s;
expectedType(errors, SymbolType.PARENT_OPEN);
ParsedSymbol s = lex();
expected(errors, s, lexer.yyline(), SymbolType.PARENT_OPEN);
int scopePos = s.position;
s = lex();
List<Path> paramNames = new ArrayList<>();
List<Integer> paramPositions = new ArrayList<>();
@@ -543,21 +544,26 @@ public class ActionScript3SimpleParser implements SimpleParser {
subvariables.add(new Variable(true, paramNames.get(paramNames.size() - 1), paramPositions.get(paramNames.size() - 1), null, new Path("Array"), null));
}
Reference<Boolean> needsActivation2 = new Reference<>(false);
if (!isInterface && !isNative) {
s = lex();
expected(errors, s, lexer.yyline(), SymbolType.CURLY_OPEN);
subvariables.add(new Variable(true, new Path("arguments"), -s.position - 1, null, new Path("Array"), null));
commands(errors, thisType, needsActivation2, importedClasses, openedNamespaces, new Stack<>(), new HashMap<>(), new HashMap<>(), true, isMethod, isStatic, 0, subvariables, abc);
expectedType(errors, SymbolType.CURLY_CLOSE);
s = lex();
expected(errors, s, lexer.yyline(), SymbolType.CURLY_CLOSE);
} else {
expectedType(errors, SymbolType.SEMICOLON);
s = lex();
expected(errors, s, lexer.yyline(), SymbolType.SEMICOLON);
}
int scopeEndPos = s.position;
if (isMethod) {
MethodScope ms = new MethodScope(subvariables, isStatic);
MethodScope ms = new MethodScope(scopePos, scopeEndPos, subvariables, isStatic);
variables.add(ms);
} else {
FunctionScope fs = new FunctionScope(subvariables, isStatic);
FunctionScope fs = new FunctionScope(scopePos, scopeEndPos, subvariables, isStatic);
variables.add(fs);
}
}
@@ -861,8 +867,9 @@ public class ActionScript3SimpleParser implements SimpleParser {
if (s.type == SymbolType.ASSIGN) {
List<VariableOrScope> 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));
int scopePos = s.position;
s = lex();
classVariables.add(new TraitVarConstValueScope(scopePos, s.position, constVarVariables, isStatic));
}
if (s.type != SymbolType.SEMICOLON) {
lexer.pushback(s);
@@ -1031,6 +1038,7 @@ public class ActionScript3SimpleParser implements SimpleParser {
switch (s.type) {
case CLASS:
case INTERFACE:
int scopePos = s.position;
isEmpty = false;
List<NamespaceItem> subOpenedNamespaces = new ArrayList<>(openedNamespaces);
boolean isInterface = false;
@@ -1084,9 +1092,10 @@ public class ActionScript3SimpleParser implements SimpleParser {
classTraits(errors, !inPackage, cinitNeedsActivation, importedClasses, subOpenedNamespaces, pkgName, subNameStr, isInterface, iinitNeedsActivation, abc, classVariables);
sinitVariables.add(new ClassScope(classVariables));
s = lex();
sinitVariables.add(new ClassScope(scopePos, s.position, classVariables));
expectedType(errors, SymbolType.CURLY_CLOSE);
expected(errors, s, lexer.yyline(), SymbolType.CURLY_CLOSE);
break;
case FUNCTION:
isEmpty = false;
@@ -1557,6 +1566,7 @@ public class ActionScript3SimpleParser implements SimpleParser {
s = lex();
boolean found = false;
while (s.type == SymbolType.CATCH) {
int scopePos = s.position;
expectedType(errors, SymbolType.PARENT_OPEN);
s = lex();
if (!expected(errors, s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.THIS, SymbolType.SUPER, SymbolType.STRING_OP)) {
@@ -1571,8 +1581,10 @@ public class ActionScript3SimpleParser implements SimpleParser {
List<VariableOrScope> 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, null, catchType, null, catchSubType.getVal(), null), catchVars));
int eScopePos = s.position;
s = lex();
expected(errors, s, lexer.yyline(), SymbolType.CURLY_CLOSE);
variables.add(new CatchScope(eScopePos, s.position, new Variable(true, enamestr, ePos, null, catchType, null, catchSubType.getVal(), null), catchVars));
s = lex();
found = true;
}
@@ -2300,7 +2312,9 @@ public class ActionScript3SimpleParser implements SimpleParser {
Map<Integer, Boolean> separatorIsStatic,
Map<Path, List<String>> localTypeTraitNames,
Map<Integer, Path> definitionToType,
Map<Integer, Path> definitionToCallType
Map<Integer, Path> definitionToCallType,
Integer caretPosition,
List<String> variableSuggestions
) throws SimpleParseException, IOException, InterruptedException {
List<List<NamespaceItem>> allOpenedNamespaces = new ArrayList<>();
Reference<Boolean> sinitNeedsActivation = new Reference<>(false);
@@ -2320,7 +2334,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, linkHandler, referenceToExternalTraitKey, externalTraitKeyToReference, separatorPosToType, separatorIsStatic, localTypeTraitNames, definitionToType, definitionToCallType);
SimpleParser.parseVariablesList(vars, definitionPosToReferences, referenceToDefinition, errors, true, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference, linkHandler, referenceToExternalTraitKey, externalTraitKeyToReference, separatorPosToType, separatorIsStatic, localTypeTraitNames, definitionToType, definitionToCallType, caretPosition, variableSuggestions);
}
/**

View File

@@ -164,12 +164,14 @@ public class ActionScript2SimpleParser implements SimpleParser {
}
private FunctionScope function(List<SimpleParseException> errors, boolean withBody, Path functionName, int functionNamePosition, boolean isMethod, List<VariableOrScope> variables, boolean inTellTarget, Reference<Boolean> hasEval, boolean isStatic) throws IOException, InterruptedException, SimpleParseException, ActionParseException {
ParsedSymbol s;
expectedType(errors, SymbolType.PARENT_OPEN);
ParsedSymbol s = lex();
int scopePos = s.position;
expected(errors, s, lexer.yyline(), SymbolType.PARENT_OPEN);
s = lex();
List<Path> paramNames = new ArrayList<>();
List<Integer> paramPositions = new ArrayList<>();
int scopeEndPos;
while (s.type != SymbolType.PARENT_CLOSE) {
if (s.type != SymbolType.COMMA) {
lexer.pushback(s);
@@ -191,6 +193,7 @@ public class ActionScript2SimpleParser implements SimpleParser {
}
}
}
scopeEndPos = s.position;
List<VariableOrScope> subvariables = new ArrayList<>();
Reference<Boolean> subHasEval = new Reference<>(false);
@@ -205,7 +208,9 @@ public class ActionScript2SimpleParser implements SimpleParser {
if (withBody) {
expectedType(errors, SymbolType.CURLY_OPEN);
commands(errors, true, isMethod, 0, inTellTarget, subvariables, subHasEval);
expectedType(errors, SymbolType.CURLY_CLOSE);
s = lex();
expected(errors, s, lexer.yyline(), SymbolType.CURLY_CLOSE);
scopeEndPos = s.position;
}
if (subHasEval.getVal()) {
@@ -213,9 +218,9 @@ public class ActionScript2SimpleParser implements SimpleParser {
}
if (isMethod) {
return new MethodScope(subvariables, isStatic);
return new MethodScope(scopePos, scopeEndPos, subvariables, isStatic);
}
return new FunctionScope(subvariables, isStatic);
return new FunctionScope(scopePos, scopeEndPos, subvariables, isStatic);
}
private boolean traits(List<SimpleParseException> errors, boolean isInterface, Path className, List<VariableOrScope> variables, boolean inTellTarget, Reference<Boolean> hasEval) throws IOException, InterruptedException, SimpleParseException, ActionParseException {
@@ -276,10 +281,12 @@ public class ActionScript2SimpleParser implements SimpleParser {
s = lex();
}
if (s.type == SymbolType.ASSIGN) {
int scopePos = s.position;
List<VariableOrScope> subVariables = new ArrayList<>();
expression(errors, false, false, false, true, subVariables, false, hasEval);
variables.add(new TraitVarConstValueScope(subVariables, isStatic));
s = lex();
variables.add(new TraitVarConstValueScope(scopePos, s.position, subVariables, isStatic));
}
if (s.type != SymbolType.SEMICOLON) {
lexer.pushback(s);
@@ -783,6 +790,7 @@ public class ActionScript2SimpleParser implements SimpleParser {
ret = true;
break;
case CLASS:
int scopePos = s.position;
Path className = type(errors, true, variables);
if (className != null) {
s = lex();
@@ -800,10 +808,12 @@ public class ActionScript2SimpleParser implements SimpleParser {
variables.add(new Variable(true, new Path("this"), s.position));
List<VariableOrScope> subVariables = new ArrayList<>();
traits(errors, false, className, subVariables, inTellTarget, hasEval);
ClassScope cs = new ClassScope(subVariables);
s = lex();
ClassScope cs = new ClassScope(scopePos, s.position, subVariables);
variables.add(cs);
expectedType(errors, SymbolType.CURLY_CLOSE);
expectedType(errors, s, lexer.yyline(), SymbolType.CURLY_CLOSE);
ret = true;
}
break;
@@ -993,6 +1003,7 @@ public class ActionScript2SimpleParser implements SimpleParser {
s = lex();
boolean found = false;
while (s.type == SymbolType.CATCH) {
int catchScopePos = s.position;
expectedType(errors, SymbolType.PARENT_OPEN);
ParsedSymbol si = lex();
if (expectedIdentifier(errors, si, lexer.yyline(), SymbolType.STRING)) {
@@ -1007,8 +1018,9 @@ public class ActionScript2SimpleParser implements SimpleParser {
List<VariableOrScope> subvariables = new ArrayList<>();
command(errors, inFunction, inMethod, forinlevel, inTellTarget, subvariables, hasEval);
variables.add(new CatchScope(new Variable(true, new Path((String) si.value), si.position), subvariables));
s = lex();
variables.add(new CatchScope(catchScopePos, s.position, new Variable(true, new Path((String) si.value), si.position), subvariables));
lexer.pushback(s);
}
s = lex();
found = true;
@@ -1585,7 +1597,9 @@ public class ActionScript2SimpleParser implements SimpleParser {
Map<Integer, Boolean> separatorIsStatic,
Map<Path, List<String>> localTypeTraitNames,
Map<Integer, Path> definitionToType,
Map<Integer, Path> definitionToCallType
Map<Integer, Path> definitionToCallType,
Integer caretPosition,
List<String> variableSuggestions
) throws SimpleParseException, IOException, InterruptedException {
List<VariableOrScope> vars = new ArrayList<>();
@@ -1676,7 +1690,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, linkHandler, referenceToExternalTraitKey, externalTraitKeyToReference, separatorPosToType, separatorIsStatic, localTypeTraitNames, definitionToType, definitionToCallType);
SimpleParser.parseVariablesList(vars, definitionPosToReferences, referenceToDefinition, errors, false, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference, linkHandler, referenceToExternalTraitKey, externalTraitKeyToReference, separatorPosToType, separatorIsStatic, localTypeTraitNames, definitionToType, definitionToCallType, caretPosition, variableSuggestions);
}
private void versionRequired(List<SimpleParseException> errors, ParsedSymbol s, int min) throws SimpleParseException {

View File

@@ -27,11 +27,15 @@ public class CatchScope implements Scope {
private final List<VariableOrScope> privateItems;
private final List<VariableOrScope> sharedItems;
private final int position;
private final int endPosition;
public CatchScope(Variable catchVariable, List<VariableOrScope> catchBody) {
public CatchScope(int position, int endPosition, Variable catchVariable, List<VariableOrScope> catchBody) {
this.privateItems = new ArrayList<>();
this.privateItems.add(catchVariable);
this.sharedItems = catchBody;
this.position = position;
this.endPosition = endPosition;
}
@Override
@@ -44,4 +48,14 @@ public class CatchScope implements Scope {
return privateItems;
}
@Override
public int getPosition() {
return position;
}
@Override
public int getEndPosition() {
return endPosition;
}
}

View File

@@ -26,9 +26,13 @@ import java.util.List;
public class ClassScope implements Scope {
private final List<VariableOrScope> privateItems;
private final int position;
private final int endPosition;
public ClassScope(List<VariableOrScope> traits) {
public ClassScope(int position, int endPosition, List<VariableOrScope> traits) {
this.privateItems = traits;
this.position = position;
this.endPosition = endPosition;
}
@Override
@@ -40,4 +44,14 @@ public class ClassScope implements Scope {
public List<VariableOrScope> getPrivateItems() {
return privateItems;
}
@Override
public int getPosition() {
return position;
}
@Override
public int getEndPosition() {
return endPosition;
}
}

View File

@@ -27,10 +27,14 @@ public class FunctionScope implements Scope {
private final List<VariableOrScope> privateItems;
private final boolean isStatic;
private final int position;
private final int endPosition;
public FunctionScope(List<VariableOrScope> functionBody, boolean isStatic) {
public FunctionScope(int position, int endPosition, List<VariableOrScope> functionBody, boolean isStatic) {
this.privateItems = functionBody;
this.isStatic = isStatic;
this.position = position;
this.endPosition = endPosition;
}
public boolean isStatic() {
@@ -46,4 +50,15 @@ public class FunctionScope implements Scope {
public List<VariableOrScope> getPrivateItems() {
return privateItems;
}
@Override
public int getPosition() {
return position;
}
@Override
public int getEndPosition() {
return endPosition;
}
}

View File

@@ -24,8 +24,8 @@ import java.util.List;
*/
public class MethodScope extends FunctionScope {
public MethodScope(List<VariableOrScope> functionBody, boolean isStatic) {
super(functionBody, isStatic);
public MethodScope(int position, int endPosition, List<VariableOrScope> functionBody, boolean isStatic) {
super(position, endPosition, functionBody, isStatic);
}
}

View File

@@ -27,4 +27,6 @@ public interface Scope extends VariableOrScope {
public List<VariableOrScope> getSharedItems();
public List<VariableOrScope> getPrivateItems();
public int getEndPosition();
}

View File

@@ -29,6 +29,9 @@ public class Separator implements VariableOrScope {
this.position = position;
}
@Override
public int getPosition() {
return position;
}
}

View File

@@ -18,8 +18,10 @@ package com.jpexs.decompiler.flash.simpleparser;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -63,11 +65,12 @@ public interface SimpleParser {
Map<Integer, Boolean> separatorIsStatic,
Map<Path, List<String>> localTypeTraitNames,
Map<Integer, Path> definitionToType,
Map<Integer, Path> definitionToCallType
Map<Integer, Path> definitionToCallType,
Integer caretPosition,
List<String> variableSuggestions
) throws SimpleParseException, IOException, InterruptedException;
public static void parseVariablesList(
List<VariableOrScope> privateVariables,
List<VariableOrScope> sharedVariables,
Map<Integer, List<Integer>> definitionPosToReferences,
Map<Integer, Integer> referenceToDefinition,
@@ -81,9 +84,11 @@ public interface SimpleParser {
Map<Path, List<Integer>> externalTraitKeyToReference,
Map<Integer, Path> separatorPosToType,
Map<Integer, Boolean> separatorIsStatic,
Map<Path, List<String>> localTypeTraitNames,
Map<Path, List<String>> localTypeTraitNames,
Map<Integer, Path> definitionToType,
Map<Integer, Path> definitionToCallType
Map<Integer, Path> definitionToCallType,
Integer caretPosition,
List<String> variableSuggestions
) {
List<Path> externalSimpleTypes = new ArrayList<>();
Map<Path, Path> simpleExternalClassNameToFullClassName = new LinkedHashMap<>();
@@ -98,9 +103,17 @@ public interface SimpleParser {
Map<Integer, Variable> definitionToCallSubType = new LinkedHashMap<>();
Map<Path, Integer> traitFullNameToDefinition = new LinkedHashMap<>();
List<VariableOrScopeWithAccess> variables = new ArrayList<>();
for (VariableOrScope vs : sharedVariables) {
variables.add(new VariableOrScopeWithAccess(vs, true));
}
Map<Integer, Boolean> positionToStatic = new LinkedHashMap<>();
findClassTraits(privateVariables, traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType);
findClassTraits(sharedVariables, traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType);
Map<Path, Integer> parentVarFullNameToDefinitionPosition = new LinkedHashMap<>();
Map<Path, Integer> parentVarNameToDefinitionPosition = new LinkedHashMap<>();
findClassTraits(variables, traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, parentVarFullNameToDefinitionPosition, parentVarNameToDefinitionPosition);
for (Path p : traitFullNameToDefinition.keySet()) {
int definition = traitFullNameToDefinition.get(p);
@@ -116,18 +129,35 @@ public interface SimpleParser {
localTypeTraitNames.get(cls).add((isStatic ? "static::" : "") + traitName);
}
parseVariablesList(privateVariables, sharedVariables, definitionPosToReferences, referenceToDefinition, new LinkedHashMap<>(), new LinkedHashMap<>(), positionToStatic, true, errors, null, innerFunctionCanUseTraits, externalSimpleTypes, externalTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, linkHandler, simpleExternalClassNameToFullClassName, referenceToExternalTraitKey, externalTraitKeyToReference, separatorPosToType, separatorIsStatic);
parseVariablesList(variables, definitionPosToReferences, referenceToDefinition, parentVarFullNameToDefinitionPosition, parentVarNameToDefinitionPosition, positionToStatic, true, errors, null, innerFunctionCanUseTraits, externalSimpleTypes, externalTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, linkHandler, simpleExternalClassNameToFullClassName, referenceToExternalTraitKey, externalTraitKeyToReference, separatorPosToType, separatorIsStatic, caretPosition, variableSuggestions, null, null);
for (Map.Entry<Integer, Integer> entry : referenceToExternalTypeIndex.entrySet()) {
if (!externalTypeIndexToReference.containsKey(entry.getValue())) {
externalTypeIndexToReference.put(entry.getValue(), new ArrayList<>());
}
externalTypeIndexToReference.get(entry.getValue()).add(entry.getKey());
}
if (caretPosition != null && variableSuggestions.isEmpty()) {
if ((variables.isEmpty() || variables.get(variables.size() - 1).var.getPosition() <= caretPosition)) {
for (Path p : parentVarNameToDefinitionPosition.keySet()) {
if (parentVarNameToDefinitionPosition.get(p) >= 0) {
variableSuggestions.add(p.getFirst().toString());
}
}
variableSuggestions.add("--finish--");
}
}
if (!variableSuggestions.isEmpty()) {
variableSuggestions.remove(variableSuggestions.size() - 1);
}
Set<String> uniqueSuggestions = new LinkedHashSet<>(variableSuggestions);
variableSuggestions.clear();
variableSuggestions.addAll(uniqueSuggestions);
}
public static void parseVariablesList(
List<VariableOrScope> privateVariables,
List<VariableOrScope> sharedVariables,
List<VariableOrScopeWithAccess> variables,
Map<Integer, List<Integer>> definitionPosToReferences,
Map<Integer, Integer> referenceToDefinition,
Map<Path, Integer> parentVarFullNameToDefinitionPosition,
@@ -150,7 +180,11 @@ public interface SimpleParser {
Map<Integer, Path> referenceToExternalTraitKey,
Map<Path, List<Integer>> externalTraitKeyToReference,
Map<Integer, Path> separatorPosToType,
Map<Integer, Boolean> separatorIsStatic
Map<Integer, Boolean> separatorIsStatic,
Integer caretPosition,
List<String> variableSuggestions,
Integer scopeStartPos,
Integer scopeEndPos
) {
Map<Path, Integer> privateVarNameToDefinitionPosition = new LinkedHashMap<>();
privateVarNameToDefinitionPosition.putAll(parentVarNameToDefinitionPosition);
@@ -158,7 +192,30 @@ public interface SimpleParser {
Map<Path, Integer> privateVarFullNameToDefinitionPosition = new LinkedHashMap<>();
privateVarFullNameToDefinitionPosition.putAll(parentVarFullNameToDefinitionPosition);
for (VariableOrScope vt : privateVariables) {
for (int i = 0; i < variables.size(); i++) {
VariableOrScopeWithAccess vsa = variables.get(i);
VariableOrScope vt = variables.get(i).var;
VariableOrScope vt2 = i + 1 < variables.size() ? variables.get(i + 1).var : null;
if (i == 0
&& scopeStartPos != null
&& caretPosition != null
&& caretPosition >= scopeStartPos
&& vt.getPosition() > caretPosition
&& variableSuggestions.isEmpty()) {
for (Path p : parentVarNameToDefinitionPosition.keySet()) {
if (parentVarNameToDefinitionPosition.get(p) >= 0) {
variableSuggestions.add(p.getFirst().toString());
}
}
for (Path p : privateVarNameToDefinitionPosition.keySet()) {
if (privateVarNameToDefinitionPosition.get(p) >= 0) {
variableSuggestions.add(p.getFirst().toString());
}
}
variableSuggestions.add("--finish--");
}
if (vt instanceof Separator) {
Separator s = (Separator) vt;
searchTrait(s.parentName, s.position, true, separatorPosToType, separatorIsStatic, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, definitionPosToReferences, referenceToDefinition, linkHandler, simpleExternalClassNameToFullClassName, referenceToExternalTraitKey, externalTraitKeyToReference);
@@ -166,6 +223,11 @@ public interface SimpleParser {
if (vt instanceof Variable) {
Variable v = (Variable) vt;
if (v.definition) {
if (vsa.shared) {
parentVarFullNameToDefinitionPosition.put(v.name, v.position);
parentVarNameToDefinitionPosition.put(v.getLastName(), v.position);
}
privateVarFullNameToDefinitionPosition.put(v.name, v.position);
privateVarNameToDefinitionPosition.put(v.getLastName(), v.position);
if (!definitionPosToReferences.containsKey(v.position)) {
@@ -189,8 +251,10 @@ public interface SimpleParser {
} else {
boolean traitFound = searchTrait(v.name, v.position, false, separatorPosToType, separatorIsStatic, 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);
if (vsa.shared) {
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<>());
@@ -200,103 +264,6 @@ public interface SimpleParser {
}
} else {
if ("this".equals(v.name.toString()) && 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.name);
}
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;
boolean subStatic = isStatic;
if (vs instanceof FunctionScope) {
subStatic = ((FunctionScope) vs).isStatic();
}
if (vs instanceof TraitVarConstValueScope) {
subStatic = ((TraitVarConstValueScope) vs).isStatic();
}
//if its inner function (not a method), remove all this variables
Map<Path, Integer> subPrivateVarFullNameToDefinitionPosition = privateVarFullNameToDefinitionPosition;
Map<Path, Integer> subPrivateVarNameToDefinitionPosition = privateVarNameToDefinitionPosition;
if ((vs instanceof FunctionScope) && (!(vs instanceof MethodScope))) {
subPrivateVarFullNameToDefinitionPosition = new LinkedHashMap<>(subPrivateVarFullNameToDefinitionPosition);
subPrivateVarNameToDefinitionPosition = new LinkedHashMap<>(subPrivateVarNameToDefinitionPosition);
Set<Path> keys = new HashSet<>(subPrivateVarFullNameToDefinitionPosition.keySet());
for (Path vName : keys) {
if (vName.toString().equals("this") || vName.getFirst().toString().equals("this")) {
subPrivateVarFullNameToDefinitionPosition.remove(vName);
if (vName.toString().equals("this")) {
subPrivateVarNameToDefinitionPosition.remove(new Path("this"));
}
if (!innerFunctionCanUseTraits) {
subPrivateVarNameToDefinitionPosition.remove(vName.getLast());
}
}
}
}
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, subPrivateVarFullNameToDefinitionPosition, subPrivateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, externalFullTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, linkHandler, simpleExternalClassNameToFullClassName, referenceToExternalTraitKey, externalTraitKeyToReference, separatorPosToType, separatorIsStatic);
}
}
for (VariableOrScope vt : sharedVariables) {
if (vt instanceof Separator) {
Separator s = (Separator) vt;
searchTrait(s.parentName, s.position, true, separatorPosToType, separatorIsStatic, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, definitionPosToReferences, referenceToDefinition, linkHandler, simpleExternalClassNameToFullClassName, referenceToExternalTraitKey, externalTraitKeyToReference);
}
if (vt instanceof Variable) {
Variable v = (Variable) vt;
if (v.definition) {
parentVarFullNameToDefinitionPosition.put(v.name, v.position);
parentVarNameToDefinitionPosition.put(v.getLastName(), v.position);
privateVarFullNameToDefinitionPosition.put(v.name, v.position);
privateVarNameToDefinitionPosition.put(v.getLastName(), v.position);
if (!definitionPosToReferences.containsKey(v.position)) {
definitionPosToReferences.put(v.position, new ArrayList<>());
}
positionToStatic.put(v.position, v.isStatic != null ? v.isStatic : isStatic);
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)) {
if (externalFullTypes.contains(v.name)) {
referenceToExternalTypeIndex.put(v.position, externalFullTypes.indexOf(v.name));
} else if (externalSimpleTypes.contains(v.name)) {
referenceToExternalTypeIndex.put(v.position, externalSimpleTypes.indexOf(v.name));
} else {
boolean traitFound = searchTrait(v.name, v.position, false, separatorPosToType, separatorIsStatic, 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);
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 {
if ("this".equals(v.name) && isStatic) {
errors.add(new SimpleParseException("Cannot use this in static context", -1, v.position));
} else {
@@ -317,6 +284,7 @@ public interface SimpleParser {
}
}
}
if (vt instanceof Scope) {
Scope vs = (Scope) vt;
boolean subStatic = isStatic;
@@ -347,22 +315,72 @@ public interface SimpleParser {
}
}
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, externalFullTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, linkHandler, simpleExternalClassNameToFullClassName, referenceToExternalTraitKey, externalTraitKeyToReference, separatorPosToType, separatorIsStatic);
List<VariableOrScopeWithAccess> list = new ArrayList<>();
for (VariableOrScope it : vs.getPrivateItems()) {
list.add(new VariableOrScopeWithAccess(it, false));
}
for (VariableOrScope it : vs.getSharedItems()) {
list.add(new VariableOrScopeWithAccess(it, true));
}
list.sort(new Comparator<VariableOrScopeWithAccess>() {
@Override
public int compare(VariableOrScopeWithAccess o1, VariableOrScopeWithAccess o2) {
return o1.var.getPosition() - o2.var.getPosition();
}
});
parseVariablesList(list, definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, externalFullTypes, referenceToExternalTypeIndex, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, traitFullNameToDefinition, linkHandler, simpleExternalClassNameToFullClassName, referenceToExternalTraitKey, externalTraitKeyToReference, separatorPosToType, separatorIsStatic, caretPosition, variableSuggestions, vs.getPosition(), vs.getEndPosition());
}
if (vt2 != null && caretPosition != null && variableSuggestions.isEmpty()) {
if (vt.getPosition() <= caretPosition && vt2.getPosition() > caretPosition) {
if (vt instanceof Variable) {
for (Path p : parentVarNameToDefinitionPosition.keySet()) {
if (parentVarNameToDefinitionPosition.get(p) >= 0) {
variableSuggestions.add(p.getFirst().toString());
}
}
for (Path p : privateVarNameToDefinitionPosition.keySet()) {
if (privateVarNameToDefinitionPosition.get(p) >= 0) {
variableSuggestions.add(p.getFirst().toString());
}
}
variableSuggestions.add("--finish--");
}
}
}
}
if (caretPosition != null && variableSuggestions.isEmpty() && scopeEndPos != null) {
if (scopeEndPos > caretPosition) {
for (Path p : parentVarNameToDefinitionPosition.keySet()) {
if (parentVarNameToDefinitionPosition.get(p) >= 0) {
variableSuggestions.add(p.getFirst().toString());
}
}
for (Path p : privateVarNameToDefinitionPosition.keySet()) {
if (privateVarNameToDefinitionPosition.get(p) >= 0) {
variableSuggestions.add(p.getFirst().toString());
}
}
variableSuggestions.add("--finish--");
}
}
}
public static void findClassTraits(
List<VariableOrScope> variables,
List<VariableOrScopeWithAccess> variables,
Map<Path, Integer> traitFullNameToDefinition,
Map<Integer, List<Integer>> definitionPosToReferences,
Map<Integer, Boolean> positionToStatic,
Map<Integer, Path> definitionToType,
Map<Integer, Path> definitionToCallType,
Map<Integer, Variable> definitionToSubType,
Map<Integer, Variable> definitionToCallSubType
Map<Integer, Variable> definitionToCallSubType,
Map<Path, Integer> parentVarFullNameToDefinitionPosition,
Map<Path, Integer> parentVarNameToDefinitionPosition
) {
for (VariableOrScope v : variables) {
for (VariableOrScopeWithAccess vsa : variables) {
VariableOrScope v = vsa.var;
if (v instanceof Type) {
Type t = (Type) v;
if (t.definition) {
@@ -386,11 +404,20 @@ public interface SimpleParser {
definitionToCallSubType.put(ct.position, ct.callSubType);
}
traitFullNameToDefinition.put(ct.getFullIdentifier(), ((ClassTrait) v).position);
parentVarFullNameToDefinitionPosition.put(ct.name, ct.position);
parentVarNameToDefinitionPosition.put(ct.getLastName(), ct.position);
}
if (v instanceof Scope) {
Scope s = (Scope) v;
findClassTraits(s.getPrivateItems(), traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType);
findClassTraits(s.getSharedItems(), traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType);
List<VariableOrScopeWithAccess> list = new ArrayList<>();
for (VariableOrScope it : s.getPrivateItems()) {
list.add(new VariableOrScopeWithAccess(it, false));
}
for (VariableOrScope it : s.getSharedItems()) {
list.add(new VariableOrScopeWithAccess(it, true));
}
findClassTraits(list, traitFullNameToDefinition, definitionPosToReferences, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, parentVarFullNameToDefinitionPosition, parentVarNameToDefinitionPosition);
}
}
}

View File

@@ -25,10 +25,15 @@ import java.util.List;
*/
public class TraitVarConstValueScope implements Scope {
private final int position;
private final int endPosition;
private List<VariableOrScope> sharedItems;
private final boolean isStatic;
public TraitVarConstValueScope(List<VariableOrScope> sharedItems, boolean isStatic) {
public TraitVarConstValueScope(int position, int endPosition, List<VariableOrScope> sharedItems, boolean isStatic) {
this.position = position;
this.endPosition = endPosition;
this.sharedItems = sharedItems;
this.isStatic = isStatic;
}
@@ -46,4 +51,16 @@ public class TraitVarConstValueScope implements Scope {
public List<VariableOrScope> getPrivateItems() {
return new ArrayList<>();
}
@Override
public int getPosition() {
return position;
}
@Override
public int getEndPosition() {
return endPosition;
}
}

View File

@@ -16,7 +16,6 @@
*/
package com.jpexs.decompiler.flash.simpleparser;
import java.util.Arrays;
import java.util.List;
/**
@@ -81,4 +80,9 @@ public class Variable implements VariableOrScope {
public boolean hasParent() {
return name.hasParent();
}
@Override
public int getPosition() {
return position;
}
}

View File

@@ -21,5 +21,5 @@ package com.jpexs.decompiler.flash.simpleparser;
* @author JPEXS
*/
public interface VariableOrScope {
public int getPosition();
}

View File

@@ -0,0 +1,31 @@
/*
* 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 class VariableOrScopeWithAccess {
public VariableOrScope var;
public boolean shared;
public VariableOrScopeWithAccess(VariableOrScope var, boolean shared) {
this.var = var;
this.shared = shared;
}
}

View File

@@ -93,6 +93,7 @@ import jsyntaxpane.actions.ActionUtils;
import jsyntaxpane.components.Markers;
import jsyntaxpane.components.SyntaxComponent;
import jsyntaxpane.util.Configuration;
import natorder.NaturalOrderComparator;
import org.pushingpixels.substance.internal.ui.SubstanceScrollBarUI;
/**
@@ -129,6 +130,7 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
private Map<Integer, Path> definitionToType = new LinkedHashMap<>();
private Map<Integer, Path> definitionToCallType = new LinkedHashMap<>();
private Map<Integer, Boolean> separatorIsStatic = new LinkedHashMap<>();
private List<String> variableSuggestions = new ArrayList<>();
private MouseMotionAdapter mouseMotionAdapter;
@@ -377,6 +379,9 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
if (referenceToExternalTypeIndex.containsKey(tok.start)) {
int typeIndex = referenceToExternalTypeIndex.get(tok.start);
for (int i : externalTypeIndexToReference.get(typeIndex)) {
if (separatorPosToType.containsKey(i)) {
continue;
}
Token referenceToken = getIdentifierTokenAt(sDoc, i);
if (referenceToken != null) {
Markers.SimpleMarker markerKind = marker;
@@ -399,6 +404,9 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
if (referenceToExternalTraitKey.containsKey(tok.start)) {
Path traitKey = referenceToExternalTraitKey.get(tok.start);
for (int i : externalTraitKeyToReference.get(traitKey)) {
if (separatorPosToType.containsKey(i)) {
continue;
}
Token referenceToken = getIdentifierTokenAt(sDoc, i);
if (referenceToken != null) {
Markers.SimpleMarker markerKind = marker;
@@ -437,6 +445,9 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
}
occurencesPositions.add(definitionToken.start);
for (int i : definitionPosToReferences.get(definitionPos)) {
if (separatorPosToType.containsKey(i)) {
continue;
}
Token referenceToken = getIdentifierTokenAt(sDoc, i);
if (referenceToken != null) {
markerKind = marker;
@@ -487,11 +498,14 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
int pos = pane.getCaretPosition();
Token tokenAt = getNearestTokenAt(sDoc, pos);
String identText = "";
if (tokenAt != null && tokenAt.type == TokenType.IDENTIFIER) {
identText = sDoc.getText(tokenAt.start, pos - tokenAt.start);
tokenAt = sDoc.getPrevToken(tokenAt);
} else if (tokenAt != null && tokenAt.start >= pos) {
tokenAt = sDoc.getPrevToken(tokenAt);
if (tokenAt != null && tokenAt.type == TokenType.IDENTIFIER) {
identText = sDoc.getText(tokenAt.start, pos - tokenAt.start);
tokenAt = sDoc.getPrevToken(tokenAt);
}
} else if (tokenAt == null) {
@@ -499,28 +513,22 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
pos--;
tokenAt = getNearestTokenAt(sDoc, pos);
}
if (tokenAt == null) {
sDoc.readUnlock();
return;
}
if (tokenAt.type == TokenType.IDENTIFIER) {
if (tokenAt != null && tokenAt.type == TokenType.IDENTIFIER) {
identText = sDoc.getText(tokenAt.start, pos - tokenAt.start);
tokenAt = sDoc.getPrevToken(tokenAt);
}
}
if (tokenAt == null) {
sDoc.readUnlock();
return;
}
boolean isDot = tokenAt.type == TokenType.OPERATOR ? ".".equals(sDoc.getText(tokenAt.start, tokenAt.length)) : false;
if (!isDot) {
sDoc.readUnlock();
return;
}
int afterDot = tokenAt.start + 1;
boolean isDot = tokenAt != null && tokenAt.type == TokenType.OPERATOR ? ".".equals(sDoc.getText(tokenAt.start, tokenAt.length)) : false;
sDoc.readUnlock();
pane.getDocument().remove(afterDot, pane.getCaretPosition() - afterDot);
pane.getDocument().insertString(afterDot, suggestion, null);
if (isDot) {
int afterDot = tokenAt.start + 1;
pane.getDocument().remove(afterDot, pane.getCaretPosition() - afterDot);
pane.getDocument().insertString(afterDot, suggestion, null);
} else {
pane.getDocument().remove(pane.getCaretPosition() - identText.length(), identText.length());
pane.getDocument().insertString(pane.getCaretPosition(), suggestion, null);
}
} catch (BadLocationException ex) {
//ignore
}
@@ -548,74 +556,67 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
pos--;
tokenAt = getNearestTokenAt(sDoc, pos);
}
if (tokenAt == null) {
return;
}
if (tokenAt.type == TokenType.IDENTIFIER) {
if (tokenAt != null && tokenAt.type == TokenType.IDENTIFIER) {
identText = sDoc.getText(tokenAt.start, pos - tokenAt.start);
tokenAt = sDoc.getPrevToken(tokenAt);
}
}
if (tokenAt == null) {
codeCompletionPopup.setVisible(false);
return;
}
boolean isDot = tokenAt.type == TokenType.OPERATOR ? ".".equals(sDoc.getText(tokenAt.start, tokenAt.length)) : false;
if (!isDot) {
codeCompletionPopup.setVisible(false);
return;
}
Token prevToken = sDoc.getPrevToken(tokenAt);
boolean isCall = prevToken.pairValue == -1; //-1 = -PARENT
pos = tokenAt.start;
if (!separatorPosToType.containsKey(pos)) {
return;
}
boolean isDot = tokenAt != null && tokenAt.type == TokenType.OPERATOR ? ".".equals(sDoc.getText(tokenAt.start, tokenAt.length)) : false;
List<String> suggestions = new ArrayList<>();
if (separatorPosToType.containsKey(pos)) {
Path type = separatorPosToType.get(pos);
if (isDot) {
boolean isStatic = false;
if (separatorIsStatic.containsKey(pos) && separatorIsStatic.get(pos)) {
isStatic = true;
}
Token prevToken = sDoc.getPrevToken(tokenAt);
boolean isCall = prevToken.pairValue == -1; //-1 = -PARENT
if (localTypeTraitNames.containsKey(type)) {
for (String traitName : localTypeTraitNames.get(type)) {
if (isStatic && !traitName.startsWith("static::")) {
continue;
}
if (traitName.startsWith("static::")) {
traitName = traitName.substring("static::".length());
}
suggestions.add(traitName);
}
suggestions.remove(type.getLast().toString()); //remove constructor
} else {
//type = externalTypes.get(referenceToExternalTypeIndex.get(pos));
List<String> traitNames = ((LineMarkedEditorPane) pane).getLinkHandler().getClassTraitNames(type, true, true, true);
for (String traitName : traitNames) {
if (isStatic && !traitName.startsWith("static::")) {
continue;
}
if (traitName.startsWith("static::")) {
traitName = traitName.substring("static::".length());
}
suggestions.add(traitName);
}
suggestions.remove(type.getLast().toString()); //remove constructor
pos = tokenAt.start;
if (!separatorPosToType.containsKey(pos)) {
return;
}
if (separatorPosToType.containsKey(pos)) {
Path type = separatorPosToType.get(pos);
boolean isStatic = false;
if (separatorIsStatic.containsKey(pos) && separatorIsStatic.get(pos)) {
isStatic = true;
}
if (localTypeTraitNames.containsKey(type)) {
for (String traitName : localTypeTraitNames.get(type)) {
if (isStatic && !traitName.startsWith("static::")) {
continue;
}
if (traitName.startsWith("static::")) {
traitName = traitName.substring("static::".length());
}
suggestions.add(traitName);
}
suggestions.remove(type.getLast().toString()); //remove constructor
} else {
//type = externalTypes.get(referenceToExternalTypeIndex.get(pos));
List<String> traitNames = ((LineMarkedEditorPane) pane).getLinkHandler().getClassTraitNames(type, true, true, true);
for (String traitName : traitNames) {
if (isStatic && !traitName.startsWith("static::")) {
continue;
}
if (traitName.startsWith("static::")) {
traitName = traitName.substring("static::".length());
}
suggestions.add(traitName);
}
suggestions.remove(type.getLast().toString()); //remove constructor
}
}
} else {
suggestions.addAll(variableSuggestions);
}
if (suggestions.isEmpty()) {
codeCompletionPopup.setVisible(false);
return;
}
Collections.sort(suggestions);
Collections.sort(suggestions, new NaturalOrderComparator());
if (!identText.isEmpty()) {
for (int i = suggestions.size() - 1; i >= 0; i--) {
String sug = suggestions.get(i);
@@ -624,7 +625,7 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
}
}
}
codeCompletionListModel.clear();
codeCompletionListModel.addAll(suggestions);
@@ -687,6 +688,9 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
tim = null;
}
if (e.getKeyChar() == '.') {
if (!editor.isEditable()) {
return;
}
tim = new Timer();
tim.schedule(new TimerTask() {
@Override
@@ -738,6 +742,10 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
View.addEditorAction(pane, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (!pane.isEditable()) {
return;
}
documentUpdated();
showCodeCompletion();
}
@@ -987,6 +995,7 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
Map<Integer, Path> newDefinitionToType = new LinkedHashMap<>();
Map<Integer, Path> newDefinitionToCallType = new LinkedHashMap<>();
Map<Integer, Boolean> newSeparatorIsStatic = new LinkedHashMap<>();
List<String> newVariableSuggestions = new ArrayList<>();
parser.parse(
fullText,
newDefinitionPosToReferences,
@@ -1001,7 +1010,9 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
newSeparatorIsStatic,
newLocalTypeTraitNames,
newDefinitionToType,
newDefinitionToCallType
newDefinitionToCallType,
pane.getCaretPosition(),
newVariableSuggestions
);
Map<Path, Path> newSimpleExternalClassNameToFullClassName = new LinkedHashMap<>();
@@ -1022,6 +1033,7 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
definitionToType = newDefinitionToType;
definitionToCallType = newDefinitionToCallType;
separatorIsStatic = newSeparatorIsStatic;
variableSuggestions = newVariableSuggestions;
for (SimpleParseException ex : newErrors) {
errors.put((int) ex.position, ex.getMessage());
}
@@ -1067,6 +1079,9 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC
}
private LinkType getLinkType(Token token) {
if (separatorPosToType.containsKey(token.start)) {
return LinkType.NO_LINK;
}
if (definitionPosToReferences.containsKey(token.start)) {
return LinkType.NO_LINK;
}