[groovy] treat no-arg calls of method with a single parameter as valid

This commit is contained in:
Daniil Ovchinnikov
2017-07-07 12:55:22 +03:00
parent 6951947fbb
commit bb3faae641
9 changed files with 88 additions and 69 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,6 +46,11 @@ public class JsonDelegateContributor extends BuilderMethodsContributor {
GrLightMethodBuilder method;
PsiClassType genericType;
// List ()
method = createMethod(name, clazz, place);
method.setReturnType(TypesUtil.createListType(place, null));
if (!processor.process(method)) return false;
// T (T)
method = createMethod(name, clazz, place);
genericType = facade.getElementFactory().createType(method.addTypeParameter("T"));
@@ -350,20 +350,6 @@ public class GrClosureSignatureUtil {
return mapParametersToArguments(signature, args, FunctionUtil.id(), context, partial);
}
private static class ArgWrapper<Arg> {
PsiType type;
@Nullable Arg arg;
private ArgWrapper(PsiType type, @Nullable Arg arg) {
this.type = type;
this.arg = arg;
}
}
private static <Arg> Function<ArgWrapper<Arg>, PsiType> ARG_WRAPPER_COMPUTER() {
return argWrapper -> argWrapper.type;
}
@Nullable
private static <Arg> ArgInfo<Arg>[] mapParametersToArguments(@NotNull GrClosureSignature signature,
@NotNull Arg[] args,
@@ -375,12 +361,12 @@ public class GrClosureSignatureUtil {
if (checkForOnlyMapParam(signature, args.length)) return ArgInfo.empty_array();
GrClosureParameter[] params = signature.getParameters();
if (args.length > params.length && !signature.isVarargs() && !partial) return null;
int optional = getOptionalParamCount(signature, false);
int optional = getOptionalParamCount(signature);
int notOptional = params.length - optional;
if (signature.isVarargs()) notOptional--;
if (notOptional > args.length && !partial) return null;
final ArgInfo<Arg>[] map = mapSimple(params, args, typeComputer, context, false);
final ArgInfo<Arg>[] map = mapSimple(params, args, typeComputer, context, optional, false);
if (map != null) return map;
if (signature.isVarargs()) {
@@ -389,7 +375,7 @@ public class GrClosureSignatureUtil {
if (!partial) return null;
return mapSimple(params, args, typeComputer, context, true);
return mapSimple(params, args, typeComputer, context, optional, true);
}
private static boolean checkForOnlyMapParam(@NotNull GrClosureSignature signature, final int argCount) {
@@ -405,11 +391,11 @@ public class GrClosureSignatureUtil {
@NotNull Arg[] args,
@NotNull Function<Arg, PsiType> typeComputer,
@NotNull PsiElement context,
int optional,
boolean partial) {
if (args.length > params.length && !partial) return null;
ArgInfo<Arg>[] map = new ArgInfo[params.length];
int optional = getOptionalParamCount(params, false);
int notOptional = params.length - optional;
int optionalArgs = args.length - notOptional;
@@ -569,16 +555,11 @@ public class GrClosureSignatureUtil {
}
}
public static int getOptionalParamCount(GrClosureSignature signature, boolean hasNamedArgs) {
return getOptionalParamCount(signature.getParameters(), hasNamedArgs);
}
public static int getOptionalParamCount(GrClosureParameter[] parameters, boolean hasNamedArgs) {
private static int getOptionalParamCount(@NotNull GrClosureSignature signature) {
GrClosureParameter[] parameters = signature.getParameters();
if (parameters.length == 1 && !(parameters[0].getType() instanceof PsiPrimitiveType) && !signature.isCurried()) return 1;
int count = 0;
int i = 0;
if (hasNamedArgs) i++;
for (; i < parameters.length; i++) {
GrClosureParameter parameter = parameters[i];
for (GrClosureParameter parameter : parameters) {
if (parameter.isOptional()) count++;
}
return count;
@@ -941,9 +922,6 @@ public class GrClosureSignatureUtil {
if (args.length > params.length && !signature.isVarargs()) return null;
int optional = getOptionalParamCount(params, false);
assert optional == 0;
int errorCount = 0;
ArgInfo<Arg>[] map = new ArgInfo[params.length];
@@ -49,7 +49,6 @@ public class ClosureSyntheticParameter extends GrLightParameter implements Navig
public ClosureSyntheticParameter(GrClosableBlock closure) {
super(GrClosableBlock.IT_PARAMETER_NAME, TypesUtil.getJavaLangObject(closure), closure);
myClosure = closure;
setOptional(true);
}
@Override
@@ -42,9 +42,6 @@ open class ConstructorMapApplicabilityProvider : GroovyApplicabilityProvider() {
if (parameters.isEmpty() && argumentTypes.size == 1) {
return if (isInheritor(argumentTypes[0], CommonClassNames.JAVA_UTIL_MAP)) applicable else inapplicable
}
if (parameters.size == 1 && argumentTypes.isEmpty() && isInheritor(parameters[0].type, CommonClassNames.JAVA_UTIL_MAP)) {
return inapplicable
}
return null
}
}
@@ -58,7 +58,9 @@ class GrAssignabilityTest extends GrHighlightingTestBase {
void testClosureWithDefaultParameters() { doTest() }
void testClosureCallMethodWithInapplicableArguments() { doTest() }
void testClosureApplicability() { doTest() }
void testSingleParameterMethodApplicability() { doTest() }
void testCallIsNotApplicable() { doTest() }
@@ -0,0 +1,31 @@
// closure without parameters
def cl1 = {}
cl1()
cl1(42)
// closure with single parameter
def cl2 = { a -> }
cl2()
cl2(42)
// closure with single primitive parameter
def cl3 = { int a -> }
cl3<warning descr="'cl3' cannot be applied to '()'">()</warning>
cl3(42)
// closure with single optional primitive parameter
def cl4 = { int a = -1 -> }
cl4()
cl4(42)
// closure with two parameters
def cl5 = { a, b -> }
cl5<warning descr="'cl5' cannot be applied to '()'">()</warning>
cl5<warning descr="'cl5' cannot be applied to '(java.lang.Integer)'">(42)</warning>
cl5(42, 43)
// closure with two parameters, one is optional
def cl6 = { a, b = 2 -> }
cl6<warning descr="'cl6' cannot be applied to '()'">()</warning>
cl6(42)
cl6(42, 43)
@@ -1,7 +0,0 @@
def foo={x, y->}
print foo.call<warning descr="'call' in 'groovy.lang.Closure<java.lang.Void>' cannot be applied to '(java.lang.Integer)'">(1)</warning>
def bar={3}
print bar.call()
print bar.call(3)
+16 -26
View File
@@ -1,37 +1,27 @@
class A {
def field
def A(x) {}
def test() {
new A<warning descr="Constructor 'A' in 'A' cannot be applied to '()'">()</warning>
new A(field: 1)
new A(field2: 1)
}
A(x) {}
}
new A()
new A(field: 1)
new A(field2: 1)
class B {
def field
def A(int x = 0) {}
def test() {
new B()
new B(field: 0)
new B(<warning descr="Property 'field1' does not exist">field1</warning>: 0)
}
B(int x = 0) {}
}
new B()
new B(field: 0)
new B(<warning descr="Property 'field1' does not exist">field1</warning>: 0)
class C {
def field
C(Map map){}
}
def C(Map map){}
def test() {
new C(field: 0)
new C(field1: 0)
new C<warning descr="Constructor 'C' in 'C' cannot be applied to '()'">()</warning>
}
}
new C()
new C(field: 0)
new C(field1: 0)
@@ -0,0 +1,24 @@
def foo(a) {}
foo()
foo(42)
// single primitive parameter
def fooInt(int a) {}
fooInt<warning descr="'fooInt' in 'SingleParameterMethodApplicability' cannot be applied to '()'">()</warning>
fooInt(42)
// single optional primitive parameter
def fooIntOptional(int a = -1) {}
fooIntOptional()
fooIntOptional(42)
// two parameters, one is optional
def fooTwoParameters(a, b = null) {}
fooTwoParameters() // https://issues.apache.org/jira/browse/GROOVY-8248
fooTwoParameters(42)
fooTwoParameters(42, 43)