mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-221863 SOE in type inlay hint: better preventing endless recursion
GitOrigin-RevId: 49a0a0675e28d6ee6b5262645575cb964851929d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
fbd7bc8a46
commit
95cf4188c9
+3
-35
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.groovy.intentions.style.inference
|
||||
|
||||
import com.intellij.openapi.util.RecursionManager
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.psi.PsiSubstitutor
|
||||
import com.intellij.psi.PsiType
|
||||
@@ -8,8 +9,6 @@ import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import com.intellij.psi.util.parentOfType
|
||||
import org.jetbrains.plugins.groovy.intentions.style.inference.MethodParameterAugmenter.Companion.VisitState.NOT_VISITED
|
||||
import org.jetbrains.plugins.groovy.intentions.style.inference.MethodParameterAugmenter.Companion.VisitState.VISITED_MANY
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod
|
||||
@@ -21,9 +20,6 @@ class MethodParameterAugmenter : TypeAugmenter() {
|
||||
|
||||
const val GROOVY_COLLECT_METHOD_CALLS_FOR_INFERENCE = "groovy.collect.method.calls.for.inference"
|
||||
|
||||
private val methodRegistry: ThreadLocal<MutableMap<GrMethod, VisitState>> =
|
||||
ThreadLocal.withInitial { mutableMapOf<GrMethod, VisitState>() }
|
||||
|
||||
internal fun createInferenceResult(method: GrMethod): InferenceResult? {
|
||||
if (!Registry.`is`(GROOVY_COLLECT_METHOD_CALLS_FOR_INFERENCE, false)) {
|
||||
return null
|
||||
@@ -32,18 +28,8 @@ class MethodParameterAugmenter : TypeAugmenter() {
|
||||
val scope = with(originalMethod.containingFile?.virtualFile) {
|
||||
if (this == null) return null else GlobalSearchScope.fileScope(originalMethod.project, this)
|
||||
}
|
||||
val involvedMethods = methodRegistry.get()
|
||||
if (involvedMethods.getOrDefault(method, NOT_VISITED) == VISITED_MANY) {
|
||||
return InferenceResult(method, PsiSubstitutor.EMPTY)
|
||||
}
|
||||
else {
|
||||
involvedMethods[method] = involvedMethods.getOrDefault(method, NOT_VISITED).nextState()
|
||||
try {
|
||||
return computeInferredMethod(method, scope)
|
||||
}
|
||||
finally {
|
||||
involvedMethods[method] = involvedMethods[method]!!.prevState()
|
||||
}
|
||||
return RecursionManager.doPreventingRecursion(method, true) {
|
||||
computeInferredMethod(method, scope)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,24 +39,6 @@ class MethodParameterAugmenter : TypeAugmenter() {
|
||||
val typeParameterSubstitutor = createVirtualToActualSubstitutor(typedMethod, method)
|
||||
CachedValueProvider.Result(InferenceResult(typedMethod, typeParameterSubstitutor), method)
|
||||
}
|
||||
|
||||
private enum class VisitState {
|
||||
NOT_VISITED {
|
||||
override fun nextState(): VisitState = VISITED_ONCE
|
||||
override fun prevState(): VisitState = NOT_VISITED
|
||||
},
|
||||
VISITED_ONCE {
|
||||
override fun nextState(): VisitState = VISITED_MANY
|
||||
override fun prevState(): VisitState = NOT_VISITED
|
||||
},
|
||||
VISITED_MANY {
|
||||
override fun nextState(): VisitState = VISITED_MANY
|
||||
override fun prevState(): VisitState = VISITED_ONCE
|
||||
};
|
||||
|
||||
abstract fun nextState(): VisitState
|
||||
abstract fun prevState(): VisitState
|
||||
}
|
||||
}
|
||||
|
||||
data class InferenceResult(val virtualMethod: GrMethod?, val typeParameterSubstitutor: PsiSubstitutor)
|
||||
|
||||
+10
-9
@@ -291,7 +291,7 @@ internal class RecursiveMethodAnalyzer(val method: GrMethod) : GroovyRecursiveEl
|
||||
for (outerCall in calls.mapNotNull { it.element.parent }) {
|
||||
val candidate = (outerCall.properResolve() as? GroovyMethodResult)?.candidate ?: continue
|
||||
val argumentMapping = candidate.argumentMapping ?: continue
|
||||
argumentMapping.expectedTypes.forEach { (_, argument) ->
|
||||
argumentMapping.arguments.forEach { argument ->
|
||||
val param = mapping[argumentMapping.targetParameter(argument)?.name] ?: return@forEach
|
||||
processOuterArgument(argument, param)
|
||||
}
|
||||
@@ -303,7 +303,7 @@ internal class RecursiveMethodAnalyzer(val method: GrMethod) : GroovyRecursiveEl
|
||||
val initializerType = parameter.initializerGroovy?.type ?: continue
|
||||
induceDeepConstraints(parameter.type,
|
||||
initializerType, dependentTypes, requiredTypesCollector,
|
||||
method.typeParameters.toSet(), INHABIT)
|
||||
method.typeParameters.toSet(), INHABIT, parameter)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ internal class RecursiveMethodAnalyzer(val method: GrMethod) : GroovyRecursiveEl
|
||||
val argtype = argument.type ?: return
|
||||
val correctArgumentType = argtype.typeParameter()?.upperBound() ?: argtype
|
||||
induceDeepConstraints(parameter.type, correctArgumentType, dependentTypes, requiredTypesCollector, method.typeParameters.toSet(),
|
||||
INHABIT)
|
||||
INHABIT, parameter)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -334,7 +334,7 @@ internal class RecursiveMethodAnalyzer(val method: GrMethod) : GroovyRecursiveEl
|
||||
dependentTypes: MutableSet<PsiTypeParameter>,
|
||||
requiredTypesCollector: MutableMap<PsiTypeParameter, MutableList<BoundConstraint>>,
|
||||
variableParameters: Set<PsiTypeParameter>,
|
||||
targetMarker: ContainMarker) {
|
||||
targetMarker: ContainMarker, context: PsiElement) {
|
||||
val leftTypeParameter = leftType.typeParameter()
|
||||
val rightTypeParameter = rightType.typeParameter()
|
||||
if (leftTypeParameter != null && rightTypeParameter != null && rightTypeParameter in variableParameters) {
|
||||
@@ -345,21 +345,22 @@ internal class RecursiveMethodAnalyzer(val method: GrMethod) : GroovyRecursiveEl
|
||||
rightTypeParameter.extendsListTypes.firstOrNull()
|
||||
}
|
||||
else if (leftTypeParameter != null) {
|
||||
val typeSet = expandWildcards(rightType, leftTypeParameter)
|
||||
val typeSet = expandWildcards(rightType, context)
|
||||
typeSet.forEach { requiredTypesCollector.safePut(leftTypeParameter, BoundConstraint(it, targetMarker)) }
|
||||
}
|
||||
if (leftType is PsiArrayType && rightType is PsiArrayType) {
|
||||
induceDeepConstraints(leftType.componentType, rightType.componentType, dependentTypes, requiredTypesCollector, variableParameters,
|
||||
targetMarker)
|
||||
targetMarker, context)
|
||||
}
|
||||
val leftBound = leftTypeParameter?.upperBound() ?: leftType
|
||||
val rightBound = rightTypeParameter?.upperBound() ?: rightType
|
||||
val leftTypeArguments = (leftBound as? PsiClassType)?.parameters ?: return
|
||||
val rightTypeArguments = (rightBound as? PsiClassType)?.parameters ?: return
|
||||
for ((leftTypeArgument, rightTypeArgument) in leftTypeArguments.zip(rightTypeArguments)) {
|
||||
val rangedRightTypeArguments = rightTypeArguments.map { it ?: PsiWildcardType.createUnbounded(context.manager) }.toTypedArray()
|
||||
for ((leftTypeArgument, rightTypeArgument) in leftTypeArguments.zip(rangedRightTypeArguments)) {
|
||||
leftTypeArgument ?: continue
|
||||
rightTypeArgument ?: continue
|
||||
induceDeepConstraints(leftTypeArgument, rightTypeArgument, dependentTypes, requiredTypesCollector, variableParameters, targetMarker)
|
||||
induceDeepConstraints(leftTypeArgument, rightTypeArgument, dependentTypes, requiredTypesCollector, variableParameters, targetMarker,
|
||||
context)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -120,7 +120,7 @@ fun collectClosureMethodInvocationDependencies(parameterizedClosure: Parameteriz
|
||||
val argumentType = argument.type ?: continue
|
||||
constraintCollector.add(TypeConstraint(expectedType, argumentType, method))
|
||||
RecursiveMethodAnalyzer.induceDeepConstraints(expectedType, argumentType, dependentTypes, requiredTypesCollector,
|
||||
method.typeParameters.toSet(), LOWER)
|
||||
method.typeParameters.toSet(), LOWER, method)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -64,7 +64,7 @@ foo(['q'], ['q'])
|
||||
|
||||
fun testClosure() {
|
||||
val text = """
|
||||
def<# [< [T extends A] >] #> foo(<# [T ] #>a, <# [[Closure < Object >] ] #>c) {
|
||||
def<# [< [T extends A] >] #> foo(<# [T ] #>a, <# [[Closure < [? ] >] ] #>c) {
|
||||
c(a)
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ foo(null as A) {
|
||||
|
||||
fun testInsideClosure() {
|
||||
val text = """
|
||||
def foo(<# [Integer ] #>arg, <# [[Closure < Byte >] ] #>closure) {
|
||||
def foo(<# [Integer ] #>arg, <# [[Closure < [? ] >] ] #>closure) {
|
||||
closure(arg)
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
import groovy.transform.stc.ClosureParams
|
||||
import groovy.transform.stc.FirstParam
|
||||
|
||||
def <T> Object foo(@DelegatesTo.Target('a') T a, @DelegatesTo(target = 'a', strategy = 1) @ClosureParams(FirstParam) Closure<?> cl) {
|
||||
def <T, U> U foo(@DelegatesTo.Target('a') T a, @DelegatesTo(target = 'a', strategy = 1) @ClosureParams(FirstParam) Closure<U> cl) {
|
||||
a.with cl
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user