Light classes: refactor, introduce lazyPub util to reduce verbosity

This commit is contained in:
Pavel V. Talanov
2017-03-13 18:16:11 +03:00
parent ba185d7616
commit feae5079ed
12 changed files with 87 additions and 54 deletions
@@ -32,6 +32,7 @@ import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForFileFacade
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.idea.KotlinLanguage
@@ -194,7 +195,7 @@ class KtLightClassForFacade private constructor(
override fun copy() = KtLightClassForFacade(manager, facadeClassFqName, lightClassDataCache, files)
override val lightClassData by lazy(LazyThreadSafetyMode.PUBLICATION) {
override val lightClassData by lazyPub {
lightClassDataCache.value.findDataForFacade(facadeClassFqName)
}
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiMethod
import com.intellij.psi.impl.light.LightClass
import com.intellij.psi.impl.light.LightMethod
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.*
@@ -36,7 +37,7 @@ open class KtLightClassForLocalDeclaration(
override fun getParent() = _parent
private val _parent: PsiElement? by lazy(LazyThreadSafetyMode.PUBLICATION, this::computeParent)
private val _parent: PsiElement? by lazyPub(this::computeParent)
private fun computeParent(): PsiElement? {
fun getParentByPsiMethod(method: PsiMethod?, name: String?, forceMethodWrapping: Boolean): PsiElement? {
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
import org.jetbrains.kotlin.asJava.elements.KtLightModifierListWithExplicitModifiers
import org.jetbrains.kotlin.asJava.elements.KtLightPsiReferenceList
import org.jetbrains.kotlin.asJava.hasInterfaceDefaultImpls
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.lexer.KtTokens
@@ -62,13 +63,13 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
: KtLazyLightClass(classOrObject.manager), StubBasedPsiElement<KotlinClassOrObjectStub<out KtClassOrObject>> {
private val lightIdentifier = KtLightIdentifier(this, classOrObject)
private val _extendsList by lazy(LazyThreadSafetyMode.PUBLICATION) {
val listDelegate = super.getExtendsList() ?: return@lazy null
private val _extendsList by lazyPub {
val listDelegate = super.getExtendsList() ?: return@lazyPub null
KtLightPsiReferenceList(listDelegate, this)
}
private val _implementsList by lazy(LazyThreadSafetyMode.PUBLICATION) {
val listDelegate = super.getImplementsList() ?: return@lazy null
private val _implementsList by lazyPub {
val listDelegate = super.getImplementsList() ?: return@lazyPub null
KtLightPsiReferenceList(listDelegate, this)
}
@@ -80,7 +81,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
override val clsDelegate: PsiClass get() = lightClassData.clsDelegate
override val lightClassData: LightClassData by lazy(LazyThreadSafetyMode.PUBLICATION) { findLightClassData() }
override val lightClassData: LightClassData by lazyPub { findLightClassData() }
open protected fun findLightClassData() = getLightClassDataHolder().findDataForClassOrObject(classOrObject)
@@ -98,7 +99,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
return lightClassData
}
private val _containingFile: PsiFile by lazy(LazyThreadSafetyMode.PUBLICATION) {
private val _containingFile: PsiFile by lazyPub {
classOrObject.containingFile.virtualFile ?: error("No virtual file for " + classOrObject.text)
object : FakeFileForLightClass(
@@ -165,7 +166,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
return super.getContainingClass()
}
private val _typeParameterList: PsiTypeParameterList by lazy(LazyThreadSafetyMode.PUBLICATION) {
private val _typeParameterList: PsiTypeParameterList by lazyPub {
LightClassUtil.buildLightTypeParameterList(this, classOrObject)
}
@@ -175,7 +176,7 @@ abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtC
override fun getName(): String? = classOrObject.nameAsName?.asString()
private val _modifierList: PsiModifierList by lazy(LazyThreadSafetyMode.PUBLICATION) {
private val _modifierList: PsiModifierList by lazyPub {
object : KtLightModifierListWithExplicitModifiers(this@KtLightClassForSourceDeclaration, computeModifiers()) {
override val delegate: PsiAnnotationOwner
get() = this@KtLightClassForSourceDeclaration.delegate.modifierList!!
@@ -0,0 +1,20 @@
/*
* 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.classes
// NOTE: avoid using blocking lazy in light classes, it leads to deadlocks
fun <T> lazyPub(initializer: () -> T) = lazy(LazyThreadSafetyMode.PUBLICATION, initializer)
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.*
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
@@ -41,16 +42,16 @@ class KtLightAnnotation(
val delegate: D,
private val parent: PsiElement
) : PsiAnnotationMemberValue, PsiExpression by delegate {
val originalExpression: PsiElement? by lazy(LazyThreadSafetyMode.PUBLICATION) {
val nameAndValue = delegate.getStrictParentOfType<PsiNameValuePair>() ?: return@lazy null
val originalExpression: PsiElement? by lazyPub {
val nameAndValue = delegate.getStrictParentOfType<PsiNameValuePair>() ?: return@lazyPub null
val annotationEntry = this@KtLightAnnotation.kotlinOrigin
val context = LightClassGenerationSupport.getInstance(project).analyze(annotationEntry)
val resolvedCall = annotationEntry.getResolvedCall(context) ?: return@lazy null
val resolvedCall = annotationEntry.getResolvedCall(context) ?: return@lazyPub null
val annotationConstructor = resolvedCall.resultingDescriptor
val parameterName = nameAndValue.name ?: "value"
val parameter = annotationConstructor.valueParameters.singleOrNull { it.name.asString() == parameterName }
?: return@lazy null
val resolvedArgument = resolvedCall.valueArguments[parameter] ?: return@lazy null
?: return@lazyPub null
val resolvedArgument = resolvedCall.valueArguments[parameter] ?: return@lazyPub null
when (resolvedArgument) {
is DefaultValueArgument -> {
val psi = parameter.source.getPsi()
@@ -129,7 +130,7 @@ class KtLightAnnotation(
private val delegate: PsiArrayInitializerMemberValue,
private val parent: PsiElement
) : PsiArrayInitializerMemberValue by delegate {
private val _initializers by lazy(LazyThreadSafetyMode.PUBLICATION) { delegate.initializers.map { wrapAnnotationValue(it, this) }.toTypedArray() }
private val _initializers by lazyPub { delegate.initializers.map { wrapAnnotationValue(it, this) }.toTypedArray() }
override fun getInitializers() = _initializers
override fun getLanguage() = KotlinLanguage.INSTANCE
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForEnumEntry
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtEnumEntry
@@ -42,9 +43,9 @@ sealed class KtLightFieldImpl<T: PsiField>(
private val containingClass: KtLightClass,
private val dummyDelegate: PsiField?
) : LightElement(containingClass.manager, KotlinLanguage.INSTANCE), KtLightField {
private val lightIdentifier by lazy(LazyThreadSafetyMode.PUBLICATION) { KtLightIdentifier(this, kotlinOrigin as? KtNamedDeclaration) }
private val lightIdentifier by lazyPub { KtLightIdentifier(this, kotlinOrigin as? KtNamedDeclaration) }
override val clsDelegate: T by lazy(LazyThreadSafetyMode.PUBLICATION, computeRealDelegate)
override val clsDelegate: T by lazyPub(computeRealDelegate)
@Throws(IncorrectOperationException::class)
override fun setInitializer(initializer: PsiExpression?) = throw IncorrectOperationException("Not supported")
@@ -83,7 +84,7 @@ sealed class KtLightFieldImpl<T: PsiField>(
return this
}
private val _modifierList by lazy(LazyThreadSafetyMode.PUBLICATION) {
private val _modifierList by lazyPub {
if (lightMemberOrigin is LightMemberOriginForDeclaration)
clsDelegate.modifierList?.let { KtLightModifierList(it, this) }
else clsDelegate.modifierList
@@ -134,7 +135,7 @@ sealed class KtLightFieldImpl<T: PsiField>(
containingClass: KtLightClass,
dummyDelegate: PsiField?
) : KtLightFieldImpl<PsiEnumConstant>(origin, computeDelegate , containingClass, dummyDelegate), PsiEnumConstant {
private val initializingClass by lazy(LazyThreadSafetyMode.PUBLICATION) {
private val initializingClass by lazyPub {
val kotlinEnumEntry = (lightMemberOrigin as? LightMemberOriginForDeclaration)?.originalElement as? KtEnumEntry
if (kotlinEnumEntry != null && kotlinEnumEntry.declarations.isNotEmpty()) {
KtLightClassForEnumEntry(kotlinEnumEntry, clsDelegate)
@@ -29,6 +29,7 @@ import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.builder.*
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.propertyNameByAccessor
import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.idea.KotlinLanguage
@@ -51,10 +52,10 @@ class KtLightMethodImpl private constructor(
) : LightElement(containingClass.manager, containingClass.language), KtLightMethod {
override val kotlinOrigin: KtDeclaration? get() = lightMethodOrigin?.originalElement as? KtDeclaration
override val clsDelegate by lazy(LazyThreadSafetyMode.PUBLICATION, computeRealDelegate)
override val clsDelegate by lazyPub(computeRealDelegate)
private val lightIdentifier by lazy(LazyThreadSafetyMode.PUBLICATION) { KtLightIdentifier(this, kotlinOrigin as? KtNamedDeclaration) }
private val returnTypeElem by lazy(LazyThreadSafetyMode.PUBLICATION) {
private val lightIdentifier by lazyPub { KtLightIdentifier(this, kotlinOrigin as? KtNamedDeclaration) }
private val returnTypeElem by lazyPub {
val delegateTypeElement = clsDelegate.returnTypeElement as? ClsTypeElementImpl
delegateTypeElement?.let { ClsTypeElementImpl(this, it.canonicalText, /*ClsTypeElementImpl.VARIANCE_NONE */ 0.toChar()) }
}
@@ -63,29 +64,31 @@ class KtLightMethodImpl private constructor(
override fun getContainingClass(): KtLightClass = containingClass
private val paramsList: PsiParameterList by lazy(LazyThreadSafetyMode.PUBLICATION) {
private val paramsList: PsiParameterList by lazyPub {
KtLightParameterList(this, dummyDelegate?.parameterList?.parametersCount ?: clsDelegate.parameterList.parametersCount) {
clsDelegate.parameterList.parameters.mapIndexed { index, clsParameter -> KtLightParameter(clsParameter, index, this@KtLightMethodImpl) }
}
}
private val typeParamsList: CachedValue<PsiTypeParameterList> by lazy(LazyThreadSafetyMode.PUBLICATION) {
private val typeParamsList: CachedValue<PsiTypeParameterList> by lazyPub {
val cacheManager = CachedValuesManager.getManager(clsDelegate.project)
cacheManager.createCachedValue<PsiTypeParameterList>({
val origin = (lightMethodOrigin as? LightMemberOriginForDeclaration)?.originalElement
val list = if (origin != null) {
if (origin is KtClassOrObject) {
KotlinLightTypeParameterListBuilder(manager)
}
else {
LightClassUtil.buildLightTypeParameterList(this@KtLightMethodImpl, origin)
}
}
else {
clsDelegate.typeParameterList
}
CachedValueProvider.Result.create(list, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)
}, false)
cacheManager.createCachedValue<PsiTypeParameterList>(
{
val origin = (lightMethodOrigin as? LightMemberOriginForDeclaration)?.originalElement
val list = if (origin != null) {
if (origin is KtClassOrObject) {
KotlinLightTypeParameterListBuilder(manager)
}
else {
LightClassUtil.buildLightTypeParameterList(this@KtLightMethodImpl, origin)
}
}
else {
clsDelegate.typeParameterList
}
CachedValueProvider.Result.create(list, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)
}, false
)
}
override fun getNavigationElement(): PsiElement = kotlinOrigin?.navigationElement ?: super.getNavigationElement()
@@ -137,7 +140,7 @@ class KtLightMethodImpl private constructor(
throw IncorrectOperationException(JavaCoreBundle.message("psi.error.attempt.to.edit.class.file"))
}
private val _modifierList by lazy(LazyThreadSafetyMode.PUBLICATION) {
private val _modifierList by lazyPub {
if (lightMethodOrigin is LightMemberOriginForDeclaration)
KtLightModifierList(clsDelegate.modifierList, this)
else clsDelegate.modifierList
@@ -26,6 +26,7 @@ import com.intellij.psi.util.PsiModificationTracker
import com.intellij.util.ArrayUtil
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtAnnotationEntry
@@ -40,7 +41,7 @@ abstract class KtLightModifierListWithExplicitModifiers(
) : LightModifierList(owner.manager, KotlinLanguage.INSTANCE, *modifiers) {
abstract val delegate: PsiAnnotationOwner
private val _annotations by lazy(LazyThreadSafetyMode.PUBLICATION) { computeAnnotations(this, delegate) }
private val _annotations by lazyPub { computeAnnotations(this, delegate) }
override fun getParent() = owner
@@ -57,7 +58,7 @@ class KtLightModifierList(
private val delegate: PsiModifierList,
private val owner: PsiModifierListOwner
) : PsiModifierList by delegate {
private val _annotations by lazy(LazyThreadSafetyMode.PUBLICATION) { computeAnnotations(this, delegate) }
private val _annotations by lazyPub { computeAnnotations(this, delegate) }
override fun getAnnotations(): Array<out PsiAnnotation> = _annotations.value
@@ -18,13 +18,14 @@ package org.jetbrains.kotlin.asJava.elements
import com.intellij.psi.*
import com.intellij.psi.impl.light.LightElement
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.idea.KotlinLanguage
class KtLightParameterList(
private val parent: KtLightMethod,
private val parametersCount: Int,
computeParameters: () -> List<PsiParameter>) : LightElement(parent.manager, KotlinLanguage.INSTANCE), PsiParameterList {
private val _parameters: Array<PsiParameter> by lazy { computeParameters().toTypedArray() }
private val _parameters: Array<PsiParameter> by lazyPub { computeParameters().toTypedArray() }
override fun getParent() = parent
@@ -23,6 +23,7 @@ import com.intellij.psi.PsiReferenceList
import com.intellij.psi.PsiReferenceList.Role
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.KtSuperTypeList
import org.jetbrains.kotlin.psi.KtSuperTypeListEntry
@@ -40,9 +41,9 @@ class KtLightPsiReferenceList (
override fun getName() = null
override fun setName(name: String) = throw UnsupportedOperationException()
override val kotlinOrigin by lazy(LazyThreadSafetyMode.PUBLICATION) {
val superTypeList = this@KtLightPsiReferenceList.kotlinOrigin ?: return@lazy null
val fqNameToFind = clsDelegate.qualifiedName ?: return@lazy null
override val kotlinOrigin by lazyPub {
val superTypeList = this@KtLightPsiReferenceList.kotlinOrigin ?: return@lazyPub null
val fqNameToFind = clsDelegate.qualifiedName ?: return@lazyPub null
val context = LightClassGenerationSupport.getInstance(project).analyze(superTypeList)
superTypeList.entries.firstOrNull {
val referencedType = context[BindingContext.TYPE, it.typeReference]
@@ -64,7 +65,7 @@ class KtLightPsiReferenceList (
override val kotlinOrigin: KtSuperTypeList?
get() = owner.kotlinOrigin?.getSuperTypeList()
private val _referenceElements by lazy(LazyThreadSafetyMode.PUBLICATION) {
private val _referenceElements by lazyPub {
clsDelegate.referenceElements.map { KtLightSuperTypeReference(it) }.toTypedArray()
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightFieldImpl
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.psi.KtClassOrObject
typealias LightClassBuilder = (LightClassConstructionContext) -> LightClassBuilderResult
@@ -36,11 +37,11 @@ class LazyLightClassDataHolder(
dummyContextProvider: LightClassContextProvider?
) : LightClassDataHolder {
private val exactResultLazyValue = lazy(LazyThreadSafetyMode.PUBLICATION) { builder(exactContextProvider()) }
private val exactResultLazyValue = lazyPub { builder(exactContextProvider()) }
private val exactResult: LightClassBuilderResult by exactResultLazyValue
private val lazyInexactResult by lazy(LazyThreadSafetyMode.PUBLICATION) {
private val lazyInexactResult by lazyPub {
dummyContextProvider?.let { builder.invoke(it()) }
}
@@ -65,9 +66,9 @@ class LazyLightClassDataHolder(
private val relyOnDummySupertypes: Boolean,
findDelegate: (LightClassBuilderResult) -> PsiClass
) : LightClassData {
override val clsDelegate: PsiClass by lazy(LazyThreadSafetyMode.PUBLICATION) { findDelegate(exactResult) }
override val clsDelegate: PsiClass by lazyPub { findDelegate(exactResult) }
private val dummyDelegate: PsiClass? by lazy(LazyThreadSafetyMode.PUBLICATION) { inexactResult?.let(findDelegate) }
private val dummyDelegate: PsiClass? by lazyPub { inexactResult?.let(findDelegate) }
override fun getOwnFields(containingClass: KtLightClass): List<KtLightField> {
if (dummyDelegate == null) return clsDelegate.fields.map { KtLightFieldImpl.fromClsField(it, containingClass) }
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiField
import com.intellij.psi.PsiMember
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -51,7 +52,7 @@ data class LightMemberOriginForCompiledField(val psiField: PsiField, val file: K
return LightMemberOriginForCompiledField(psiField.copy() as PsiField, file)
}
override val originalElement: KtDeclaration? by lazy(LazyThreadSafetyMode.PUBLICATION) {
override val originalElement: KtDeclaration? by lazyPub {
val desc = MapPsiToAsmDesc.typeDesc(psiField.type)
val signature = MemberSignature.fromFieldNameAndDesc(psiField.name!!, desc)
findDeclarationInCompiledFile(file, psiField, signature)
@@ -63,7 +64,7 @@ data class LightMemberOriginForCompiledMethod(val psiMethod: PsiMethod, val file
return LightMemberOriginForCompiledMethod(psiMethod.copy() as PsiMethod, file)
}
override val originalElement: KtDeclaration? by lazy(LazyThreadSafetyMode.PUBLICATION) {
override val originalElement: KtDeclaration? by lazyPub {
val desc = MapPsiToAsmDesc.methodDesc(psiMethod)
val signature = MemberSignature.fromMethodNameAndDesc(psiMethod.name, desc)
findDeclarationInCompiledFile(file, psiMethod, signature)