Skip to content

Commit

Permalink
reworked how openParameterlist is handled to help figure out the type…
Browse files Browse the repository at this point in the history
… for the untyped parameter (should fix issue #1165)
  • Loading branch information
m0rkeulv committed Apr 26, 2024
1 parent ed122a8 commit 37ec417
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,13 @@ public static CallExpressionValidation checkMethodCall(@NotNull HaxeCallExpressi
// attempt re-resolve after adding inherited type parameters
parameterType = resolveParameterType(parameter, argumentResolver);
}
// heck if functionType has untyped open parameterlist, if so inherit type
if (parameterType.isFunctionType() && argumentType.isFunctionType()
&& argument instanceof HaxeFunctionLiteral literal && literal.getOpenParameterList() != null) {
SpecificFunctionReference paramFn = parameterType.getFunctionType();
SpecificFunctionReference argFn = argumentType.getFunctionType();
argumentType = new SpecificFunctionReference(paramFn.getArguments(), argFn.getReturnType(), null, literal, literal).createHolder();
}

//TODO properly resolve typedefs
SpecificHaxeClassReference argumentClass = argumentType.getClassType();
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/com/intellij/plugins/haxe/lang/parser/haxe.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,10 @@ restParameter ::= ('...'componentName typeTag?)


// An open parameter can't have all of the type and init info. Plus, it makes the parser *very* *very* slow in some circumstances.
openParameterList ::= componentName {extends=parameterList}
untypedParameter ::= componentName {extends=parameter}
openParameterList ::= untypedParameter
{mixin="com.intellij.plugins.haxe.lang.psi.impl.HaxeParameterListPsiMixinImpl" implements="com.intellij.plugins.haxe.lang.psi.HaxeParameterListPsiMixin"}

private parenthesizedParameterList ::= '(' parameterList ')'
parameterList ::= (parameter ((',' parameter)* (',' restParameter)?)? | restParameter)? {recoverWhile="parameterListRecovery" mixin="com.intellij.plugins.haxe.lang.psi.impl.HaxeParameterListPsiMixinImpl" implements="com.intellij.plugins.haxe.lang.psi.HaxeParameterListPsiMixin"}
private parameterListRecovery ::= !('(' | ')') // Open parens are allowable in arrow function arguments.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1490,8 +1490,8 @@ public boolean execute(@NotNull PsiElement element, ResolveState state) {
else if (element instanceof HaxeNamedComponent) {
componentName = ((HaxeNamedComponent)element).getComponentName();
}
else if (element instanceof HaxeOpenParameterList) {
componentName = ((HaxeOpenParameterList)element).getComponentName();
else if (element instanceof HaxeOpenParameterList parameterList) {
componentName = parameterList.getUntypedParameter().getComponentName();
}
else if (element instanceof HaxeSwitchCaseExpr expr) {
if (!executeForSwitchCase(expr)) return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -978,20 +978,36 @@ public static ResultHolder tryToFindTypeFromCallExpression(@NotNull HaxeFunction
ResultHolder type = model.getType();
if (type.isFunctionType()) {
SpecificFunctionReference functionType = type.getFunctionType();
HaxeParameterList parameterList = literal.getParameterList();
if (parameterList == null || functionType == null) return null;
int parameterMappedToArgument = parameterList.getParameterList().indexOf(parameter);
List<SpecificFunctionReference.Argument> arguments = functionType.getArguments();
SpecificFunctionReference.Argument argument = arguments.get(parameterMappedToArgument);

ResultHolder resolved = validation.getResolver().withoutUnknowns().resolve(argument.getType());
if (resolved != null && !resolved.isUnknown()) return resolved.getType().createHolder();
if (functionType == null) return null;
int index = findParameterIndex(literal, parameter);
if (index > -1 ) {
List<SpecificFunctionReference.Argument> arguments = functionType.getArguments();
SpecificFunctionReference.Argument argument = arguments.get(index);

ResultHolder resolved = validation.getResolver().withoutUnknowns().resolve(argument.getType());
if (resolved != null && !resolved.isUnknown()) return resolved.getType().createHolder();
}
}
}
return null;
});
}

private static int findParameterIndex(@NotNull HaxeFunctionLiteral literal, @NotNull PsiElement parameter) {
HaxeParameterList parameterList = literal.getParameterList();
if (parameterList != null) {
return parameterList.getParameterList().indexOf(parameter);
}

HaxeOpenParameterList openParameterList = literal.getOpenParameterList();
if (openParameterList != null) {
if(openParameterList.getUntypedParameter() == parameter) {
return 0;
}
}
return -1;
}

private static final RecursionGuard<PsiElement> genericResolverRecursionGuard = RecursionManager.createGuard("genericResolverRecursionGuard");


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,8 @@ else if (subelement instanceof HaxeSwitchCaseExpr caseExpr) {

if (subelement instanceof HaxeImportAlias) return typeHolder;
// overriding context to avoid problems with canAssign thinking this is a "Pure" class reference
return typeHolder.withElementContext(element);
if (!typeHolder.isFunctionType()) return typeHolder.withElementContext(element);
return typeHolder;
}

return SpecificTypeReference.getDynamic(element).createHolder();
Expand Down Expand Up @@ -734,25 +735,26 @@ static ResultHolder handleFunctionLiteral(
HaxeExpressionEvaluatorContext context,
HaxeGenericResolver resolver,
HaxeFunctionLiteral function) {
HaxeParameterList params = function.getParameterList(); // TODO mlo: get expected type to use if signature/parameters are without types
if (params == null) {
return SpecificHaxeClassReference.getInvalid(function).createHolder();
}
//HaxeParameterList params = function.getParameterList(); // TODO mlo: get expected type to use if signature/parameters are without types
//if (params == null) {
// return SpecificHaxeClassReference.getInvalid(function).createHolder();
//}
LinkedList<SpecificFunctionReference.Argument> arguments = new LinkedList<>();
ResultHolder returnType = null;
context.beginScope();
try {
if (params instanceof HaxeOpenParameterList openParamList) {
HaxeOpenParameterList openParamList = function.getOpenParameterList();
HaxeParameterList parameterList = function.getParameterList();
if (openParamList != null) {
// Arrow function with a single, unparenthesized, parameter.

// TODO: Infer the type from first usage in the function body.
ResultHolder argumentType = SpecificTypeReference.getUnknown(function).createHolder();
String argumentName = openParamList.getComponentName().getName();
String argumentName = openParamList.getUntypedParameter().getComponentName().getName();
context.setLocal(argumentName, argumentType);
// TODO check if rest param?
arguments.add(new SpecificFunctionReference.Argument(0, false, false, argumentType, argumentName));
} else {
List<HaxeParameter> list = params.getParameterList();
} else if (parameterList != null) {
List<HaxeParameter> list = parameterList.getParameterList();
for (int i = 0; i < list.size(); i++) {
HaxeParameter parameter = list.get(i);
//ResultHolder argumentType = HaxeTypeResolver.getTypeFromTypeTag(parameter.getTypeTag(), function);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ class Untypedgenerics<T> {
// function literal
myArr.filter(function(arg/*<# :String #>*/) {return true;});
// lambda
myArr.filter((arg/*<# :String #>*/) -> true);
myArr.filter((arg/*<# :String #>*/) -> arg.length > 0);
myArr.filter(arg/*<# :String #>*/ -> arg.length < 0);
myArr.sort((s1/*<# :String #>*/,s2/*<# :String #>*/)-> -1);

testMethodGenericPassing("", (arg/*<# :String #>*/)-> {});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,10 @@ Haxe File
HaxePsiToken:=('=')
FUNCTION_LITERAL
OPEN_PARAMETER_LIST
COMPONENT_NAME
IDENTIFIER
HaxePsiToken:ID('a')
UNTYPED_PARAMETER
COMPONENT_NAME
IDENTIFIER
HaxePsiToken:ID('a')
HaxePsiToken:->('->')
CALL_EXPRESSION
REFERENCE_EXPRESSION
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,10 @@ Haxe File
CALL_EXPRESSION_LIST
FUNCTION_LITERAL
OPEN_PARAMETER_LIST
COMPONENT_NAME
IDENTIFIER
HaxePsiToken:ID('a')
UNTYPED_PARAMETER
COMPONENT_NAME
IDENTIFIER
HaxePsiToken:ID('a')
HaxePsiToken:->('->')
CALL_EXPRESSION
REFERENCE_EXPRESSION
Expand Down

0 comments on commit 37ec417

Please sign in to comment.