From 159f18a6feea7225bb58cb626b8fe8c6b22840e9 Mon Sep 17 00:00:00 2001 From: "Konstantin.Nisht" Date: Wed, 9 Oct 2019 12:25:08 +0300 Subject: [PATCH] fix incorrect searching of GrCall corresponding to closure invocation GitOrigin-RevId: fd137586d9fe4b636214b0e21708dfc09b3220fa --- .../closure/ImplicitClosureCallPredicateUtil.kt | 10 +++++++++- .../inference/driver/closure/ClosureInferenceUtil.kt | 11 +++++------ .../driver/closure/ClosureParametersStorageBuilder.kt | 2 +- .../InferMethodParametersTypesIntentionTest.groovy | 2 +- ...solvedCode4.groovy => PassClosureInClosure.groovy} | 0 .../PassClosureInClosure_after.groovy | 8 ++++++++ .../UnresolvedCode4_after.groovy | 9 --------- 7 files changed, 24 insertions(+), 18 deletions(-) rename plugins/groovy/testdata/refactoring/inferMethodParametersTypes/{UnresolvedCode4.groovy => PassClosureInClosure.groovy} (100%) create mode 100644 plugins/groovy/testdata/refactoring/inferMethodParametersTypes/PassClosureInClosure_after.groovy delete mode 100644 plugins/groovy/testdata/refactoring/inferMethodParametersTypes/UnresolvedCode4_after.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/closure/ImplicitClosureCallPredicateUtil.kt b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/closure/ImplicitClosureCallPredicateUtil.kt index bddeeac48569..f67008315f45 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/closure/ImplicitClosureCallPredicateUtil.kt +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/closure/ImplicitClosureCallPredicateUtil.kt @@ -5,6 +5,8 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod import com.intellij.psi.PsiType import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames @@ -16,4 +18,10 @@ internal fun PsiElement?.isClosureCallMethod(): Boolean { return this is PsiMethod && name == "call" && containingClass?.qualifiedName == GroovyCommonClassNames.GROOVY_LANG_CLOSURE } -internal fun GrCall?.isClosureCall(): Boolean = this?.resolveMethod()?.isClosureCallMethod() ?: false \ No newline at end of file +internal fun GrCall?.isClosureCall(qualifier: PsiElement): Boolean = this?.resolveMethod()?.isClosureCallMethod() ?: false + && this is GrMethodCall + && ((this.invokedExpression as? GrReferenceExpression) + ?.qualifierExpression + ?.reference + ?.resolve() == qualifier + || this.invokedExpression.reference?.resolve() == qualifier) \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/inference/driver/closure/ClosureInferenceUtil.kt b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/inference/driver/closure/ClosureInferenceUtil.kt index f3647404715f..14c2fd8ca78f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/inference/driver/closure/ClosureInferenceUtil.kt +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/inference/driver/closure/ClosureInferenceUtil.kt @@ -8,7 +8,6 @@ import com.intellij.psi.* import com.intellij.psi.impl.source.resolve.graphInference.constraints.ConstraintFormula import com.intellij.psi.util.parentOfType import org.jetbrains.plugins.groovy.intentions.closure.isClosureCall -import org.jetbrains.plugins.groovy.intentions.closure.isClosureCallMethod import org.jetbrains.plugins.groovy.intentions.style.inference.CollectingGroovyInferenceSession import org.jetbrains.plugins.groovy.intentions.style.inference.driver.BoundConstraint.ContainMarker.LOWER import org.jetbrains.plugins.groovy.intentions.style.inference.driver.RecursiveMethodAnalyzer @@ -16,7 +15,6 @@ import org.jetbrains.plugins.groovy.intentions.style.inference.driver.TypeUsageI import org.jetbrains.plugins.groovy.intentions.style.inference.driver.closure.ClosureParametersStorageBuilder.Companion.isReferenceTo import org.jetbrains.plugins.groovy.intentions.style.inference.properResolve import org.jetbrains.plugins.groovy.intentions.style.inference.resolve -import org.jetbrains.plugins.groovy.intentions.style.inference.typeParameter import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory import org.jetbrains.plugins.groovy.lang.psi.api.GroovyMethodResult import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation @@ -47,7 +45,7 @@ fun extractConstraintsFromClosureInvocations(closureParameter: ParameterizedClos instructions: List): List { val collector = mutableListOf() for (call in instructions) { - val nearestCall = call.element?.parentOfType()?.takeIf { it.isClosureCall() } ?: continue + val nearestCall = call.element?.parentOfType()?.takeIf { it.isClosureCall(closureParameter.parameter) } ?: continue for (index in nearestCall.expressionArguments.indices) { val argumentExpression = nearestCall.expressionArguments.getOrNull(index) ?: continue val innerParameterType = closureParameter.typeParameters.getOrNull(index)?.type() @@ -87,7 +85,7 @@ fun analyzeClosureUsages(closureParameter: ParameterizedClosure, val resolveResult = nearestCall.properResolve() as? GroovyMethodResult ?: return if (nearestCall.resolveMethod()?.containingClass?.qualifiedName == GROOVY_LANG_CLOSURE) { delegatesToCombiner.acceptResolveResult(resolveResult) - collectClosureMethodInvocationDependencies(closureParameter, builder, resolveResult) + collectClosureMethodInvocationDependencies(closureParameter, builder, resolveResult, nearestCall) } else { val mapping = resolveResult.candidate?.argumentMapping ?: continue @@ -103,8 +101,9 @@ fun analyzeClosureUsages(closureParameter: ParameterizedClosure, fun collectClosureMethodInvocationDependencies(parameterizedClosure: ParameterizedClosure, builder: TypeUsageInformationBuilder, - resolveResult: GroovyMethodResult) { - if (resolveResult.candidate?.method.isClosureCallMethod()) { + resolveResult: GroovyMethodResult, + nearestCall: GrCall) { + if (nearestCall.isClosureCall(parameterizedClosure.parameter)) { val arguments = resolveResult.candidate?.argumentMapping?.arguments ?: return val expectedTypes = parameterizedClosure.types.zip(arguments) val method = parameterizedClosure.parameter.parentOfType() ?: return diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/inference/driver/closure/ClosureParametersStorageBuilder.kt b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/inference/driver/closure/ClosureParametersStorageBuilder.kt index fc6dc7e4ebea..74db70b44dca 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/inference/driver/closure/ClosureParametersStorageBuilder.kt +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/inference/driver/closure/ClosureParametersStorageBuilder.kt @@ -53,7 +53,7 @@ internal class ClosureParametersStorageBuilder(private val generator: NameGenera fun extractClosuresFromCallInvocation(callUsages: Iterable, parameter: GrParameter): Boolean { - val directClosureCall = callUsages.firstOrNull { it.isClosureCall() } ?: return false + val directClosureCall = callUsages.firstOrNull { it.isClosureCall(parameter) } ?: return false val argumentAmount = directClosureCall.argumentList?.allArguments?.size ?: return false acceptParameter(parameter, argumentAmount, emptyList()) return true diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/InferMethodParametersTypesIntentionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/InferMethodParametersTypesIntentionTest.groovy index b72c2a7bdf76..366630e8ada6 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/InferMethodParametersTypesIntentionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/InferMethodParametersTypesIntentionTest.groovy @@ -529,7 +529,7 @@ class AA { static void foo(Integer a) {} } doTest(true) } - void testUnresolvedCode4() { + void testPassClosureInClosure() { doTest(true) } } diff --git a/plugins/groovy/testdata/refactoring/inferMethodParametersTypes/UnresolvedCode4.groovy b/plugins/groovy/testdata/refactoring/inferMethodParametersTypes/PassClosureInClosure.groovy similarity index 100% rename from plugins/groovy/testdata/refactoring/inferMethodParametersTypes/UnresolvedCode4.groovy rename to plugins/groovy/testdata/refactoring/inferMethodParametersTypes/PassClosureInClosure.groovy diff --git a/plugins/groovy/testdata/refactoring/inferMethodParametersTypes/PassClosureInClosure_after.groovy b/plugins/groovy/testdata/refactoring/inferMethodParametersTypes/PassClosureInClosure_after.groovy new file mode 100644 index 000000000000..08b53b38ef60 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/inferMethodParametersTypes/PassClosureInClosure_after.groovy @@ -0,0 +1,8 @@ +import groovy.transform.stc.ClosureParams +import groovy.transform.stc.FirstParam + +def > Void bar(T a, @ClosureParams(FirstParam) Closure b) { + b(a) +} + +bar({}, {}) \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/inferMethodParametersTypes/UnresolvedCode4_after.groovy b/plugins/groovy/testdata/refactoring/inferMethodParametersTypes/UnresolvedCode4_after.groovy deleted file mode 100644 index 2e0d410b4e43..000000000000 --- a/plugins/groovy/testdata/refactoring/inferMethodParametersTypes/UnresolvedCode4_after.groovy +++ /dev/null @@ -1,9 +0,0 @@ -import groovy.transform.stc.ClosureParams -import groovy.transform.stc.FirstParam -import groovy.transform.stc.FromString - -def > Void bar(@ClosureParams(value = FromString, options = ["U"]) T a, @ClosureParams(FirstParam) Closure b) { - b(a) -} - -bar({}, {}) \ No newline at end of file