fix incorrect searching of GrCall corresponding to closure invocation

GitOrigin-RevId: fd137586d9fe4b636214b0e21708dfc09b3220fa
This commit is contained in:
Konstantin.Nisht
2019-10-09 14:08:11 +00:00
committed by intellij-monorepo-bot
parent 93c84a43d9
commit 159f18a6fe
7 changed files with 24 additions and 18 deletions
@@ -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
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)
@@ -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<ReadWriteVariableInstruction>): List<ConstraintFormula> {
val collector = mutableListOf<ConstraintFormula>()
for (call in instructions) {
val nearestCall = call.element?.parentOfType<GrCall>()?.takeIf { it.isClosureCall() } ?: continue
val nearestCall = call.element?.parentOfType<GrCall>()?.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<GrMethod>() ?: return
@@ -53,7 +53,7 @@ internal class ClosureParametersStorageBuilder(private val generator: NameGenera
fun extractClosuresFromCallInvocation(callUsages: Iterable<GrCall>,
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
@@ -529,7 +529,7 @@ class AA { static void fo<caret>o(Integer a) {} }
doTest(true)
}
void testUnresolvedCode4() {
void testPassClosureInClosure() {
doTest(true)
}
}
@@ -0,0 +1,8 @@
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.FirstParam
def <T extends Closure<Void>> Void bar(T a, @ClosureParams(FirstParam) Closure<Void> b) {
b(a)
}
bar({}, {})
@@ -1,9 +0,0 @@
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.FirstParam
import groovy.transform.stc.FromString
def <T extends U, U extends Closure<Void>> Void bar(@ClosureParams(value = FromString, options = ["U"]) T a, @ClosureParams(FirstParam) Closure<Void> b) {
b(a)
}
bar({}, {})