diff --git a/src/main/java/com/intellij/plugins/haxe/ide/annotator/semantics/HaxeCallExpressionUtil.java b/src/main/java/com/intellij/plugins/haxe/ide/annotator/semantics/HaxeCallExpressionUtil.java index 490e3e43c..5044d8588 100644 --- a/src/main/java/com/intellij/plugins/haxe/ide/annotator/semantics/HaxeCallExpressionUtil.java +++ b/src/main/java/com/intellij/plugins/haxe/ide/annotator/semantics/HaxeCallExpressionUtil.java @@ -213,12 +213,32 @@ public static CallExpressionValidation checkMethodCall(@NotNull HaxeCallExpressi inheritTypeParametersFromArgument(unresolvedParameterType, argumentType, argumentResolver, resolver, typeParamTable); } - // heck if functionType has untyped open parameterlist, if so inherit type - if (parameterType.isFunctionType() && argumentType.isFunctionType() - && argument instanceof HaxeFunctionLiteral literal && literal.getOpenParameterList() != null) { + // hack if functionType has untyped open parameterlist, if so inherit type, (lambdas can also be missing type) + if (parameterType.isFunctionType() && argumentType.isFunctionType() && argument instanceof HaxeFunctionLiteral literal) { SpecificFunctionReference paramFn = parameterType.getFunctionType(); SpecificFunctionReference argFn = argumentType.getFunctionType(); - argumentType = new SpecificFunctionReference(paramFn.getArguments(), argFn.getReturnType(), null, literal, literal).createHolder(); + if(literal.getOpenParameterList() != null) { + argumentType = new SpecificFunctionReference(paramFn.getArguments(), argFn.getReturnType(), null, literal, literal).createHolder(); + }else if (literal.getParameterList() != null) { + List list = literal.getParameterList().getParameterList(); + List argumentsArgs = argFn.getArguments(); + List paramsArgs = paramFn.getArguments(); + int min = Math.min(Math.min(list.size(), argumentsArgs.size()),paramsArgs.size()); + + for (int i = 0; i < min; i++) { + HaxeParameter haxeParameter = list.get(i); + if (haxeParameter.getTypeTag() == null && haxeParameter.getVarInit() == null) { + SpecificFunctionReference.Argument argArg = argumentsArgs.get(i); + SpecificFunctionReference.Argument paramArg = paramsArgs.get(i); + ResultHolder argArgType = argArg.getType(); + ResultHolder paramArgType = paramArg.getType(); + if(argArgType.isUnknown() && !paramArgType.isUnknown()) { + argumentsArgs.set(i, argArg.withType(paramArgType)); + } + } + } + argumentType = new SpecificFunctionReference(argumentsArgs, argFn.getReturnType(), null, literal, literal).createHolder(); + } } //TODO properly resolve typedefs diff --git a/src/main/java/com/intellij/plugins/haxe/model/evaluator/HaxeExpressionEvaluator.java b/src/main/java/com/intellij/plugins/haxe/model/evaluator/HaxeExpressionEvaluator.java index a101771cc..5704dd7f1 100644 --- a/src/main/java/com/intellij/plugins/haxe/model/evaluator/HaxeExpressionEvaluator.java +++ b/src/main/java/com/intellij/plugins/haxe/model/evaluator/HaxeExpressionEvaluator.java @@ -438,7 +438,7 @@ static ResultHolder _handle(final PsiElement element, ResultHolder typeHolder) { // if new expression is missing typeParameters try to resolve from usage HaxeType type = expression.getType(); - if (type.getTypeParam() == null && typeHolder.getClassType() != null && typeHolder.getClassType().getSpecifics().length > 0) { + if (type != null && type.getTypeParam() == null && typeHolder.getClassType() != null && typeHolder.getClassType().getSpecifics().length > 0) { HaxePsiField fieldDeclaration = PsiTreeUtil.getParentOfType(expression, HaxePsiField.class); if (fieldDeclaration != null && fieldDeclaration.getTypeTag() == null) { SpecificHaxeClassReference classType = typeHolder.getClassType(); diff --git a/src/main/java/com/intellij/plugins/haxe/model/evaluator/HaxeExpressionEvaluatorHandlers.java b/src/main/java/com/intellij/plugins/haxe/model/evaluator/HaxeExpressionEvaluatorHandlers.java index fda97ded6..ffaa98de4 100644 --- a/src/main/java/com/intellij/plugins/haxe/model/evaluator/HaxeExpressionEvaluatorHandlers.java +++ b/src/main/java/com/intellij/plugins/haxe/model/evaluator/HaxeExpressionEvaluatorHandlers.java @@ -369,7 +369,7 @@ else if (subelement instanceof HaxeSwitchCaseExpr caseExpr) { else { // attempt to resolve sub-element using default handle logic if (!(subelement instanceof PsiPackage)) { - typeHolder = handleWithRecursionGuard(subelement, context, resolver);//TODO null should probably block result cache + typeHolder = handleWithRecursionGuard(subelement, context, resolver); } } } diff --git a/src/main/java/com/intellij/plugins/haxe/model/evaluator/HaxeExpressionUsageUtil.java b/src/main/java/com/intellij/plugins/haxe/model/evaluator/HaxeExpressionUsageUtil.java index 1ebc5b901..80ed47c7d 100644 --- a/src/main/java/com/intellij/plugins/haxe/model/evaluator/HaxeExpressionUsageUtil.java +++ b/src/main/java/com/intellij/plugins/haxe/model/evaluator/HaxeExpressionUsageUtil.java @@ -110,22 +110,22 @@ public static ResultHolder searchReferencesForTypeParameters(final HaxeComponent PsiElement parent = expression.getParent(); if (reference instanceof HaxeReferenceExpression referenceExpression) { - ResultHolder unified = tryFindTypeWhenUsedAsParameterInCallExpression(resultHolder, referenceExpression, parent); - if (unified != null) return unified; + ResultHolder result = tryFindTypeWhenUsedAsParameterInCallExpression(resultHolder, referenceExpression, parent); + if (result != null) return mapTypeParameter(resultHolder, result); } if (parent instanceof HaxeAssignExpression assignExpression) { - ResultHolder result = tryTypeFromAssignExpression(context, resolver, resultHolder, assignExpression); - if (result != null) return result; + ResultHolder result = tryTypeFromAssignExpression(context, resolver, resultHolder, assignExpression, componentName); + if (result != null) return mapTypeParameter(resultHolder, result); } if (parent instanceof HaxeReferenceExpression referenceExpression) { - ResultHolder resolve = tryFindTypeFromMethodCallOnReference(resultHolder, referenceExpression, isFirst); - if (resolve != null) return resolve; + ResultHolder result = tryFindTypeFromMethodCallOnReference(resultHolder, referenceExpression, isFirst); + if (result != null) return mapTypeParameter(resultHolder, result); } if (parent instanceof HaxeObjectLiteralElement literalElement) { ResultHolder result = tryTypeFromObjectLiteral(context, resolver, literalElement); - if (result != null) return result; + if (result != null) return mapTypeParameter(resultHolder, result); } if (parent instanceof HaxeArrayAccessExpression arrayAccessExpression) { @@ -141,6 +141,13 @@ public static ResultHolder searchReferencesForTypeParameters(final HaxeComponent return resultHolder; } + private static @NotNull ResultHolder mapTypeParameter(ResultHolder current, ResultHolder found) { + if(current.canAssign(found)) { + return found; + } + return current; + } + private static void tryUpdateTypePAramFromOjbectLiteral(HaxeExpressionEvaluatorContext context, HaxeGenericResolver resolver, HaxeObjectLiteralElement literalElement, @@ -316,11 +323,37 @@ private static void tryUpdateTypeParamFromArrayAccess(HaxeExpressionEvaluatorCon } private static @Nullable ResultHolder tryTypeFromAssignExpression(HaxeExpressionEvaluatorContext context, - HaxeGenericResolver resolver, - ResultHolder resultHolder, - HaxeAssignExpression assignExpression) { + HaxeGenericResolver resolver, + ResultHolder resultHolder, + HaxeAssignExpression assignExpression, HaxeComponentName componentName) { + boolean isRight = false; + boolean isLeft = false; + HaxeExpression rightExpression = assignExpression.getRightExpression(); - ResultHolder result = handleWithRecursionGuard(rightExpression, context, resolver); + HaxeExpression leftExpression = assignExpression.getLeftExpression(); + + + if(rightExpression instanceof HaxeReferenceExpression referenceExpression) { + PsiElement resolve = referenceExpression.resolve(); + if(resolve instanceof HaxeNamedComponent namedComponent) { + if(namedComponent.getComponentName() == componentName) { + isRight = true; + } + } + } + if(!isRight) { + if (leftExpression instanceof HaxeReferenceExpression referenceExpression) { + PsiElement resolve = referenceExpression.resolve(); + if (resolve instanceof HaxeNamedComponent namedComponent) { + if (namedComponent.getComponentName() == componentName) { + isLeft = true; + } + } + } + } + + if(isLeft || isRight) { + ResultHolder result = handleWithRecursionGuard(isLeft ? rightExpression : leftExpression, context, resolver); if (result != null && !result.isUnknown() && result.getType().isSameType(resultHolder.getType())) { HaxeGenericResolver resultResolver = result.getClassType().getGenericResolver(); HaxeGenericResolver resultResolverWithoutUnknowns = resultResolver.withoutUnknowns(); @@ -329,6 +362,8 @@ private static void tryUpdateTypeParamFromArrayAccess(HaxeExpressionEvaluatorCon return result; } } + } + return null; } diff --git a/src/main/java/com/intellij/plugins/haxe/model/type/HaxeGenericResolver.java b/src/main/java/com/intellij/plugins/haxe/model/type/HaxeGenericResolver.java index 2f54da85d..846213603 100644 --- a/src/main/java/com/intellij/plugins/haxe/model/type/HaxeGenericResolver.java +++ b/src/main/java/com/intellij/plugins/haxe/model/type/HaxeGenericResolver.java @@ -591,14 +591,6 @@ else if (entry.type().equals(specific)) { return null; } - public void addAssignHint(HaxeGenericResolver resolver) { - Optional assign = resolver.findAssignToType(); - if(assign.isPresent()) { - // remove old if present - resolvers.removeIf(entry -> entry.resolveSource() == ResolveSource.ASSIGN_TYPE); - resolvers.add(assign.get().copy()); - } - } public SpecificFunctionReference substituteTypeParamsWithAssignHintTypes(SpecificFunctionReference type) { Optional assignHint = findAssignToType(); diff --git a/src/test/resources/testData/annotation.semantic/Monomorphism.hx b/src/test/resources/testData/annotation.semantic/Monomorphism.hx index d48bdbaf9..e8d547324 100644 --- a/src/test/resources/testData/annotation.semantic/Monomorphism.hx +++ b/src/test/resources/testData/annotation.semantic/Monomorphism.hx @@ -36,6 +36,8 @@ class MonomorphTest { mapDelayed.set(1, "test"); } + var myMap = new Map(); + public function advancemonomorphism(morphA, morphB):Void { var arr = [""]; arr.push(morphA); @@ -48,6 +50,12 @@ class MonomorphTest { morphB = ""; // Wrong already morphed Int var test2:String = morphB; // Wrong already morphed Int + + var someMap = new Map(); + myMap = someMap; + + someMap.set(1,1); // Wrong already morphed to Map + } }