Skip to content

Commit

Permalink
changing findHaxeMethodByName/findHaxeFieldByName to check parent cla…
Browse files Browse the repository at this point in the history
…sses and forwarded methods and canAssignType to check inherited classes/interfaces
  • Loading branch information
m0rkeulv committed Nov 1, 2023
1 parent 4a0aef2 commit 11cd342
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,12 @@ public List<HaxeFieldDeclaration> 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<HaxeNamedComponent>)component -> name.equals(component.getName()));
return ContainerUtil.find(getHaxeMethodsAll(HaxeComponentType.CLASS), (Condition<HaxeNamedComponent>)component -> name.equals(component.getName()));
}

/** Optimized path to replace findHaxeMethod and findHaxeField when used together. */
Expand Down Expand Up @@ -498,6 +498,19 @@ public List<HaxeMethod> 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<HaxeNamedComponent> components = abstractHaxePsiClass.getAllHaxeNamedComponents(HaxeComponentType.METHOD);
for (HaxeNamedComponent component : components) {
if (model.isForwarded(component.getName())) {
result.add((HaxeMethod)component);
}
}
}
}
}
return result;
}
@NotNull
Expand All @@ -517,6 +530,20 @@ public List<HaxeFieldDeclaration> 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<HaxeNamedComponent> components = abstractHaxePsiClass.getAllHaxeNamedComponents(HaxeComponentType.FIELD);
for (HaxeNamedComponent field : fields) {
if (model.isForwarded(field.getName())) {
result.add((HaxeFieldDeclaration)field);
}
}
}
}
}

return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public class HaxeClassModel implements HaxeExposableModel {

private HaxeModifiersModel _modifiers;

private SpecificHaxeClassReference reference;

//for caching purposes
private FullyQualifiedInfo myQualifiedInfo;

Expand Down Expand Up @@ -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<HaxeClassReferenceModel> getExtendingTypes() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -570,7 +568,7 @@ static public boolean canAssignToFromSpecificType(
static private boolean canAssignToFromSpecificType(
@NotNull SpecificHaxeClassReference to,
@NotNull SpecificHaxeClassReference from,
@Nullable List<SpecificHaxeClassReference> recursionGuard
@Nullable List<HaxeModel> recursionGuard
) {
if (to.isDynamic() || from.isDynamic()) {
return true;
Expand Down Expand Up @@ -623,16 +621,42 @@ else if (from.getSpecifics().length == 0) {
return true;
}
}
if (to.getHaxeClass() != null && to.getHaxeClass().isInterface()) {
Set<SpecificHaxeClassReference> 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<SpecificHaxeClassReference> 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<HaxeType> 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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
18 changes: 13 additions & 5 deletions src/main/java/com/intellij/plugins/haxe/util/HaxeResolveUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -400,14 +400,22 @@ public int compare(HaxeNamedComponent o1, HaxeNamedComponent o2) {
}

public static List<HaxeNamedComponent> getAllNamedSubComponentsFromClassType(HaxeClass haxeClass, HaxeComponentType... fromTypes) {
return getAllNamedSubComponentsFromClassType(haxeClass, fromTypes, null);
}
public static List<HaxeNamedComponent> getAllNamedSubComponentsFromClassType(HaxeClass haxeClass, HaxeComponentType[] fromTypes, List<PsiClass> recursionGuard) {
if (recursionGuard == null) recursionGuard = new ArrayList<>();
List<HaxeNamedComponent> components = getNamedSubComponents(haxeClass);
List<HaxeComponentType> 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<HaxeNamedComponent> type = getAllNamedSubComponentsFromClassType((HaxeClass)superComponent, fromTypes, recursionGuard);
components.addAll(type);
}
}

if (types.contains(HaxeComponentType.typeOf(haxeClass))) {
components.addAll(getNamedSubComponents(haxeClass));
Expand Down

0 comments on commit 11cd342

Please sign in to comment.