Skip to content

Commit

Permalink
Fixing bug for assignHint & function reference + wip logic to find/cr…
Browse files Browse the repository at this point in the history
…eate resolver for base class
  • Loading branch information
m0rkeulv committed Feb 24, 2024
1 parent 5247567 commit 6dedbea
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ static public boolean isValidClassName(String name) {
return name.substring(0, 1).equals(name.substring(0, 1).toUpperCase());
}

@NotNull
public HaxeClassReference getReference() {
return new HaxeClassReference(this, this.getPsi());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
package com.intellij.plugins.haxe.model;

import com.intellij.plugins.haxe.lang.psi.*;
import com.intellij.plugins.haxe.model.type.HaxeClassReference;
import com.intellij.plugins.haxe.model.type.ResultHolder;
import com.intellij.plugins.haxe.model.type.SpecificHaxeClassReference;
import com.intellij.plugins.haxe.util.HaxeResolveUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -54,4 +57,11 @@ public HaxeClassModel getHaxeClass() {
}
return (_clazz != null) ? _clazz.getModel() : null;
}
public SpecificHaxeClassReference getSpecificHaxeClassReference() {
HaxeClassReference reference = getHaxeClass().getReference();
List<HaxeTypeParameterModel> parameters = getTypeParameters();
List<ResultHolder> generics = parameters.stream().map(model -> model.getTypeReference().getSpecificHaxeClassReference().createHolder()).toList();
return SpecificHaxeClassReference.withGenerics(reference, generics.toArray(new ResultHolder[0]));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,13 @@ else if (subelement instanceof HaxeFieldDeclaration fieldDeclaration) {
}
}
else if (subelement instanceof HaxeMethodDeclaration methodDeclaration) {
SpecificFunctionReference type = methodDeclaration.getModel().getFunctionType(resolver);
boolean isFromCallExpression = reference instanceof HaxeCallExpression;
SpecificFunctionReference type = methodDeclaration.getModel().getFunctionType(isFromCallExpression ? resolver : resolver.withoutAssignHint());
if (!isFromCallExpression) {
// expression is referring to the method not calling it.
// assign hint should be used for substituting parameters instead of being used as return type
type = resolver.substituteTypeParamsWithAssignHintTypes(type);
}
typeHolder = type.createHolder();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,4 +512,39 @@ public void addAssignHint(HaxeGenericResolver resolver) {
}
}

public SpecificFunctionReference substituteTypeParamsWithAssignHintTypes(SpecificFunctionReference type) {
Optional<ResolverEntry> assignHint = findAssignToType();
if (assignHint.isEmpty()) return type;

ResultHolder assignType = assignHint.get().type();
SpecificFunctionReference functionTypeHint = assignType.getFunctionType();
if (functionTypeHint == null) return type;

List<SpecificFunctionReference.Argument> originalArguments = type.getArguments();
List<SpecificFunctionReference.Argument> hintArguments = functionTypeHint.getArguments();

LinkedList<SpecificFunctionReference.Argument> args = new LinkedList<>();

int minArgs = Math.min(originalArguments.size(), hintArguments.size());
for (int i = 0; i < minArgs; i++) {
SpecificFunctionReference.Argument argument = originalArguments.get(i);
if (argument.isTypeParameter()) {
SpecificFunctionReference.Argument hint = hintArguments.get(i);
args.add(new SpecificFunctionReference.Argument(i, argument.isOptional(), argument.isRest(), hint.getType(), argument.getName()));
}else {
args.add(argument);
}
}
ResultHolder returnType = type.getReturnType();
if (returnType.isTypeParameter()) {
returnType = functionTypeHint.getReturnType();
}
if (type.method != null) {
return new SpecificFunctionReference(args, returnType, type.method, type.context );
}else {
return new SpecificFunctionReference(args, returnType, type.functionType, type.context);
}


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,50 @@ public ResultHolder access(String name, HaxeExpressionEvaluatorContext context,
HaxeNamedComponent field = aClass.findHaxeFieldByName(name, localResolver);
if (field != null) {
if (context.root == field) return null;
HaxeClass containingClass = (HaxeClass)((HaxePsiField)field).getContainingClass();
if (containingClass != aClass) {
localResolver.addAll(createInheritedClassResolver(containingClass, aClass, localResolver));
}
return HaxeTypeResolver.getFieldOrMethodReturnType(field, localResolver);
}
return null;
}

private HaxeGenericResolver createInheritedClassResolver(HaxeClass inheritedClass, HaxeClass ownerClass,
HaxeGenericResolver localResolver) {

List<SpecificHaxeClassReference> path = new ArrayList<>();
findClasHierarchy(ownerClass, inheritedClass, path);

Collections.reverse(path);
HaxeGenericResolver resolver = ownerClass.getMemberResolver(localResolver);
for (SpecificHaxeClassReference reference : path) {
ResultHolder resolved = resolver.resolve(reference.createHolder());
resolver = resolved.getClassType().getGenericResolver();
}
return resolver;
}

private boolean findClasHierarchy(HaxeClass from, HaxeClass to, List<SpecificHaxeClassReference> path) {
List<HaxeClassReferenceModel> types = from.getModel().getExtendingTypes();
for (HaxeClassReferenceModel model : types) {
HaxeClassModel classModel = model.getHaxeClass();
if (classModel != null) {
HaxeClass childClass = classModel.haxeClass;
if (childClass == to) {
return path.add(model.getSpecificHaxeClassReference());
} else {
if (findClasHierarchy(childClass, to, path)) {
path.add(model.getSpecificHaxeClassReference());
return true;
}
}
}
}

return false;
}


public enum Compatibility {
ASSIGNABLE_TO, // Assignable via @:to or "to <Type>" on an abstract.
Expand Down

0 comments on commit 6dedbea

Please sign in to comment.