Code completion popup shows property/function types

This commit is contained in:
Jindra Petřík
2025-06-15 21:50:18 +02:00
parent f5b66b6322
commit 551b0e45a5
8 changed files with 204 additions and 108 deletions

View File

@@ -616,17 +616,17 @@ public final class AbcIndexing {
return classNames;
}
public Set<String> getClassTraitNames(GraphTargetItem cls, ABC abc, Integer scriptIndex, boolean getStatic, boolean getInstance, boolean getInheritance) {
public void getClassTraits(GraphTargetItem cls, ABC abc, Integer scriptIndex, boolean getStatic, boolean getInstance, boolean getInheritance, List<PropertyDef> ret, List<Boolean> staticRet) {
ClassIndex ci = findClass(cls, abc, scriptIndex);
if (ci == null) {
return new LinkedHashSet<>();
return;
}
Set<String> ret = new LinkedHashSet<>();
getClassIndexTraitNames(ret, ci, getStatic, getInstance, getInheritance);
return ret;
ret.clear();
staticRet.clear();
getClassIndexTraitNames(ret, staticRet, ci, getStatic, getInstance, getInheritance, new HashSet<>());
}
private void getClassIndexTraitNames(Set<String> ret, ClassIndex ci, boolean getStatic, boolean getInstance, boolean getInheritance) {
private void getClassIndexTraitNames(List<PropertyDef> ret, List<Boolean> staticRet, ClassIndex ci, boolean getStatic, boolean getInstance, boolean getInheritance, Set<String> used) {
GraphTargetItem ciName = multinameToType(ci.abc.instance_info.get(ci.index).name_index, ci.abc.constants);
boolean isObject = ciName.equals(new TypeItem("Object"));
@@ -643,9 +643,16 @@ public final class AbcIndexing {
}
if (nsKind == Namespace.KIND_PRIVATE || nsKind == Namespace.KIND_PROTECTED || nsKind == Namespace.KIND_STATIC_PROTECTED) {
continue;
}
if (Objects.equals(def.parent, ciName)) {
ret.add(def.propName);
}
if (Objects.equals(def.parent, ciName)) {
if (used.contains(def.propName)) {
continue;
}
used.add(def.propName);
ret.add(def);
staticRet.add(false);
}
}
}
@@ -662,17 +669,23 @@ public final class AbcIndexing {
continue;
}
if (Objects.equals(def.parent, ciName)) {
ret.add("static::" + def.propName);
if (used.contains(def.propName)) {
continue;
}
used.add(def.propName);
ret.add(def);
staticRet.add(true);
}
}
}
if (getInheritance && ci.parent != null) {
getClassIndexTraitNames(ret, ci.parent, getStatic, getInstance, getInheritance);
}
if (parent != null) {
parent.getClassIndexTraitNames(ret, ci, getStatic, getInstance, getInheritance);
parent.getClassIndexTraitNames(ret, staticRet, ci, getStatic, getInstance, getInheritance, used);
}
if (getInheritance && ci.parent != null) {
getClassIndexTraitNames(ret, staticRet, ci.parent, getStatic, getInstance, getInheritance, used);
}
}
/**

View File

@@ -2310,11 +2310,11 @@ public class ActionScript3SimpleParser implements SimpleParser {
Map<Path, List<Integer>> externalTraitKeyToReference,
Map<Integer, Path> separatorPosToType,
Map<Integer, Boolean> separatorIsStatic,
Map<Path, List<String>> localTypeTraitNames,
Map<Path, List<Variable>> localTypeTraits,
Map<Integer, Path> definitionToType,
Map<Integer, Path> definitionToCallType,
Integer caretPosition,
List<String> variableSuggestions
List<Variable> variableSuggestions
) throws SimpleParseException, IOException, InterruptedException {
List<List<NamespaceItem>> allOpenedNamespaces = new ArrayList<>();
Reference<Boolean> sinitNeedsActivation = new Reference<>(false);
@@ -2334,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(vars, definitionPosToReferences, referenceToDefinition, errors, true, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference, linkHandler, referenceToExternalTraitKey, externalTraitKeyToReference, separatorPosToType, separatorIsStatic, localTypeTraitNames, definitionToType, definitionToCallType, caretPosition, variableSuggestions);
SimpleParser.parseVariablesList(vars, definitionPosToReferences, referenceToDefinition, errors, true, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference, linkHandler, referenceToExternalTraitKey, externalTraitKeyToReference, separatorPosToType, separatorIsStatic, localTypeTraits, definitionToType, definitionToCallType, caretPosition, variableSuggestions);
}
/**

View File

@@ -1595,11 +1595,11 @@ public class ActionScript2SimpleParser implements SimpleParser {
Map<Path, List<Integer>> externalTraitKeyToReference,
Map<Integer, Path> separatorPosToType,
Map<Integer, Boolean> separatorIsStatic,
Map<Path, List<String>> localTypeTraitNames,
Map<Path, List<Variable>> localTypeTraits,
Map<Integer, Path> definitionToType,
Map<Integer, Path> definitionToCallType,
Integer caretPosition,
List<String> variableSuggestions
List<Variable> variableSuggestions
) throws SimpleParseException, IOException, InterruptedException {
List<VariableOrScope> vars = new ArrayList<>();
@@ -1690,7 +1690,7 @@ public class ActionScript2SimpleParser implements SimpleParser {
} catch (ActionParseException ex) {
errors.add(new SimpleParseException(ex.getMessage(), ex.line, ex.position));
}
SimpleParser.parseVariablesList(vars, definitionPosToReferences, referenceToDefinition, errors, false, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference, linkHandler, referenceToExternalTraitKey, externalTraitKeyToReference, separatorPosToType, separatorIsStatic, localTypeTraitNames, definitionToType, definitionToCallType, caretPosition, variableSuggestions);
SimpleParser.parseVariablesList(vars, definitionPosToReferences, referenceToDefinition, errors, false, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference, linkHandler, referenceToExternalTraitKey, externalTraitKeyToReference, separatorPosToType, separatorIsStatic, localTypeTraits, definitionToType, definitionToCallType, caretPosition, variableSuggestions);
}
private void versionRequired(List<SimpleParseException> errors, ParsedSymbol s, int min) throws SimpleParseException {

View File

@@ -40,5 +40,5 @@ public interface LinkHandler {
public void handleTraitLink(Path className, String traitName);
public List<String> getClassTraitNames(Path className, boolean getStatic, boolean getInstance, boolean getInheritance);
public List<Variable> getClassTraits(Path className, boolean getStatic, boolean getInstance, boolean getInheritance);
}

View File

@@ -63,13 +63,60 @@ public interface SimpleParser {
Map<Path, List<Integer>> externalTraitKeyToReference,
Map<Integer, Path> separatorPosToType,
Map<Integer, Boolean> separatorIsStatic,
Map<Path, List<String>> localTypeTraitNames,
Map<Path, List<Variable>> localTypeTraitNames,
Map<Integer, Path> definitionToType,
Map<Integer, Path> definitionToCallType,
Integer caretPosition,
List<String> variableSuggestions
List<Variable> variableSuggestions
) throws SimpleParseException, IOException, InterruptedException;
public static void fillSuggestionsOne(
List<Variable> variableSuggestions,
Map<Path, Integer> varNameToDefinition,
Map<Integer, Boolean> positionToStatic,
Map<Integer, Path> definitionToType,
Map<Integer, Path> definitionToCallType,
Map<Integer, Variable> definitionToSubType,
Map<Integer, Variable> definitionToCallSubType,
Set<String> used
) {
for (Path p : varNameToDefinition.keySet()) {
int definition = varNameToDefinition.get(p);
if (definition >= 0) {
if (used.contains(p.getLast().toString())) {
continue;
}
used.add(p.getLast().toString());
Path type = definitionToType.get(definition);;
Path callType = definitionToCallType.get(definition);
Variable subType = definitionToSubType.get(definition);
Variable callSubType = definitionToCallSubType.get(definition);
Boolean isStatic = positionToStatic.get(definition);
variableSuggestions.add(new Variable(true, p, definition, isStatic, type, callType, subType, callSubType));
}
}
}
public static void fillSuggestions(List<Variable> variableSuggestions,
Map<Path, Integer> varNameToDefinition1,
Map<Path, Integer> varNameToDefinition2,
Map<Integer, Boolean> positionToStatic,
Map<Integer, Path> definitionToType,
Map<Integer, Path> definitionToCallType,
Map<Integer, Variable> definitionToSubType,
Map<Integer, Variable> definitionToCallSubType
) {
Set<String> used = new HashSet<>();
if (varNameToDefinition1 != null) {
fillSuggestionsOne(variableSuggestions, varNameToDefinition1, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, used);
}
if (varNameToDefinition2 != null) {
fillSuggestionsOne(variableSuggestions, varNameToDefinition2, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType, used);
}
variableSuggestions.add(new Variable(true, new Path("--finish--"), 0));
}
public static void parseVariablesList(
List<VariableOrScope> sharedVariables,
Map<Integer, List<Integer>> definitionPosToReferences,
@@ -84,11 +131,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<Variable>> localTypeTraits,
Map<Integer, Path> definitionToType,
Map<Integer, Path> definitionToCallType,
Integer caretPosition,
List<String> variableSuggestions
List<Variable> variableSuggestions
) {
List<Path> externalSimpleTypes = new ArrayList<>();
Map<Path, Path> simpleExternalClassNameToFullClassName = new LinkedHashMap<>();
@@ -121,12 +168,17 @@ public interface SimpleParser {
if (positionToStatic.containsKey(definition) && positionToStatic.get(definition)) {
isStatic = true;
}
Path traitType = definitionToType.get(definition);
Path traitCallType = definitionToCallType.get(definition);
Variable traitSubType = definitionToSubType.get(definition);
Variable traitCallSubType = definitionToCallSubType.get(definition);
Path cls = p.getParent();
String traitName = p.getLast().toString();
if (!localTypeTraitNames.containsKey(cls)) {
localTypeTraitNames.put(cls, new ArrayList<>());
if (!localTypeTraits.containsKey(cls)) {
localTypeTraits.put(cls, new ArrayList<>());
}
localTypeTraitNames.get(cls).add((isStatic ? "static::" : "") + traitName);
localTypeTraits.get(cls).add(new Variable(true, p.getLast(), definition, isStatic, traitType, traitCallType, traitSubType, traitCallSubType));
}
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);
@@ -139,21 +191,13 @@ public interface SimpleParser {
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--");
fillSuggestions(variableSuggestions, parentVarNameToDefinitionPosition, null, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType);
}
}
if (!variableSuggestions.isEmpty()) {
variableSuggestions.remove(variableSuggestions.size() - 1);
}
Set<String> uniqueSuggestions = new LinkedHashSet<>(variableSuggestions);
variableSuggestions.clear();
variableSuggestions.addAll(uniqueSuggestions);
}
}
public static void parseVariablesList(
@@ -182,7 +226,7 @@ public interface SimpleParser {
Map<Integer, Path> separatorPosToType,
Map<Integer, Boolean> separatorIsStatic,
Integer caretPosition,
List<String> variableSuggestions,
List<Variable> variableSuggestions,
Integer scopeStartPos,
Integer scopeEndPos
) {
@@ -203,17 +247,7 @@ public interface SimpleParser {
&& 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--");
fillSuggestions(variableSuggestions, parentVarNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType);
}
if (vt instanceof Separator) {
@@ -321,17 +355,7 @@ public interface SimpleParser {
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--");
fillSuggestions(variableSuggestions, parentVarNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType);
}
}
}
@@ -339,17 +363,7 @@ public interface SimpleParser {
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--");
fillSuggestions(variableSuggestions, parentVarNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, definitionToType, definitionToCallType, definitionToSubType, definitionToCallSubType);
}
}
}