diff --git a/src/common/com/intellij/plugins/haxe/ide/HaxeLookupElement.java b/src/common/com/intellij/plugins/haxe/ide/HaxeLookupElement.java index 20d5250e0..ff60a64ac 100644 --- a/src/common/com/intellij/plugins/haxe/ide/HaxeLookupElement.java +++ b/src/common/com/intellij/plugins/haxe/ide/HaxeLookupElement.java @@ -34,13 +34,14 @@ import com.intellij.plugins.haxe.model.HaxeMethodContext; import com.intellij.plugins.haxe.model.HaxeMethodModel; import com.intellij.plugins.haxe.model.type.HaxeGenericResolver; -import com.intellij.plugins.haxe.model.type.ResultHolder; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import static com.intellij.plugins.haxe.model.type.HaxeGenericResolverUtil.getResolverSkipAbstractNullScope; + /** * @author: Fedor.Korotkov */ @@ -84,7 +85,12 @@ public void renderElement(LookupElementPresentation presentation) { presentation.setItemText(getLookupString()); return; } - HaxeGenericResolver resolver = leftReference == null ? null :leftReference.getGenericResolver();; + + HaxeGenericResolver resolver = null; + if(leftReference != null && leftReference.getHaxeClass() != null) { + resolver = getResolverSkipAbstractNullScope(leftReference.getHaxeClass().getModel(), leftReference.getGenericResolver()); + } + String presentableText = myComponentNamePresentation.getPresentableText(); diff --git a/src/common/com/intellij/plugins/haxe/lang/psi/impl/HaxeReferenceImpl.java b/src/common/com/intellij/plugins/haxe/lang/psi/impl/HaxeReferenceImpl.java index 05fc85780..2111fdb53 100644 --- a/src/common/com/intellij/plugins/haxe/lang/psi/impl/HaxeReferenceImpl.java +++ b/src/common/com/intellij/plugins/haxe/lang/psi/impl/HaxeReferenceImpl.java @@ -485,7 +485,13 @@ private HaxeClassResolveResult resolveHaxeClassInternal() { if (expression instanceof HaxeReference) { // creating a resolver that combines parent(leftExpression) current(expression) and children (parameterExpressions) HaxeGenericResolver resolver = new HaxeGenericResolver(); - resolver.addAll(leftResult.getGenericResolver()); + + if (leftResult.getHaxeClass() != null) { + resolver.addAll(HaxeGenericResolverUtil + .getResolverSkipAbstractNullScope(leftResult.getHaxeClass().getModel(), leftResult.getGenericResolver())); + } else { + resolver.addAll(leftResult.getGenericResolver()); + } PsiElement resolvedExpression = ((HaxeReference)expression).resolve(); if (resolvedExpression instanceof HaxeMethod) { @@ -614,29 +620,35 @@ private HaxeClassResolveResult resolveHaxeClassInternal() { if(isType(resolve, HaxeParameter.class)) { // check if type parameters has multiple constraints and try to unify HaxeTypeTag tag = ((HaxeParameter)resolve).getTypeTag(); - String typeName = tag != null ? tag.getTypeOrAnonymous().getText() : null; + String typeName = tag != null && tag.getTypeOrAnonymous() != null ? tag.getTypeOrAnonymous().getText() : null; PsiElement parameterList = resolve.getParent(); if(parameterList != null && parameterList.getParent() instanceof HaxeMethodDeclaration ) { HaxeMethodDeclaration method = (HaxeMethodDeclaration)parameterList.getParent(); - if(method != null) { - HaxeGenericParam genericParam = method.getGenericParam(); - List partList =genericParam != null ? genericParam.getGenericListPartList() : null; - if(partList!= null) { - Optional match = partList.stream().filter(part -> Objects.equals(typeName, part.getName())).findFirst(); - if(match.isPresent()) { - HaxeGenericListPart listPart = match.get(); - HaxeTypeList list = listPart.getTypeList(); - if(list != null) { - list.getTypeListPartList(); - List classReferences = list.getTypeListPartList().stream() - .map(part -> part.getTypeOrAnonymous() == null ? null : part.getTypeOrAnonymous().getType()) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - - HaxeTypeParameterMultiType constraint = new HaxeTypeParameterMultiType(listPart.getContext().getNode(), classReferences); - return HaxeClassResolveResult.create(constraint); + HaxeGenericParam genericParam = method.getGenericParam(); + List partList =genericParam != null ? genericParam.getGenericListPartList() : null; + if(partList!= null) { + HaxeGenericListPart listPart = null; + for (HaxeGenericListPart genericListPart : partList) { + if (Objects.equals(typeName, genericListPart.getName())) { + listPart = genericListPart; + break; + } + } + if(listPart!= null) { + HaxeTypeList list = listPart.getTypeList(); + if(list != null) { + list.getTypeListPartList(); + List classReferences = new ArrayList<>(); + for (HaxeTypeListPart part : list.getTypeListPartList()) { + HaxeType type = part.getTypeOrAnonymous() == null ? null : part.getTypeOrAnonymous().getType(); + if (type != null) { + classReferences.add(type); + } } + + HaxeTypeParameterMultiType constraint = new HaxeTypeParameterMultiType(listPart.getContext().getNode(), classReferences); + return HaxeClassResolveResult.create(constraint); } } } diff --git a/src/common/com/intellij/plugins/haxe/model/type/HaxeExpressionEvaluator.java b/src/common/com/intellij/plugins/haxe/model/type/HaxeExpressionEvaluator.java index 51bc72bd9..f6badf69a 100644 --- a/src/common/com/intellij/plugins/haxe/model/type/HaxeExpressionEvaluator.java +++ b/src/common/com/intellij/plugins/haxe/model/type/HaxeExpressionEvaluator.java @@ -304,7 +304,7 @@ public void run() { ResultHolder result = typeTag != null ? typeTagResult : initResult; - if (init != null) { + if (init != null && typeTag != null) { if (!typeTagResult.canAssign(initResult)) { context.addError( element, @@ -315,9 +315,7 @@ public void run() { } } - if (name != null) { - context.setLocal(name.getText(), result); - } + context.setLocal(name.getText(), result); return result; } diff --git a/src/common/com/intellij/plugins/haxe/model/type/HaxeGenericResolverUtil.java b/src/common/com/intellij/plugins/haxe/model/type/HaxeGenericResolverUtil.java index 4c6e62dbb..a3461ab1a 100644 --- a/src/common/com/intellij/plugins/haxe/model/type/HaxeGenericResolverUtil.java +++ b/src/common/com/intellij/plugins/haxe/model/type/HaxeGenericResolverUtil.java @@ -16,6 +16,7 @@ package com.intellij.plugins.haxe.model.type; import com.intellij.plugins.haxe.lang.psi.*; +import com.intellij.plugins.haxe.model.HaxeAbstractClassModel; import com.intellij.plugins.haxe.model.HaxeClassModel; import com.intellij.plugins.haxe.model.HaxeMethodModel; import com.intellij.plugins.haxe.model.HaxeParameterModel; @@ -98,6 +99,9 @@ public static HaxeGenericResolver generateResolverForSupers(HaxeClass clazz) { if (element instanceof HaxeReference) { HaxeClassResolveResult result = ((HaxeReference)element).resolveHaxeClass(); resolver.addAll(result.getGenericResolver()); + if (result.getHaxeClass() != null) { + resolver.addAll(getResolverSkipAbstractNullScope(result.getHaxeClass().getModel(), result.getGenericResolver())); + } } return resolver; } @@ -177,4 +181,21 @@ public static HaxeGenericResolver generateResolverForSupers(HaxeClass clazz) { return resolver; } + // Hack? + // Since null references in some places are handled as if they where type T + // we also have to support resolving Type Parameters as if Null was just T + public static HaxeGenericResolver getResolverSkipAbstractNullScope(@Nullable HaxeClassModel model, @NotNull HaxeGenericResolver resolver) { + if (model instanceof HaxeAbstractClassModel) { + HaxeAbstractClassModel abstractClassModel = (HaxeAbstractClassModel)model; + if ("Null".equals(abstractClassModel.getName()) && abstractClassModel.isCoreType()) { + HaxeGenericParam param = abstractClassModel.getAbstractClass().getGenericParam(); + if (param != null) { + HaxeGenericListPart generic = param.getGenericListPartList().get(0); + ResultHolder resolve = resolver.resolve(generic.getName()); + return resolve == null || resolve.getClassType() == null ? resolver : resolve.getClassType().getGenericResolver(); + } + } + } + return resolver; + } } diff --git a/src/common/com/intellij/plugins/haxe/util/HaxeAbstractForwardUtil.java b/src/common/com/intellij/plugins/haxe/util/HaxeAbstractForwardUtil.java index 8c5da526f..6c30b80c9 100644 --- a/src/common/com/intellij/plugins/haxe/util/HaxeAbstractForwardUtil.java +++ b/src/common/com/intellij/plugins/haxe/util/HaxeAbstractForwardUtil.java @@ -38,6 +38,8 @@ import java.util.List; import java.util.Set; +import static com.intellij.plugins.haxe.model.type.HaxeGenericResolverUtil.getResolverSkipAbstractNullScope; + /** * Extensions for resolving and analyzing @:forward abstract meta */ @@ -56,7 +58,9 @@ public static List findAbstractForwardingNamedSubComponents( final HaxeClass underlyingClass = abstractClassModel.getUnderlyingClass(resolver); if (underlyingClass != null) { if (forwardingFieldsNames.isEmpty()) { - return HaxeResolveUtil.findNamedSubComponents(resolver, underlyingClass); + HaxeGenericResolver forwardResolver = resolver != null ? resolver : new HaxeGenericResolver(); + forwardResolver = getResolverSkipAbstractNullScope(abstractClassModel, forwardResolver); + return HaxeResolveUtil.findNamedSubComponents(forwardResolver, underlyingClass); } List haxeNamedComponentList = new ArrayList<>(); for (String fieldName : forwardingFieldsNames) {