From 11cd34200a9c3f141968022d515926b1a19ff756 Mon Sep 17 00:00:00 2001 From: m0rkeulv Date: Wed, 1 Nov 2023 21:50:20 +0100 Subject: [PATCH] changing findHaxeMethodByName/findHaxeFieldByName to check parent classes and forwarded methods and canAssignType to check inherited classes/interfaces --- .../lang/psi/impl/AbstractHaxePsiClass.java | 31 ++++++++++++- .../plugins/haxe/model/HaxeClassModel.java | 10 +++- .../haxe/model/type/HaxeClassReference.java | 2 + .../haxe/model/type/HaxeTypeCompatible.java | 46 ++++++++++++++----- .../haxe/model/type/HaxeTypeResolver.java | 2 +- .../plugins/haxe/util/HaxeResolveUtil.java | 18 ++++++-- 6 files changed, 89 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/intellij/plugins/haxe/lang/psi/impl/AbstractHaxePsiClass.java b/src/main/java/com/intellij/plugins/haxe/lang/psi/impl/AbstractHaxePsiClass.java index 52883ad1c..0548721f6 100644 --- a/src/main/java/com/intellij/plugins/haxe/lang/psi/impl/AbstractHaxePsiClass.java +++ b/src/main/java/com/intellij/plugins/haxe/lang/psi/impl/AbstractHaxePsiClass.java @@ -241,12 +241,12 @@ public List getFieldSelf(@Nullable HaxeGenericResolver res @Nullable @Override public HaxeNamedComponent findHaxeFieldByName(@NotNull final String name, @Nullable HaxeGenericResolver resolver) { - return ContainerUtil.find(getHaxeFieldsSelf(resolver), component -> name.equals(component.getName())); + return ContainerUtil.find(getHaxeFieldAll(HaxeComponentType.CLASS, HaxeComponentType.ENUM), component -> name.equals(component.getName())); } @Override public HaxeNamedComponent findHaxeMethodByName(@NotNull final String name, @Nullable HaxeGenericResolver resolver) { - return ContainerUtil.find(getHaxeMethodsSelf(resolver), (Condition)component -> name.equals(component.getName())); + return ContainerUtil.find(getHaxeMethodsAll(HaxeComponentType.CLASS), (Condition)component -> name.equals(component.getName())); } /** Optimized path to replace findHaxeMethod and findHaxeField when used together. */ @@ -498,6 +498,19 @@ public List getHaxeMethodsAll(HaxeComponentType... fromTypesFilter) for (HaxeNamedComponent method : methods) { result.add((HaxeMethod)method); } + if (this.getModel() instanceof HaxeAbstractClassModel model) { + if (model.hasForwards()) { + HaxeClass underlyingClass = model.getUnderlyingClass(null); + if (underlyingClass instanceof AbstractHaxePsiClass abstractHaxePsiClass) { + List components = abstractHaxePsiClass.getAllHaxeNamedComponents(HaxeComponentType.METHOD); + for (HaxeNamedComponent component : components) { + if (model.isForwarded(component.getName())) { + result.add((HaxeMethod)component); + } + } + } + } + } return result; } @NotNull @@ -517,6 +530,20 @@ public List getHaxeFieldAll(HaxeComponentType... fromTypes for (HaxeNamedComponent field : fields) { result.add((HaxeFieldDeclaration)field); } + if (this.getModel() instanceof HaxeAbstractClassModel model) { + if (model.hasForwards()) { + HaxeClass underlyingClass = model.getUnderlyingClass(null); + if (underlyingClass instanceof AbstractHaxePsiClass abstractHaxePsiClass) { + List components = abstractHaxePsiClass.getAllHaxeNamedComponents(HaxeComponentType.FIELD); + for (HaxeNamedComponent field : fields) { + if (model.isForwarded(field.getName())) { + result.add((HaxeFieldDeclaration)field); + } + } + } + } + } + return result; } diff --git a/src/main/java/com/intellij/plugins/haxe/model/HaxeClassModel.java b/src/main/java/com/intellij/plugins/haxe/model/HaxeClassModel.java index c595e5610..f1f1bae26 100644 --- a/src/main/java/com/intellij/plugins/haxe/model/HaxeClassModel.java +++ b/src/main/java/com/intellij/plugins/haxe/model/HaxeClassModel.java @@ -50,6 +50,8 @@ public class HaxeClassModel implements HaxeExposableModel { private HaxeModifiersModel _modifiers; + private SpecificHaxeClassReference reference; + //for caching purposes private FullyQualifiedInfo myQualifiedInfo; @@ -79,7 +81,13 @@ public HaxeClassReference getReference() { @NotNull public ResultHolder getInstanceType() { - return SpecificHaxeClassReference.withoutGenerics(getReference()).createHolder(); + return getInstanceReference().createHolder(); + } + public SpecificHaxeClassReference getInstanceReference() { + if (reference == null) { + reference = SpecificHaxeClassReference.withoutGenerics(getReference()); + } + return reference; } public List getExtendingTypes() { diff --git a/src/main/java/com/intellij/plugins/haxe/model/type/HaxeClassReference.java b/src/main/java/com/intellij/plugins/haxe/model/type/HaxeClassReference.java index de9909a99..426cbb3fa 100644 --- a/src/main/java/com/intellij/plugins/haxe/model/type/HaxeClassReference.java +++ b/src/main/java/com/intellij/plugins/haxe/model/type/HaxeClassReference.java @@ -96,6 +96,8 @@ private String getClassNameInternal(HaxeClassModel clazz) { public HaxeClass getHaxeClass() { if (this.classModel != null) return classModel.getPsi(); if (this.clazz != null) return clazz; + // no real HaxeClass exists for type parameters (only HaxeClassWrapperForTypeParameter synthetically created) + if (this.isTypeParameter) return null; clazz = HaxeResolveUtil.findClassByQName(name, elementContext); if (clazz == null) { clazz = HaxeResolveUtil.tryResolveClassByQName(elementContext); diff --git a/src/main/java/com/intellij/plugins/haxe/model/type/HaxeTypeCompatible.java b/src/main/java/com/intellij/plugins/haxe/model/type/HaxeTypeCompatible.java index 695d76cb2..3d50b3a69 100644 --- a/src/main/java/com/intellij/plugins/haxe/model/type/HaxeTypeCompatible.java +++ b/src/main/java/com/intellij/plugins/haxe/model/type/HaxeTypeCompatible.java @@ -21,9 +21,7 @@ import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.plugins.haxe.lang.psi.*; -import com.intellij.plugins.haxe.model.HaxeClassModel; -import com.intellij.plugins.haxe.model.HaxeMemberModel; -import com.intellij.plugins.haxe.model.HaxeMethodModel; +import com.intellij.plugins.haxe.model.*; import com.intellij.plugins.haxe.util.HaxeResolveUtil; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; @@ -570,7 +568,7 @@ static public boolean canAssignToFromSpecificType( static private boolean canAssignToFromSpecificType( @NotNull SpecificHaxeClassReference to, @NotNull SpecificHaxeClassReference from, - @Nullable List recursionGuard + @Nullable List recursionGuard ) { if (to.isDynamic() || from.isDynamic()) { return true; @@ -623,16 +621,42 @@ else if (from.getSpecifics().length == 0) { return true; } } - if (to.getHaxeClass() != null && to.getHaxeClass().isInterface()) { - Set fromInferTypes = from.getInferTypes(); - for (SpecificHaxeClassReference fromInterface : fromInferTypes) { - if (recursionGuard == null) recursionGuard = new ArrayList<>(); - if (!recursionGuard.contains(fromInterface)) { - recursionGuard.add(fromInterface); - if (canAssignToFromSpecificType(to, fromInterface, recursionGuard)) return true; + // if not working with type parameters check inheritance + if (!to.isFromTypeParameter() && !from.isFromTypeParameter()) { + if (to.getHaxeClass() != null && to.getHaxeClass().isInterface()) { + Set fromInferTypes = from.getInferTypes(); + for (SpecificHaxeClassReference fromInterface : fromInferTypes) { + HaxeClassModel classModel = fromInterface.getHaxeClassModel(); + if (recursionGuard == null) recursionGuard = new ArrayList<>(); + if (!recursionGuard.contains(classModel)) { + recursionGuard.add(classModel); + if (canAssignToFromSpecificType(to, fromInterface, recursionGuard)) return true; + } + } + } + HaxeClass haxeClass = from.getHaxeClass(); + if (haxeClass != null) { + + + List extendsList = haxeClass.getHaxeExtendsList(); + for (HaxeType type : extendsList) { + PsiElement resolve = type.getReferenceExpression().resolve(); + if (resolve instanceof HaxeClass fromClass) { + HaxeClassModel fromModel = fromClass.getModel(); + if (fromModel != null) { + if (recursionGuard == null) recursionGuard = new ArrayList<>(); + if (!recursionGuard.contains(fromModel)) { + recursionGuard.add(fromModel); + SpecificHaxeClassReference fromReference = + SpecificHaxeClassReference.withoutGenerics(new HaxeClassReference(fromModel, fromClass)); + if (canAssignToFromSpecificType(to, fromReference, recursionGuard)) return true; + } + } + } } } } + return false; } diff --git a/src/main/java/com/intellij/plugins/haxe/model/type/HaxeTypeResolver.java b/src/main/java/com/intellij/plugins/haxe/model/type/HaxeTypeResolver.java index 9dd035054..76abcea36 100644 --- a/src/main/java/com/intellij/plugins/haxe/model/type/HaxeTypeResolver.java +++ b/src/main/java/com/intellij/plugins/haxe/model/type/HaxeTypeResolver.java @@ -266,7 +266,7 @@ static private ResultHolder getFunctionReturnType(HaxeNamedComponent comp, HaxeG if (typeOrAnonymous != null) { //TODO resolve for anonymous types ? if (typeOrAnonymous.getType() != null) { - ResultHolder type = HaxeTypeResolver.getTypeFromType(typeOrAnonymous.getType()); + ResultHolder type = HaxeTypeResolver.getTypeFromType(typeOrAnonymous.getType(), resolver); ResultHolder resolve = resolver.resolveReturnType(type); if (resolve != null && !resolve.isUnknown()) { return resolve; diff --git a/src/main/java/com/intellij/plugins/haxe/util/HaxeResolveUtil.java b/src/main/java/com/intellij/plugins/haxe/util/HaxeResolveUtil.java index a9bcb1985..ff0bae7e9 100644 --- a/src/main/java/com/intellij/plugins/haxe/util/HaxeResolveUtil.java +++ b/src/main/java/com/intellij/plugins/haxe/util/HaxeResolveUtil.java @@ -400,14 +400,22 @@ public int compare(HaxeNamedComponent o1, HaxeNamedComponent o2) { } public static List getAllNamedSubComponentsFromClassType(HaxeClass haxeClass, HaxeComponentType... fromTypes) { + return getAllNamedSubComponentsFromClassType(haxeClass, fromTypes, null); + } + public static List getAllNamedSubComponentsFromClassType(HaxeClass haxeClass, HaxeComponentType[] fromTypes, List recursionGuard) { + if (recursionGuard == null) recursionGuard = new ArrayList<>(); List components = getNamedSubComponents(haxeClass); List types = Arrays.asList(fromTypes); - components.addAll(Stream.of(haxeClass.getSupers()) - .filter(superComponent -> types.isEmpty() || types.contains(HaxeComponentType.typeOf(superComponent))) - .map(superComponent -> getAllNamedSubComponentsFromClassType((HaxeClass)superComponent, fromTypes)) - .flatMap(Collection::stream) - .toList()); + for (PsiClass superComponent : haxeClass.getSupers()) { + if (recursionGuard.contains(superComponent)) continue; + recursionGuard.add(superComponent); + + if (types.isEmpty() || types.contains(HaxeComponentType.typeOf(superComponent))) { + List type = getAllNamedSubComponentsFromClassType((HaxeClass)superComponent, fromTypes, recursionGuard); + components.addAll(type); + } + } if (types.contains(HaxeComponentType.typeOf(haxeClass))) { components.addAll(getNamedSubComponents(haxeClass));