IDEA-221863 SOE in type inlay hint: fix endless recreation of DFA for single method

GitOrigin-RevId: 3eca8237078e4524bed5593ccd5704ce006f95ba
This commit is contained in:
Konstantin.Nisht
2019-10-09 14:08:11 +00:00
committed by intellij-monorepo-bot
parent 7f3c23f58e
commit fbd7bc8a46
@@ -8,6 +8,8 @@ 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
@@ -19,6 +21,9 @@ 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
@@ -27,13 +32,45 @@ class MethodParameterAugmenter : TypeAugmenter() {
val scope = with(originalMethod.containingFile?.virtualFile) {
if (this == null) return null else GlobalSearchScope.fileScope(originalMethod.project, this)
}
return CachedValuesManager.getCachedValue(method) {
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()
}
}
}
private fun computeInferredMethod(method: GrMethod, scope: GlobalSearchScope): InferenceResult =
CachedValuesManager.getCachedValue(method) {
val typedMethod = runInferenceProcess(method, scope)
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)