From 6ac345df516b38b4bf5ee1300626c936079f2672 Mon Sep 17 00:00:00 2001 From: Nicolay Mitropolsky Date: Tue, 12 Dec 2017 19:29:59 +0300 Subject: [PATCH] Caching `KtLightClassForSourceDeclaration` (KT-21701) to make their UserData survive for longer, because otherwise a new LightClass with empty UserData comes to Spring every time, but Spring stores a lot of important things in UserData --- .../KtLightClassForSourceDeclaration.kt | 10 +++- .../kotlin/asJava/KotlinLightClassTest.kt | 58 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 compiler/tests/org/jetbrains/kotlin/asJava/KotlinLightClassTest.kt diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt index cbffbe0e15f..b28d2fcd2d6 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt @@ -31,7 +31,9 @@ import com.intellij.psi.search.SearchScope import com.intellij.psi.stubs.IStubElementType import com.intellij.psi.stubs.StubElement import com.intellij.psi.util.CachedValue +import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager +import com.intellij.psi.util.PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT import com.intellij.util.IncorrectOperationException import com.intellij.util.containers.ContainerUtil import org.jetbrains.annotations.NonNls @@ -331,7 +333,13 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC FINAL_KEYWORD to PsiModifier.FINAL) - fun create(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? { + fun create(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? = + CachedValuesManager.getCachedValue(classOrObject) { + CachedValueProvider.Result + .create(createNoCache(classOrObject), OUT_OF_CODE_BLOCK_MODIFICATION_COUNT) + } + + private fun createNoCache(classOrObject: KtClassOrObject): KtLightClassForSourceDeclaration? { if (classOrObject.hasExpectModifier()) { return null } diff --git a/compiler/tests/org/jetbrains/kotlin/asJava/KotlinLightClassTest.kt b/compiler/tests/org/jetbrains/kotlin/asJava/KotlinLightClassTest.kt new file mode 100644 index 00000000000..3f132a2ece4 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/asJava/KotlinLightClassTest.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.asJava + +import com.intellij.openapi.util.Key +import com.intellij.psi.search.GlobalSearchScope +import junit.framework.TestCase +import org.jetbrains.kotlin.asJava.classes.KtLightClass +import java.io.File + +class KotlinLightClassTest : KotlinAsJavaTestBase() { + override fun getKotlinSourceRoots(): List = listOf( + File("compiler/testData/asJava/lightClassStructure/ClassObject.kt"), + File("compiler/testData/asJava/lightClasses/ideRegression/ImplementingMap.kt") + ) + + private val key = Key.create("testKey") + + fun testClassInterchangeability() { + val lightClass = finder.findClass("test.WithClassObject", GlobalSearchScope.allScope(project)) as KtLightClass + val kotlinOrigin = lightClass.kotlinOrigin ?: throw AssertionError("no kotlinOrigin") + val testValue = "some data" + lightClass.putUserData(key, testValue) + val anotherLightClass = kotlinOrigin.toLightClass() ?: throw AssertionError("cant get light class second time") + TestCase.assertEquals(testValue, anotherLightClass.getUserData(key)) + TestCase.assertEquals(lightClass, anotherLightClass) + } + + fun testMethodInterchangeability() { + val lightClass = finder.findClass("p1.TypeHierarchyMap", GlobalSearchScope.allScope(project)) as KtLightClass + val kotlinOrigin = lightClass.kotlinOrigin ?: throw AssertionError("no kotlinOrigin") + + val anotherLightClass = kotlinOrigin.toLightClass() ?: throw AssertionError("cant get light class second time") + + val lightMethod1 = lightClass.methods.first { it.name == "containsKey" } + + val testValue = "some data" + lightMethod1.putUserData(key, testValue) + val lightMethod2 = anotherLightClass.methods.first { it.name == "containsKey" } + TestCase.assertEquals(testValue, lightMethod2.getUserData(key)) + TestCase.assertEquals(lightMethod1, lightMethod2) + } + +} \ No newline at end of file