From bb3faae6417e394bb02b482fc14254999b3cbca0 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Fri, 7 Jul 2017 12:49:39 +0300 Subject: [PATCH] [groovy] treat no-arg calls of method with a single parameter as valid --- .../builder/JsonDelegateContributor.java | 7 +++- .../signatures/GrClosureSignatureUtil.java | 38 ++++------------- .../synthetic/ClosureSyntheticParameter.java | 1 - .../ConstructorMapApplicabilityProvider.kt | 3 -- .../highlighting/GrAssignabilityTest.groovy | 4 +- .../highlighting/ClosureApplicability.groovy | 31 ++++++++++++++ ...CallMethodWithInapplicableArguments.groovy | 7 ---- .../testdata/highlighting/Constructor.groovy | 42 +++++++------------ .../SingleParameterMethodApplicability.groovy | 24 +++++++++++ 9 files changed, 88 insertions(+), 69 deletions(-) create mode 100644 plugins/groovy/testdata/highlighting/ClosureApplicability.groovy delete mode 100644 plugins/groovy/testdata/highlighting/ClosureCallMethodWithInapplicableArguments.groovy create mode 100644 plugins/groovy/testdata/highlighting/SingleParameterMethodApplicability.groovy diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/JsonDelegateContributor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/JsonDelegateContributor.java index b534275203d4..db50b1323d78 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/JsonDelegateContributor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/builder/JsonDelegateContributor.java @@ -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")); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java index 1455aac208d5..5acccdf82008 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java @@ -350,20 +350,6 @@ public class GrClosureSignatureUtil { return mapParametersToArguments(signature, args, FunctionUtil.id(), context, partial); } - private static class ArgWrapper { - PsiType type; - @Nullable Arg arg; - - private ArgWrapper(PsiType type, @Nullable Arg arg) { - this.type = type; - this.arg = arg; - } - } - - private static Function, PsiType> ARG_WRAPPER_COMPUTER() { - return argWrapper -> argWrapper.type; - } - @Nullable private static ArgInfo[] 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[] map = mapSimple(params, args, typeComputer, context, false); + final ArgInfo[] 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 typeComputer, @NotNull PsiElement context, + int optional, boolean partial) { if (args.length > params.length && !partial) return null; ArgInfo[] 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[] map = new ArgInfo[params.length]; diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/ClosureSyntheticParameter.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/ClosureSyntheticParameter.java index 13db03071c83..23566c9681db 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/ClosureSyntheticParameter.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/ClosureSyntheticParameter.java @@ -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 diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ConstructorMapApplicabilityProvider.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ConstructorMapApplicabilityProvider.kt index 9f418ff99e9b..8ed08b460244 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ConstructorMapApplicabilityProvider.kt +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ConstructorMapApplicabilityProvider.kt @@ -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 } } \ No newline at end of file diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.groovy index 993f3e063af5..65dca4d97a3b 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.groovy @@ -58,7 +58,9 @@ class GrAssignabilityTest extends GrHighlightingTestBase { void testClosureWithDefaultParameters() { doTest() } - void testClosureCallMethodWithInapplicableArguments() { doTest() } + void testClosureApplicability() { doTest() } + + void testSingleParameterMethodApplicability() { doTest() } void testCallIsNotApplicable() { doTest() } diff --git a/plugins/groovy/testdata/highlighting/ClosureApplicability.groovy b/plugins/groovy/testdata/highlighting/ClosureApplicability.groovy new file mode 100644 index 000000000000..33a16b7c19f6 --- /dev/null +++ b/plugins/groovy/testdata/highlighting/ClosureApplicability.groovy @@ -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() +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() +cl5(42) +cl5(42, 43) + +// closure with two parameters, one is optional +def cl6 = { a, b = 2 -> } +cl6() +cl6(42) +cl6(42, 43) diff --git a/plugins/groovy/testdata/highlighting/ClosureCallMethodWithInapplicableArguments.groovy b/plugins/groovy/testdata/highlighting/ClosureCallMethodWithInapplicableArguments.groovy deleted file mode 100644 index 01c677096279..000000000000 --- a/plugins/groovy/testdata/highlighting/ClosureCallMethodWithInapplicableArguments.groovy +++ /dev/null @@ -1,7 +0,0 @@ -def foo={x, y->} - -print foo.call(1) - -def bar={3} -print bar.call() -print bar.call(3) diff --git a/plugins/groovy/testdata/highlighting/Constructor.groovy b/plugins/groovy/testdata/highlighting/Constructor.groovy index 7c8ce1abfb7c..48a3f79fbe59 100644 --- a/plugins/groovy/testdata/highlighting/Constructor.groovy +++ b/plugins/groovy/testdata/highlighting/Constructor.groovy @@ -1,37 +1,27 @@ class A { def field - - def A(x) {} - - def test() { - new A() - - 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(field1: 0) - } + B(int x = 0) {} } +new B() + +new B(field: 0) +new B(field1: 0) + class C { def field + C(Map map){} +} - def C(Map map){} - - def test() { - new C(field: 0) - new C(field1: 0) - new C() - } -} \ No newline at end of file +new C() +new C(field: 0) +new C(field1: 0) diff --git a/plugins/groovy/testdata/highlighting/SingleParameterMethodApplicability.groovy b/plugins/groovy/testdata/highlighting/SingleParameterMethodApplicability.groovy new file mode 100644 index 000000000000..1f4f21ade419 --- /dev/null +++ b/plugins/groovy/testdata/highlighting/SingleParameterMethodApplicability.groovy @@ -0,0 +1,24 @@ +def foo(a) {} + +foo() +foo(42) + +// single primitive parameter +def fooInt(int a) {} + +fooInt() +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) +