From 3ed75ce0a3d31e2a540648eb41bd8f4da9433d33 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Tue, 13 Oct 2020 19:21:13 +0300 Subject: [PATCH] [groovy] eagerly compute list component types .. otherwise the instantiation of ListLiteralType happens inside one InferenceContext instance, while component types might be computed in another one, leading to incorrect results/messed caching/SOE. Example: `org.jetbrains.plugins.groovy.lang.resolve.TypeInferenceTest.testRecursionWithLists`. Changing list literal type to ArrayList will cause two `DFAType`s in the beginning of a while-loop to become unequal, then they are joined via LUB (`DFAType.create(DFAType, DFAType, PsiManager)`), type of the `[list]` was instantiated inside a `PartialContext`, then computation of component types happens outside of `PartialContext`, which causes unnecessary recursion and disabled caching. GitOrigin-RevId: 83bc7e0a2fac6f48d30ac55f8c96fca5428b6811 --- .../plugins/groovy/lang/typing/ListLiteralType.kt | 10 ++++++---- .../groovy/lang/resolve/TypeInferenceTest.groovy | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/typing/ListLiteralType.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/typing/ListLiteralType.kt index 4524b17dbc88..b5435feb0c9a 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/typing/ListLiteralType.kt +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/typing/ListLiteralType.kt @@ -1,4 +1,4 @@ -// 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. +// Copyright 2000-2020 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.lang.typing import com.intellij.openapi.util.RecursionManager @@ -16,9 +16,11 @@ open class ListLiteralType(val expressions: List, private val cont override fun isValid(): Boolean = context.isValid - override fun inferComponents(): List { - return expressions.flatMap { - doGetComponentTypes(it) ?: return emptyList() + override fun inferComponents(): List = myComponentTypes + + private val myComponentTypes: List = run { + expressions.flatMap { + doGetComponentTypes(it) ?: return@run emptyList() } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.groovy index 9bab7705117d..adfa6e66a93c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.groovy @@ -994,7 +994,7 @@ def foo() { void 'test recursive literal types'() { RecursionManager.disableMissedCacheAssertions(testRootDisposable) - doExprTest 'def foo() { [foo()] }\nfoo()', "java.util.List" + doExprTest 'def foo() { [foo()] }\nfoo()', "java.util.List" doExprTest 'def foo() { [new Object(), foo()] }\nfoo()', "java.util.List" doExprTest 'def foo() { [someKey1: foo()] }\nfoo()', "java.util.LinkedHashMap" doExprTest 'def foo() { [someKey0: new Object(), someKey1: foo()] }\nfoo()',