From 46f3eae32ceb39e68206105f48cbaefb57a0972a Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Tue, 27 Sep 2016 17:31:54 +0300 Subject: [PATCH] Kapt: Dispose every JeElement and JeTypeMirror because some annotation processors may store them in static fields. (KT-13917) Hello, Data Binding, why you cache them? :( (cherry picked from commit d86a30b) --- .../processing/AnnotationProcessingPlugin.kt | 3 ++ .../processing/impl/DisposableRef.kt | 4 +- .../impl/KotlinProcessingEnvironment.kt | 10 +++-- .../annotation/processing/impl/KotlinTypes.kt | 4 +- .../jetbrains/kotlin/java/model/JeElement.kt | 32 +++++++++++++- .../java/model/elements/JeAnnotationMirror.kt | 3 +- .../java/model/elements/JeAnnotationValue.kt | 19 +++++---- .../JeClassInitializerExecutableElement.kt | 6 +-- .../elements/JeMethodExecutableElement.kt | 2 +- .../java/model/elements/JePackageElement.kt | 7 +--- .../java/model/elements/JeTypeElement.kt | 2 +- .../model/elements/JeTypeParameterElement.kt | 4 +- .../java/model/elements/JeVariableElement.kt | 4 +- .../java/model/internal/JeElementRegistry.kt | 42 +++++++++++++++++++ .../kotlin/java/model/types/JeArrayType.kt | 6 +-- .../JeClassInitializerExecutableTypeMirror.kt | 17 ++++---- .../kotlin/java/model/types/JeDeclaredType.kt | 18 ++++++-- .../java/model/types/JeIntersectionType.kt | 6 +-- .../types/JeMethodExecutableTypeMirror.kt | 29 +++++++++---- .../java/model/types/JePrimitiveType.kt | 2 +- .../kotlin/java/model/types/JePsiType.kt | 30 ++++++++++++- .../java/model/types/JeTypeVariableType.kt | 18 ++++++-- .../kotlin/java/model/types/JeWildcardType.kt | 13 +++--- .../test/processor/AbstractProcessorTest.kt | 4 ++ .../test/processor/ProcessorTests.kt | 2 +- .../AbstractAnnotationProcessingTest.kt | 4 ++ 26 files changed, 219 insertions(+), 72 deletions(-) create mode 100644 plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/JeElementRegistry.kt diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt index 11689af8597..ebc1b716ede 100755 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfigurationKey import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages +import org.jetbrains.kotlin.java.model.internal.JeElementRegistry import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension import java.io.File @@ -127,6 +128,8 @@ class AnnotationProcessingComponentRegistrar : ComponentRegistrar { val annotationProcessingExtension = ClasspathBasedAnnotationProcessingExtension( classpath, generatedOutputDirFile, classesOutputDir, javaRoots, verboseOutput, incrementalDataFile, sourceRetentionAnnotationHandler) + + project.registerService(JeElementRegistry::class.java, JeElementRegistry()) AnalysisCompletedHandlerExtension.registerExtension(project, annotationProcessingExtension) } diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/DisposableRef.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/DisposableRef.kt index ab781b61d18..dc4e1a8c3c9 100644 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/DisposableRef.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/DisposableRef.kt @@ -31,6 +31,6 @@ class DisposableRef(initialValue: T): Disposable { fun T.toDisposable() = DisposableRef(this) -fun dispose(vararg refs: DisposableRef<*>) { - refs.forEach { it.dispose() } +fun dispose(vararg refs: DisposableRef<*>?) { + refs.forEach { it?.dispose() } } \ No newline at end of file diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinProcessingEnvironment.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinProcessingEnvironment.kt index 21a39d254e8..c7edceb7723 100644 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinProcessingEnvironment.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinProcessingEnvironment.kt @@ -17,10 +17,12 @@ package org.jetbrains.kotlin.annotation.processing.impl import com.intellij.openapi.Disposable +import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.project.Project import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiManager import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.java.model.internal.JeElementRegistry import org.jetbrains.kotlin.resolve.BindingContext import java.io.File import java.util.* @@ -55,13 +57,15 @@ class KotlinProcessingEnvironment( internal val javaPsiFacade = javaPsiFacade.toDisposable() internal val projectScope = projectScope.toDisposable() internal val bindingContext = bindingContext.toDisposable() - + + private val registry = ServiceManager.getService(project, JeElementRegistry::class.java).toDisposable() internal val appendJavaSourceRootsHandler = appendJavaSourceRootsHandler.toDisposable() private val options = Collections.unmodifiableMap(options).toDisposable() override fun dispose() { - types.dispose() - elements.dispose() + types().dispose() + elements().dispose() + registry().dispose() dispose(elements, types, messager, filer, processors, project, psiManager, javaPsiFacade, projectScope, bindingContext, appendJavaSourceRootsHandler, options) diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinTypes.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinTypes.kt index ce93ad0be44..0b184a5cc16 100644 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinTypes.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/impl/KotlinTypes.kt @@ -272,8 +272,8 @@ class KotlinTypes( } override fun isSubsignature(t1: ExecutableType, t2: ExecutableType): Boolean { - val m1 = (t1 as JeClassInitializerExecutableTypeMirror).initializer - val m2 = (t2 as JeClassInitializerExecutableTypeMirror).initializer + val m1 = (t1 as JeClassInitializerExecutableTypeMirror).psi + val m2 = (t2 as JeClassInitializerExecutableTypeMirror).psi // No parameters if (m1 is PsiClassInitializer && m2 is PsiClassInitializer) return true diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeElement.kt index 9d576ffb521..b177c7d261d 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeElement.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/JeElement.kt @@ -16,9 +16,37 @@ package org.jetbrains.kotlin.java.model +import com.intellij.openapi.Disposable +import com.intellij.openapi.components.ServiceManager import com.intellij.psi.PsiElement +import com.intellij.psi.PsiManager +import org.jetbrains.kotlin.annotation.processing.impl.toDisposable +import org.jetbrains.kotlin.java.model.internal.JeElementRegistry import javax.lang.model.element.Element -interface JeElement : Element { +interface JePsiElementOwner { val psi: PsiElement -} \ No newline at end of file +} + +interface JeElement : Element, JePsiElementOwner + +abstract class JeDisposablePsiElementOwner(element: T) : JePsiElementOwner, Disposable { + private val disposablePsi = element.toDisposable() + + init { + @Suppress("LeakingThis") + ServiceManager.getService(element.project, JeElementRegistry::class.java).register(this) + } + + override fun dispose() { + disposablePsi.dispose() + } + + override val psi: T + get() = disposablePsi() + + val psiManager: PsiManager + get() = disposablePsi().manager +} + +abstract class JeAbstractElement(element: T) : JeDisposablePsiElementOwner(element), JeElement, Disposable \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationMirror.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationMirror.kt index cee86f9e670..6aea97a1191 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationMirror.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationMirror.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.java.model.elements import com.intellij.psi.* +import org.jetbrains.kotlin.java.model.JeDisposablePsiElementOwner import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters import org.jetbrains.kotlin.java.model.types.JeDeclaredErrorType import org.jetbrains.kotlin.java.model.types.JeDeclaredType @@ -25,7 +26,7 @@ import javax.lang.model.element.AnnotationValue import javax.lang.model.element.ExecutableElement import javax.lang.model.type.DeclaredType -class JeAnnotationMirror(val psi: PsiAnnotation) : AnnotationMirror { +class JeAnnotationMirror(psi: PsiAnnotation) : JeDisposablePsiElementOwner(psi), AnnotationMirror { override fun getAnnotationType(): DeclaredType? { val psiClass = resolveAnnotationClass() ?: return JeDeclaredErrorType return JeDeclaredType(psiClass.getTypeWithTypeParameters(), psiClass) diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationValue.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationValue.kt index f721267301c..fc2033d7b33 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationValue.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeAnnotationValue.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.java.model.elements import com.intellij.psi.* +import org.jetbrains.kotlin.java.model.JeDisposablePsiElementOwner import org.jetbrains.kotlin.java.model.internal.calcConstantValue import org.jetbrains.kotlin.java.model.types.toJeType import java.util.* @@ -48,22 +49,22 @@ fun JeAnnotationValue(psi: PsiAnnotationMemberValue): AnnotationValue { return annotationValue } -class JeAnnotationAnnotationValue(val psi: PsiAnnotation) : AnnotationValue { +class JeAnnotationAnnotationValue(psi: PsiAnnotation) : JeDisposablePsiElementOwner(psi), AnnotationValue { override fun getValue() = JeAnnotationMirror(psi) override fun accept(v: AnnotationValueVisitor, p: P) = v.visitAnnotation(value, p) } -class JeEnumValueAnnotationValue(val psi: PsiEnumConstant) : AnnotationValue { +class JeEnumValueAnnotationValue(psi: PsiEnumConstant) : JeDisposablePsiElementOwner(psi), AnnotationValue { override fun getValue() = JeVariableElement(psi) override fun accept(v: AnnotationValueVisitor, p: P) = v.visitEnumConstant(value, p) } -class JeTypeAnnotationValue(val psi: PsiClassObjectAccessExpression) : AnnotationValue { +class JeTypeAnnotationValue(psi: PsiClassObjectAccessExpression) : JeDisposablePsiElementOwner(psi), AnnotationValue { override fun getValue() = psi.operand.type.toJeType(psi.manager) override fun accept(v: AnnotationValueVisitor, p: P) = v.visitType(value, p) } -abstract class JePrimitiveAnnotationValue : AnnotationValue { +abstract class JePrimitiveAnnotationValue(psi: T) : JeDisposablePsiElementOwner(psi), AnnotationValue { override fun accept(v: AnnotationValueVisitor, p: P): R { val value = this.value return when (value) { @@ -81,25 +82,25 @@ abstract class JePrimitiveAnnotationValue : AnnotationValue { } } -class JeLiteralAnnotationValue(val psi: PsiLiteral) : JePrimitiveAnnotationValue() { +class JeLiteralAnnotationValue(psi: PsiLiteral) : JePrimitiveAnnotationValue(psi) { override fun getValue() = psi.value } -class JeExpressionAnnotationValue(val psi: PsiExpression) : JePrimitiveAnnotationValue() { +class JeExpressionAnnotationValue(psi: PsiExpression) : JePrimitiveAnnotationValue(psi) { override fun getValue() = psi.calcConstantValue() } -class JeArrayAnnotationValue(val psi: PsiArrayInitializerMemberValue) : AnnotationValue { +class JeArrayAnnotationValue(psi: PsiArrayInitializerMemberValue) : JeDisposablePsiElementOwner(psi), AnnotationValue { override fun getValue() = psi.initializers.map(::JeAnnotationValue) override fun accept(v: AnnotationValueVisitor, p: P) = v.visitArray(value, p) } -class JeSingletonArrayAnnotationValue(val psi: PsiAnnotationMemberValue) : AnnotationValue { +class JeSingletonArrayAnnotationValue(psi: PsiAnnotationMemberValue) : JeDisposablePsiElementOwner(psi), AnnotationValue { override fun getValue(): List = Collections.singletonList(JeAnnotationValue(psi)) override fun accept(v: AnnotationValueVisitor, p: P) = v.visitArray(value, p) } -class JeErrorAnnotationValue(val psi: PsiElement) : AnnotationValue { +class JeErrorAnnotationValue(psi: PsiElement) : JeDisposablePsiElementOwner(psi), AnnotationValue { override fun accept(v: AnnotationValueVisitor, p: P) = v.visitString(psi.text, p) override fun getValue() = null } \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeClassInitializerExecutableElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeClassInitializerExecutableElement.kt index 79146f5decb..1d190075db0 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeClassInitializerExecutableElement.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeClassInitializerExecutableElement.kt @@ -24,9 +24,9 @@ import org.jetbrains.kotlin.java.model.types.JeNoneType import javax.lang.model.element.* import javax.lang.model.type.TypeMirror -class JeClassInitializerExecutableElement(override val psi: PsiClassInitializer) : JeElement, - ExecutableElement, JeNoAnnotations, JeModifierListOwner -{ +class JeClassInitializerExecutableElement( + psi: PsiClassInitializer +) : JeAbstractElement(psi), ExecutableElement, JeNoAnnotations, JeModifierListOwner { val isStaticInitializer = psi.isStatic override fun getEnclosingElement() = psi.containingClass?.let { JeTypeElement(it) } diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeMethodExecutableElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeMethodExecutableElement.kt index 7273bb70ea4..52fb2990f3e 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeMethodExecutableElement.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeMethodExecutableElement.kt @@ -26,7 +26,7 @@ import org.jetbrains.kotlin.java.model.types.toJeType import javax.lang.model.element.* import javax.lang.model.type.TypeMirror -class JeMethodExecutableElement(override val psi: PsiMethod) : JeElement, ExecutableElement, JeModifierListOwner, JeAnnotationOwner { +class JeMethodExecutableElement(psi: PsiMethod) : JeAbstractElement(psi), ExecutableElement, JeModifierListOwner, JeAnnotationOwner { override fun getEnclosingElement() = psi.containingClass?.let(::JeTypeElement) override fun getSimpleName(): JeName { diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JePackageElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JePackageElement.kt index 6734b974f09..e1994e6c3e6 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JePackageElement.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JePackageElement.kt @@ -17,16 +17,13 @@ package org.jetbrains.kotlin.java.model.elements import com.intellij.psi.PsiPackage -import org.jetbrains.kotlin.java.model.JeElement -import org.jetbrains.kotlin.java.model.JeModifierListOwner -import org.jetbrains.kotlin.java.model.JeName -import org.jetbrains.kotlin.java.model.JeNoAnnotations +import org.jetbrains.kotlin.java.model.* import org.jetbrains.kotlin.java.model.types.JePackageTypeMirror import javax.lang.model.element.ElementKind import javax.lang.model.element.ElementVisitor import javax.lang.model.element.PackageElement -class JePackageElement(override val psi: PsiPackage) : JeElement, PackageElement, JeModifierListOwner, JeNoAnnotations { +class JePackageElement(psi: PsiPackage) : JeAbstractElement(psi), PackageElement, JeModifierListOwner, JeNoAnnotations { override fun getEnclosingElement() = null override fun getSimpleName() = JeName(psi.name) diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeElement.kt index fca81b14606..278fa163da3 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeElement.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeElement.kt @@ -28,7 +28,7 @@ import org.jetbrains.kotlin.java.model.types.toJeType import javax.lang.model.element.* import javax.lang.model.type.TypeMirror -class JeTypeElement(override val psi: PsiClass) : JeElement, TypeElement, JeAnnotationOwner, JeModifierListOwner { +class JeTypeElement(psi: PsiClass) : JeAbstractElement(psi), TypeElement, JeAnnotationOwner, JeModifierListOwner { override fun getEnclosingElement(): Element? { psi.containingClass?.let { return JeTypeElement(it) } val javaFile = psi.containingFile as? PsiJavaFile ?: return null diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeParameterElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeParameterElement.kt index 61ae4ecd256..ea460896f51 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeParameterElement.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeTypeParameterElement.kt @@ -26,9 +26,9 @@ import javax.lang.model.element.ElementVisitor import javax.lang.model.element.TypeParameterElement class JeTypeParameterElement( - override val psi: PsiTypeParameter, + psi: PsiTypeParameter, val parent: JeElement? -) : JeElement, TypeParameterElement, JeAnnotationOwner, JeModifierListOwner { +) : JeAbstractElement(psi), TypeParameterElement, JeAnnotationOwner, JeModifierListOwner { override fun getSimpleName() = JeName(psi.name) override fun getEnclosingElement() = parent diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeVariableElement.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeVariableElement.kt index 05cc9e00fbf..c9bfb47d2c6 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeVariableElement.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/elements/JeVariableElement.kt @@ -26,10 +26,12 @@ import javax.lang.model.element.ElementKind import javax.lang.model.element.ElementVisitor import javax.lang.model.element.VariableElement -class JeVariableElement(override val psi: PsiVariable) : JeElement, VariableElement, JeModifierListOwner, JeAnnotationOwner { +class JeVariableElement(psi: PsiVariable) : JeAbstractElement(psi), VariableElement, JeModifierListOwner, JeAnnotationOwner { override fun getSimpleName() = JeName(psi.name) override fun getEnclosingElement(): JeElement? { + val psi = psi + if (psi is PsiParameter) { (psi.declarationScope as? PsiMethod)?.let { return JeMethodExecutableElement(it) } } diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/JeElementRegistry.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/JeElementRegistry.kt new file mode 100644 index 00000000000..eb036d9c492 --- /dev/null +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/internal/JeElementRegistry.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2016 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.java.model.internal + +import com.intellij.openapi.Disposable + +/* + Some annotation processors (I'm looking at you, Data Binding) + have a habit to cache Element or TypeMirror instances into static fields. + Because almost every JeElement or JeTypeMirror is dependent on some PsiElement, and PsiElements are dependent on PsiProject, + the entire project will not be gc'ed normally. + JeElementRegistry allows us to remove all Psi*-references from our wrapper Element and TypeMirror instances. + + So this class basically remembers all instances created by kapt, and disposes all of them as the Annotation Processing is complete. + */ +class JeElementRegistry : Disposable { + private val list = mutableListOf() + + fun register(obj: Disposable) { + list += obj + } + + override fun dispose() { + val list = this.list + list.forEach { it.dispose() } + this.list.clear() + } +} \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeArrayType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeArrayType.kt index 9a3c0570c91..6157c700b77 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeArrayType.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeArrayType.kt @@ -23,10 +23,10 @@ import javax.lang.model.type.TypeKind import javax.lang.model.type.TypeVisitor class JeArrayType( - override val psiType: PsiArrayType, - override val psiManager: PsiManager, + psiType: PsiArrayType, + psiManager: PsiManager, private val isRaw: Boolean -) : JePsiType(), JeTypeWithManager, ArrayType { +) : JePsiTypeBase(psiType, psiManager), ArrayType { override fun getKind() = TypeKind.ARRAY override fun accept(v: TypeVisitor, p: P) = v.visitArray(this, p) override fun getComponentType() = psiType.componentType.toJeType(psiManager, isRaw = isRaw) diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeClassInitializerExecutableTypeMirror.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeClassInitializerExecutableTypeMirror.kt index bb01ac46f2f..ddd62b518d4 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeClassInitializerExecutableTypeMirror.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeClassInitializerExecutableTypeMirror.kt @@ -17,18 +17,17 @@ package org.jetbrains.kotlin.java.model.types import com.intellij.psi.PsiClassInitializer -import com.intellij.psi.PsiManager +import org.jetbrains.kotlin.java.model.JeDisposablePsiElementOwner import org.jetbrains.kotlin.java.model.internal.isStatic import javax.lang.model.type.* -class JeClassInitializerExecutableTypeMirror(val initializer: PsiClassInitializer) : JeTypeMirror, JeTypeWithManager, ExecutableType { +class JeClassInitializerExecutableTypeMirror( + psi: PsiClassInitializer +) : JeDisposablePsiElementOwner(psi), JeTypeMirror, JeTypeWithManager, ExecutableType { override fun getKind() = TypeKind.EXECUTABLE override fun accept(v: TypeVisitor, p: P) = v.visitExecutable(this, p) - override val psiManager: PsiManager - get() = initializer.manager - override fun getReturnType() = JeVoidType override fun getReceiverType() = JeNoneType @@ -39,15 +38,15 @@ class JeClassInitializerExecutableTypeMirror(val initializer: PsiClassInitialize override fun getTypeVariables() = emptyList() - override fun toString() = (initializer.containingClass?.qualifiedName?.let { it + "." } ?: "") + - (if (initializer.isStatic) "" else "") + override fun toString() = (psi.containingClass?.qualifiedName?.let { it + "." } ?: "") + + (if (psi.isStatic) "" else "") override fun equals(other: Any?): Boolean { if (this === other) return true if (other?.javaClass != javaClass) return false other as? JeClassInitializerExecutableTypeMirror ?: return false - return initializer == other.initializer + return psi == other.psi } - override fun hashCode() = initializer.hashCode() + override fun hashCode() = psi.hashCode() } \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeDeclaredType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeDeclaredType.kt index c16b961c737..5f7fcdb6c5b 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeDeclaredType.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeDeclaredType.kt @@ -21,6 +21,7 @@ import com.intellij.psi.* import com.intellij.psi.impl.PsiSubstitutorImpl import com.intellij.psi.impl.source.PsiClassReferenceType import com.intellij.psi.impl.source.PsiImmediateClassType +import org.jetbrains.kotlin.annotation.processing.impl.toDisposable import org.jetbrains.kotlin.java.model.elements.JeTypeElement import org.jetbrains.kotlin.java.model.internal.getTypeWithTypeParameters import org.jetbrains.kotlin.java.model.internal.isStatic @@ -39,11 +40,22 @@ fun createImmediateClassType(psiClass: PsiClass, typeArgs: List): PsiIm } class JeDeclaredType( - override val psiType: PsiClassType, - val psiClass: PsiClass, + psiType: PsiClassType, + psiClass: PsiClass, val enclosingDeclaredType: DeclaredType? = null, val isRaw: Boolean = false -) : JePsiType(), JeTypeWithManager, DeclaredType { +) : JePsiTypeBase(psiType, psiClass.manager), DeclaredType { + private val disposablePsiClass = psiClass.toDisposable() + + val psiClass: PsiClass + get() = disposablePsiClass() + + // JeElementRegistry registration is done in JePsiType + override fun dispose() { + super.dispose() + disposablePsiClass.dispose() + } + override fun getKind() = TypeKind.DECLARED override fun accept(v: TypeVisitor, p: P) = v.visitDeclared(this, p) diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeIntersectionType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeIntersectionType.kt index 1d1e4c2f9cd..11658e98e79 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeIntersectionType.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeIntersectionType.kt @@ -23,10 +23,10 @@ import javax.lang.model.type.TypeKind import javax.lang.model.type.TypeVisitor class JeIntersectionType( - override val psiType: PsiIntersectionType, - override val psiManager: PsiManager, + psiType: PsiIntersectionType, + psiManager: PsiManager, private val isRaw: Boolean -) : JePsiType(), JeTypeWithManager, IntersectionType { +) : JePsiTypeBase(psiType, psiManager), IntersectionType { override fun getKind() = TypeKind.INTERSECTION override fun accept(v: TypeVisitor, p: P) = v.visitIntersection(this, p) diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeMethodExecutableTypeMirror.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeMethodExecutableTypeMirror.kt index a5336912adb..d2915304678 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeMethodExecutableTypeMirror.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeMethodExecutableTypeMirror.kt @@ -21,6 +21,9 @@ import com.intellij.psi.PsiMethod import com.intellij.psi.PsiType import com.intellij.psi.util.MethodSignature import com.intellij.psi.util.PsiTypesUtil +import org.jetbrains.kotlin.annotation.processing.impl.toDisposable +import org.jetbrains.kotlin.annotation.processing.impl.dispose +import org.jetbrains.kotlin.java.model.JeDisposablePsiElementOwner import org.jetbrains.kotlin.java.model.elements.getReceiverTypeMirror import javax.lang.model.type.ExecutableType import javax.lang.model.type.TypeKind @@ -28,11 +31,26 @@ import javax.lang.model.type.TypeMirror import javax.lang.model.type.TypeVisitor class JeMethodExecutableTypeMirror( - val psi: PsiMethod, - val signature: MethodSignature? = null, - val returnType: PsiType? = null, + psi: PsiMethod, + signature: MethodSignature? = null, + returnType: PsiType? = null, val isRaw: Boolean = false -) : JeTypeMirror, JeTypeWithManager, ExecutableType { +) : JeDisposablePsiElementOwner(psi), JeTypeMirror, JeTypeWithManager, ExecutableType { + private val disposableSignature = signature?.toDisposable() + private val disposableReturnType = returnType?.toDisposable() + + val signature: MethodSignature? + get() = disposableSignature?.invoke() + + val returnType: PsiType? + get() = disposableReturnType?.invoke() + + // JeElementRegistry registration is done in JeDisposablePsiElementOwner + override fun dispose() { + super.dispose() + dispose(disposableSignature, disposableReturnType) + } + override fun getKind() = TypeKind.EXECUTABLE override fun accept(v: TypeVisitor, p: P) = v.visitExecutable(this, p) @@ -43,9 +61,6 @@ class JeMethodExecutableTypeMirror( override fun getThrownTypes() = psi.throwsList.referencedTypes.map { it.toJeType(psi.manager, isRaw = isRaw) } - override val psiManager: PsiManager - get() = psi.manager - override fun getParameterTypes(): List { signature?.parameterTypes?.let { types -> return types.map { it.toJeType(psi.manager, isRaw = isRaw) } } return psi.parameterList.parameters.map { it.type.toJeType(psi.manager, isRaw = isRaw) } diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JePrimitiveType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JePrimitiveType.kt index a11042e816e..feffc97b18d 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JePrimitiveType.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JePrimitiveType.kt @@ -22,7 +22,7 @@ import javax.lang.model.type.PrimitiveType import javax.lang.model.type.TypeKind import javax.lang.model.type.TypeVisitor -class JePrimitiveType(override val psiType: PsiPrimitiveType) : JePsiType(), PrimitiveType { +class JePrimitiveType(override val psiType: PsiPrimitiveType) : JePsiType, PrimitiveType { override fun accept(v: TypeVisitor, p: P) = v.visitPrimitive(this, p) override fun getKind() = when (psiType) { diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JePsiType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JePsiType.kt index 3b7c7222338..f03d8c79ac2 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JePsiType.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JePsiType.kt @@ -16,8 +16,34 @@ package org.jetbrains.kotlin.java.model.types +import com.intellij.openapi.Disposable +import com.intellij.openapi.components.ServiceManager +import com.intellij.psi.PsiManager import com.intellij.psi.PsiType +import org.jetbrains.kotlin.annotation.processing.impl.toDisposable +import org.jetbrains.kotlin.java.model.internal.JeElementRegistry +import org.jetbrains.kotlin.annotation.processing.impl.dispose -abstract class JePsiType : JeTypeMirror { - abstract val psiType: PsiType +interface JePsiType : JeTypeMirror { + val psiType: PsiType +} + +abstract class JePsiTypeBase( + psiType: T, + manager: PsiManager +) : JePsiType, JeTypeWithManager, Disposable { + private val disposableManager = manager.toDisposable() + private val disposableType = psiType.toDisposable() + + init { + ServiceManager.getService(manager.project, JeElementRegistry::class.java).register(this) + } + + override fun dispose() = dispose(disposableManager, disposableType) + + override val psiManager: PsiManager + get() = disposableManager() + + override val psiType: T + get() = disposableType() } \ No newline at end of file diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeTypeVariableType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeTypeVariableType.kt index 9b2d31c0f02..f1751537eb3 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeTypeVariableType.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeTypeVariableType.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.java.model.types import org.jetbrains.kotlin.java.model.elements.JeTypeParameterElement import com.intellij.psi.* +import org.jetbrains.kotlin.annotation.processing.impl.toDisposable import org.jetbrains.kotlin.java.model.toJeElement import javax.lang.model.type.TypeKind import javax.lang.model.type.TypeMirror @@ -25,9 +26,20 @@ import javax.lang.model.type.TypeVariable import javax.lang.model.type.TypeVisitor class JeTypeVariableType( - override val psiType: PsiClassType, - val parameter: PsiTypeParameter -) : JePsiType(), JeTypeWithManager, TypeVariable { + psiType: PsiClassType, + parameter: PsiTypeParameter +) : JePsiTypeBase(psiType, parameter.manager), TypeVariable { + private val disposableParameter = parameter.toDisposable() + + val parameter: PsiTypeParameter + get() = disposableParameter() + + // JeElementRegistry registration is done in JeDisposablePsiElementOwner + override fun dispose() { + super.dispose() + disposableParameter.dispose() + } + override fun getKind() = TypeKind.TYPEVAR override fun accept(v: TypeVisitor, p: P) = v.visitTypeVariable(this, p) diff --git a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeWildcardType.kt b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeWildcardType.kt index 030ae51facf..4ff0b298b02 100644 --- a/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeWildcardType.kt +++ b/plugins/java-model-wrappers/src/org/jetbrains/kotlin/java/model/types/JeWildcardType.kt @@ -24,18 +24,15 @@ import javax.lang.model.type.TypeVisitor import javax.lang.model.type.WildcardType class JeWildcardType( - override val psiType: PsiWildcardType, + psiType: PsiWildcardType, private val isRaw: Boolean -) : JePsiType(), JeTypeWithManager, WildcardType { +) : JePsiTypeBase(psiType, psiType.manager), WildcardType { override fun getKind() = TypeKind.WILDCARD override fun accept(v: TypeVisitor, p: P) = v.visitWildcard(this, p) override fun getSuperBound() = psiType.superBound.toJeType(psiManager, isRaw = isRaw) override fun getExtendsBound() = psiType.extendsBound.toJeType(psiManager, isRaw = isRaw) - override val psiManager: PsiManager - get() = psiType.manager - override fun equals(other: Any?): Boolean { if (this === other) return true if (other?.javaClass != javaClass) return false @@ -61,10 +58,10 @@ class JeWildcardType( } class JeCapturedWildcardType( - override val psiType: PsiCapturedWildcardType, - override val psiManager: PsiManager, + psiType: PsiCapturedWildcardType, + psiManager: PsiManager, private val isRaw: Boolean -) : JePsiType(), JeTypeWithManager, WildcardType { +) : JePsiTypeBase(psiType, psiManager), WildcardType { override fun getKind() = TypeKind.WILDCARD override fun accept(v: TypeVisitor, p: P) = v.visitWildcard(this, p) diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt index 7e92ede36cf..182ebe303cf 100755 --- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.annotation.processing.test.processor +import com.intellij.testFramework.registerServiceInstance import org.jetbrains.kotlin.annotation.AbstractAnnotationProcessingExtension import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment @@ -26,6 +27,7 @@ import org.jetbrains.kotlin.java.model.elements.JeAnnotationMirror import org.jetbrains.kotlin.java.model.elements.JeMethodExecutableElement import org.jetbrains.kotlin.java.model.elements.JeTypeElement import org.jetbrains.kotlin.java.model.elements.JeVariableElement +import org.jetbrains.kotlin.java.model.internal.JeElementRegistry import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.KotlinTestUtils @@ -67,6 +69,8 @@ abstract class AbstractProcessorTest : AbstractBytecodeTextTest() { val apExtension = AnnotationProcessingExtensionForTests(processors) AnalysisCompletedHandlerExtension.registerExtension(project, apExtension) + project.registerServiceInstance(JeElementRegistry::class.java, JeElementRegistry()) + return environment } diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt index 0e3a58d9735..1c1a8a4d2b2 100644 --- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt @@ -122,7 +122,7 @@ class ProcessorTests : AbstractProcessorTest() { fun AnnotationMirror.getParam(name: String) = elementValues.entries.first { it.key.simpleName.toString() == name }.value assertTrue(anno2.getParam("a") is JeAnnotationAnnotationValue) assertTrue((anno2.getParam("b") as JeArrayAnnotationValue).value.first() is JeAnnotationAnnotationValue) - assertTrue(anno2.getParam("c") is JePrimitiveAnnotationValue) + assertTrue(anno2.getParam("c") is JePrimitiveAnnotationValue<*>) assertTrue(anno2.getParam("d") is JeTypeAnnotationValue) assertTrue((anno2.getParam("e") as JeArrayAnnotationValue).value.first() is JeTypeAnnotationValue) } diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/AbstractAnnotationProcessingTest.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/AbstractAnnotationProcessingTest.kt index 5128c03a989..17637457259 100755 --- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/AbstractAnnotationProcessingTest.kt +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/AbstractAnnotationProcessingTest.kt @@ -19,10 +19,12 @@ package org.jetbrains.kotlin.annotation.processing.test.wrappers import com.intellij.openapi.util.io.FileUtil import com.intellij.psi.JavaPsiFacade import com.intellij.psi.search.GlobalSearchScope +import com.intellij.testFramework.registerServiceInstance import org.jetbrains.kotlin.codegen.AbstractBytecodeTextTest import org.jetbrains.kotlin.codegen.CodegenTestCase import org.jetbrains.kotlin.codegen.CodegenTestUtil import org.jetbrains.kotlin.java.model.elements.DefaultJeElementRenderer +import org.jetbrains.kotlin.java.model.internal.JeElementRegistry import org.jetbrains.kotlin.java.model.toJeElement import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.KotlinTestUtils @@ -38,6 +40,8 @@ abstract class AbstractAnnotationProcessingTest : AbstractBytecodeTextTest() { override fun doMultiFileTest(wholeFile: File, files: List, javaFilesDir: File?) { createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL, files, javaFilesDir) + myEnvironment.project.registerServiceInstance(JeElementRegistry::class.java, JeElementRegistry()) + loadMultiFiles(files) val text = FileUtil.loadFile(wholeFile, true)