diff --git a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledDeclaration.kt b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledDeclaration.kt index 57fe5173fce..c59a9a7407e 100644 --- a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledDeclaration.kt +++ b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledDeclaration.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -18,8 +18,7 @@ import org.jetbrains.kotlin.analysis.decompiled.light.classes.origin.LightMember import org.jetbrains.kotlin.analysis.decompiled.light.classes.origin.LightMemberOriginForCompiledMethod import org.jetbrains.kotlin.analysis.decompiler.psi.file.KtClsFile import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService -import org.jetbrains.kotlin.asJava.classes.KotlinClassInnerStuffCache -import org.jetbrains.kotlin.asJava.classes.LightClassesLazyCreator +import org.jetbrains.kotlin.asJava.classes.ClassInnerStuffCache import org.jetbrains.kotlin.asJava.classes.getEnumEntriesPsiMethod import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.isGetEntriesMethod @@ -29,36 +28,37 @@ import org.jetbrains.kotlin.psi.KtClassOrObject open class KtLightClassForDecompiledDeclaration( clsDelegate: PsiClass, - private val clsParent: PsiElement, - private val file: KtClsFile, + clsParent: PsiElement, + protected val file: KtClsFile, kotlinOrigin: KtClassOrObject? ) : KtLightClassForDecompiledDeclarationBase(clsDelegate, clsParent, kotlinOrigin) { + private val myInnersCache by lazyPub { + ClassInnerStuffCache( + /* aClass = */ this, + /* generateEnumMethods = */ true, + /* modificationTracker = */ KotlinModificationTrackerService.getInstance(manager.project).outOfBlockModificationTracker, + ) + } - private val myInnersCache = KotlinClassInnerStuffCache( - myClass = this, - dependencies = listOf(KotlinModificationTrackerService.getInstance(manager.project).outOfBlockModificationTracker), - lazyCreator = LightClassesLazyCreator(project) - ) + override fun getOwnMethods(): List = _methods - override fun getOwnMethods(): MutableList = _methods + override fun getOwnFields(): List = _fields - override fun getOwnFields(): MutableList = _fields + override fun getOwnInnerClasses(): List = _innerClasses - override fun getOwnInnerClasses(): MutableList = _innerClasses + override fun getFields(): Array = myInnersCache.fields - override fun getFields() = myInnersCache.fields + override fun getMethods(): Array = myInnersCache.methods - override fun getMethods() = myInnersCache.methods + override fun getConstructors(): Array = myInnersCache.constructors - override fun getConstructors() = myInnersCache.constructors + override fun getInnerClasses(): Array = myInnersCache.innerClasses - override fun getInnerClasses() = myInnersCache.innerClasses + override fun findFieldByName(name: String, checkBases: Boolean): PsiField? = myInnersCache.findFieldByName(name, checkBases) - override fun findFieldByName(name: String, checkBases: Boolean) = myInnersCache.findFieldByName(name, checkBases) + override fun findMethodsByName(name: String, checkBases: Boolean): Array = myInnersCache.findMethodsByName(name, checkBases) - override fun findMethodsByName(name: String, checkBases: Boolean) = myInnersCache.findMethodsByName(name, checkBases) - - override fun findInnerClassByName(name: String, checkBases: Boolean) = myInnersCache.findInnerClassByName(name, checkBases) + override fun findInnerClassByName(name: String, checkBases: Boolean): PsiClass? = myInnersCache.findInnerClassByName(name, checkBases) override fun hasModifierProperty(name: String): Boolean = clsDelegate.hasModifierProperty(name) @@ -82,15 +82,15 @@ open class KtLightClassForDecompiledDeclaration( override fun getContainingClass(): PsiClass? = parent as? PsiClass - override fun isInheritorDeep(baseClass: PsiClass?, classToByPass: PsiClass?): Boolean = clsDelegate.isInheritorDeep(baseClass, classToByPass) + override fun isInheritorDeep(baseClass: PsiClass?, classToByPass: PsiClass?): Boolean = + clsDelegate.isInheritorDeep(baseClass, classToByPass) override fun getAllMethodsAndTheirSubstitutors(): List?> = PsiClassImplUtil.getAllWithSubstitutorsByMap(this, PsiClassImplUtil.MemberType.METHOD) override fun isInterface(): Boolean = clsDelegate.isInterface - override fun getTypeParameters(): Array = - clsDelegate.typeParameters + override fun getTypeParameters(): Array = clsDelegate.typeParameters override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean = clsDelegate.isInheritor(baseClass, checkDeep) @@ -159,59 +159,54 @@ open class KtLightClassForDecompiledDeclaration( override fun getAllFields(): Array = PsiClassImplUtil.getAllFields(this) - private val _methods: MutableList by lazyPub { - mutableListOf().also { - val isEnum = isEnum - clsDelegate.methods.mapNotNullTo(it) { psiMethod -> - if (isSyntheticValuesOrValueOfMethod(psiMethod)) return@mapNotNullTo null - if (isEnum && isGetEntriesMethod(psiMethod)) { - return@mapNotNullTo getEnumEntriesPsiMethod(this) - } - KtLightMethodForDecompiledDeclaration( - funDelegate = psiMethod, - funParent = this, - lightMemberOrigin = LightMemberOriginForCompiledMethod(psiMethod, file) + private val _methods: List by lazyPub { + val isEnum = isEnum + this.clsDelegate.methods.mapNotNull { psiMethod -> + if (isSyntheticValuesOrValueOfMethod(psiMethod)) return@mapNotNull null + if (isEnum && isGetEntriesMethod(psiMethod)) { + return@mapNotNull getEnumEntriesPsiMethod(this) + } + + KtLightMethodForDecompiledDeclaration( + funDelegate = psiMethod, + funParent = this, + lightMemberOrigin = LightMemberOriginForCompiledMethod(psiMethod, file) + ) + } + } + + private val _fields: List by lazyPub { + this.clsDelegate.fields.map { psiField -> + if (psiField !is PsiEnumConstant) { + KtLightFieldForDecompiledDeclaration( + fldDelegate = psiField, + fldParent = this, + lightMemberOrigin = LightMemberOriginForCompiledField(psiField, file) + ) + } else { + KtLightEnumEntryForDecompiledDeclaration( + fldDelegate = psiField, + fldParent = this, + lightMemberOrigin = LightMemberOriginForCompiledField(psiField, file), + file = file ) } } } - private val _fields: MutableList by lazyPub { - mutableListOf().also { - clsDelegate.fields.mapTo(it) { psiField -> - if (psiField !is PsiEnumConstant) { - KtLightFieldForDecompiledDeclaration( - fldDelegate = psiField, - fldParent = this, - lightMemberOrigin = LightMemberOriginForCompiledField(psiField, file) - ) - } else { - KtLightEnumEntryForDecompiledDeclaration( - fldDelegate = psiField, - fldParent = this, - lightMemberOrigin = LightMemberOriginForCompiledField(psiField, file), - file = file - ) - } - } - } - } + private val _innerClasses: List by lazyPub { + this.clsDelegate.innerClasses.map { psiClass -> + val innerDeclaration = this.kotlinOrigin + ?.declarations + ?.filterIsInstance() + ?.firstOrNull { cls -> cls.name == this.clsDelegate.name } - private val _innerClasses: MutableList by lazyPub { - mutableListOf().also { - clsDelegate.innerClasses.mapTo(it) { psiClass -> - val innerDeclaration = kotlinOrigin - ?.declarations - ?.filterIsInstance() - ?.firstOrNull { cls -> cls.name == clsDelegate.name } - - KtLightClassForDecompiledDeclaration( - clsDelegate = psiClass, - clsParent = this, - file = file, - kotlinOrigin = innerDeclaration, - ) - } + KtLightClassForDecompiledDeclaration( + clsDelegate = psiClass, + clsParent = this, + file = file, + kotlinOrigin = innerDeclaration, + ) } } diff --git a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledFacade.kt b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledFacade.kt index ea59888034c..b01df47036b 100644 --- a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledFacade.kt +++ b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightClassForDecompiledFacade.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -23,8 +23,6 @@ internal class KtLightClassForDecompiledFacade( override val files: Collection, ) : KtLightClassForDecompiledDeclaration(clsDelegate, clsParent, file, kotlinOrigin), KtLightClassForFacade { override fun getName(): String = super.getName() - - override val facadeClassFqName: FqName = file.javaFileFacadeFqName - + override val facadeClassFqName: FqName get() = file.javaFileFacadeFqName override val originKind: LightClassOriginKind get() = LightClassOriginKind.BINARY } \ No newline at end of file diff --git a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightEnumClassForDecompiledDeclaration.kt b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightEnumClassForDecompiledDeclaration.kt index 2666479fae6..50060ffbad6 100644 --- a/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightEnumClassForDecompiledDeclaration.kt +++ b/analysis/decompiled/light-classes-for-decompiled/src/org/jetbrains/kotlin/analysis/decompiled/light/classes/KtLightEnumClassForDecompiledDeclaration.kt @@ -1,4 +1,7 @@ -// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ package org.jetbrains.kotlin.analysis.decompiled.light.classes @@ -12,14 +15,12 @@ internal class KtLightEnumClassForDecompiledDeclaration( clsParent: KtLightClassForDecompiledDeclaration, file: KtClsFile, kotlinOrigin: KtClassOrObject? -) : - KtLightClassForDecompiledDeclaration( - clsDelegate = psiConstantInitializer, - clsParent = clsParent, - file = file, - kotlinOrigin = kotlinOrigin - ), PsiEnumConstantInitializer { - +) : KtLightClassForDecompiledDeclaration( + clsDelegate = psiConstantInitializer, + clsParent = clsParent, + file = file, + kotlinOrigin = kotlinOrigin +), PsiEnumConstantInitializer { override fun getBaseClassType(): PsiClassType = psiConstantInitializer.baseClassType override fun getArgumentList(): PsiExpressionList? = psiConstantInitializer.argumentList diff --git a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/ClassInnerStuffCache.java b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/ClassInnerStuffCache.java index c4d1c07c110..fd1bad803c2 100644 --- a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/ClassInnerStuffCache.java +++ b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/ClassInnerStuffCache.java @@ -6,21 +6,22 @@ package org.jetbrains.kotlin.asJava.classes; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.ModificationTracker; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.augment.PsiAugmentProvider; import com.intellij.psi.impl.PsiClassImplUtil; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.impl.PsiSuperMethodImplUtil; import com.intellij.psi.impl.light.*; -import com.intellij.psi.impl.source.PsiExtensibleClass; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; -import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ConcurrentFactoryMap; @@ -30,6 +31,11 @@ import com.intellij.util.containers.JBIterable; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin; +import org.jetbrains.kotlin.asJava.elements.KtLightMethod; +import org.jetbrains.kotlin.asJava.elements.KtLightParameter; +import org.jetbrains.kotlin.psi.KtDeclaration; +import org.jetbrains.kotlin.psi.KtParameter; import java.util.*; @@ -41,31 +47,65 @@ import static com.intellij.util.ObjectUtils.notNull; * @see com.intellij.psi.impl.source.ClassInnerStuffCache */ public final class ClassInnerStuffCache { - private final PsiExtensibleClass myClass; - private final Ref>> myInterner = Ref.create(); + public static final String NOT_NULL_ANNOTATION_QUALIFIER = "@" + NotNull.class.getName(); - public ClassInnerStuffCache(@NotNull PsiExtensibleClass aClass) { + private final @NotNull KtExtensibleLightClass myClass; + private final @NotNull ModificationTracker myModificationTracker; + private final @NotNull Ref>> myInterner = Ref.create(); + private final boolean myGenerateEnumMethods; + + public ClassInnerStuffCache( + @NotNull KtExtensibleLightClass aClass, + boolean generateEnumMethods, + @NotNull ModificationTracker modificationTracker + ) { + myGenerateEnumMethods = generateEnumMethods; myClass = aClass; + myModificationTracker = modificationTracker; } - public PsiMethod @NotNull [] getConstructors() { - return copy(CachedValuesManager.getProjectPsiDependentCache(myClass, PsiImplUtil::getConstructors)); + @NotNull + public PsiMethod[] getConstructors() { + return copy(CachedValuesManager.getCachedValue( + myClass, + () -> CachedValueProvider.Result.createSingleDependency( + PsiImplUtil.getConstructors(myClass), + myModificationTracker + ) + )); } - public PsiField @NotNull [] getFields() { - return copy(CachedValuesManager.getProjectPsiDependentCache(myClass, __ -> calcFields())); + @NotNull + public PsiField[] getFields() { + return copy(CachedValuesManager.getCachedValue( + myClass, + () -> CachedValueProvider.Result.createSingleDependency( + calcFields(), + myModificationTracker + ) + )); } - public PsiMethod @NotNull [] getMethods() { - return copy(CachedValuesManager.getProjectPsiDependentCache(myClass, __ -> calcMethods())); + @NotNull + public PsiMethod[] getMethods() { + return copy(CachedValuesManager.getCachedValue( + myClass, + () -> CachedValueProvider.Result.createSingleDependency( + calcMethods(), + myModificationTracker + ) + )); } - public PsiClass @NotNull [] getInnerClasses() { - return copy(CachedValuesManager.getProjectPsiDependentCache(myClass, __ -> calcInnerClasses())); - } - - public PsiRecordComponent @NotNull [] getRecordComponents() { - return copy(CachedValuesManager.getProjectPsiDependentCache(myClass, __ -> calcRecordComponents())); + @NotNull + public PsiClass[] getInnerClasses() { + return copy(CachedValuesManager.getCachedValue( + myClass, + () -> CachedValueProvider.Result.createSingleDependency( + calcInnerClasses(), + myModificationTracker + ) + )); } @Nullable @@ -74,16 +114,29 @@ public final class ClassInnerStuffCache { return PsiClassImplUtil.findFieldByName(myClass, name, true); } else { - return CachedValuesManager.getProjectPsiDependentCache(myClass, __ -> getFieldsMap()).get(name); + return CachedValuesManager.getCachedValue( + myClass, + () -> CachedValueProvider.Result.createSingleDependency( + getFieldsMap(), + myModificationTracker + ) + ).get(name); } } - public PsiMethod @NotNull [] findMethodsByName(String name, boolean checkBases) { + @NotNull + public PsiMethod[] findMethodsByName(String name, boolean checkBases) { if (checkBases) { return PsiClassImplUtil.findMethodsByName(myClass, name, true); } else { - return copy(notNull(CachedValuesManager.getProjectPsiDependentCache(myClass, __ -> getMethodsMap()).get(name), PsiMethod.EMPTY_ARRAY)); + return copy(notNull(CachedValuesManager.getCachedValue( + myClass, + () -> CachedValueProvider.Result.createSingleDependency( + getMethodsMap(), + myModificationTracker + ) + ).get(name), PsiMethod.EMPTY_ARRAY)); } } @@ -93,37 +146,48 @@ public final class ClassInnerStuffCache { return PsiClassImplUtil.findInnerByName(myClass, name, true); } else { - return CachedValuesManager.getProjectPsiDependentCache(myClass, __ -> getInnerClassesMap()).get(name); + return CachedValuesManager.getCachedValue( + myClass, + () -> CachedValueProvider.Result.createSingleDependency( + getInnerClassesMap(), + myModificationTracker + ) + ).get(name); } } @Nullable - PsiMethod getValuesMethod() { - return myClass.isEnum() && !isAnonymousClass() && !classNameIsSealed() - ? internMember(CachedValuesManager.getProjectPsiDependentCache(myClass, ClassInnerStuffCache::makeValuesMethod)) - : null; - } - - private boolean classNameIsSealed() { - return PsiKeyword.SEALED.equals(myClass.getName()) && PsiUtil.getLanguageLevel(myClass).isAtLeast(LanguageLevel.JDK_17); + private PsiMethod getValuesMethod() { + return isEnum() ? internMember(CachedValuesManager.getCachedValue( + myClass, + () -> CachedValueProvider.Result.createSingleDependency( + makeValuesMethod(myClass), + myModificationTracker + ) + )) : null; } @Nullable private PsiMethod getValueOfMethod() { - return myClass.isEnum() && !isAnonymousClass() - ? internMember(CachedValuesManager.getProjectPsiDependentCache(myClass, ClassInnerStuffCache::makeValueOfMethod)) - : null; + return isEnum() ? internMember(CachedValuesManager.getCachedValue( + myClass, + () -> CachedValueProvider.Result.createSingleDependency( + makeValueOfMethod(myClass), + myModificationTracker + ) + )) : null; } - private boolean isAnonymousClass() { - return myClass.getName() == null || myClass instanceof PsiAnonymousClass; + private boolean isEnum() { + return myGenerateEnumMethods && myClass.isEnum(); } private static T[] copy(T[] value) { return value.length == 0 ? value : value.clone(); } - private PsiField @NotNull [] calcFields() { + @NotNull + private PsiField[] calcFields() { List own = myClass.getOwnFields(); List ext = internMembers(PsiAugmentProvider.collectAugments(myClass, PsiField.class, null)); return ArrayUtil.mergeCollections(own, ext, PsiField.ARRAY_FACTORY); @@ -134,23 +198,25 @@ public final class ClassInnerStuffCache { return ContainerUtil.map(members, this::internMember); } + @SuppressWarnings("unchecked") private T internMember(T m) { if (m == null) return null; - long modCount = myClass.getManager().getModificationTracker().getModificationCount(); + long modCount = myModificationTracker.getModificationCount(); synchronized (myInterner) { Pair> pair = myInterner.get(); if (pair == null || pair.first.longValue() != modCount) { myInterner.set(pair = Pair.create(modCount, Interner.createWeakInterner())); } - //noinspection unchecked + return (T) pair.second.intern(m); } } - private PsiMethod @NotNull [] calcMethods() { + @NotNull + private PsiMethod[] calcMethods() { List own = myClass.getOwnMethods(); List ext = internMembers(PsiAugmentProvider.collectAugments(myClass, PsiMethod.class, null)); - if (myGenerateEnumMethods && myClass.isEnum()) { + if (isEnum()) { ext = new ArrayList<>(ext); ContainerUtil.addIfNotNull(ext, getValuesMethod()); ContainerUtil.addIfNotNull(ext, getValueOfMethod()); @@ -158,26 +224,21 @@ public final class ClassInnerStuffCache { return ArrayUtil.mergeCollections(own, ext, PsiMethod.ARRAY_FACTORY); } - private PsiClass @NotNull [] calcInnerClasses() { + @NotNull + private PsiClass[] calcInnerClasses() { List own = myClass.getOwnInnerClasses(); List ext = internMembers(PsiAugmentProvider.collectAugments(myClass, PsiClass.class, null)); return ArrayUtil.mergeCollections(own, ext, PsiClass.ARRAY_FACTORY); } - private PsiRecordComponent @NotNull [] calcRecordComponents() { - PsiRecordHeader header = myClass.getRecordHeader(); - return header == null ? PsiRecordComponent.EMPTY_ARRAY : header.getRecordComponents(); - } - @NotNull private Map getFieldsMap() { Map cachedFields = new HashMap<>(); for (PsiField field : myClass.getOwnFields()) { String name = field.getName(); - if (!cachedFields.containsKey(name)) { - cachedFields.put(name, field); - } + cachedFields.putIfAbsent(name, field); } + return ConcurrentFactoryMap.createMap(name -> { PsiField result = cachedFields.get(name); return result != null ? result : @@ -188,14 +249,13 @@ public final class ClassInnerStuffCache { @NotNull private Map getMethodsMap() { List ownMethods = myClass.getOwnMethods(); - return ConcurrentFactoryMap.createMap(name -> { - return JBIterable - .from(ownMethods).filter(m -> name.equals(m.getName())) - .append("values".equals(name) ? getValuesMethod() : null) - .append("valueOf".equals(name) ? getValueOfMethod() : null) - .append(internMembers(PsiAugmentProvider.collectAugments(myClass, PsiMethod.class, name))) - .toArray(PsiMethod.EMPTY_ARRAY); - }); + return ConcurrentFactoryMap.createMap(name -> JBIterable + .from(ownMethods) + .filter(m -> name.equals(m.getName())) + .append("values".equals(name) ? getValuesMethod() : null) + .append("valueOf".equals(name) ? getValueOfMethod() : null) + .append(internMembers(PsiAugmentProvider.collectAugments(myClass, PsiMethod.class, name))) + .toArray(PsiMethod.EMPTY_ARRAY)); } @NotNull @@ -210,18 +270,20 @@ public final class ClassInnerStuffCache { cachedInners.put(name, psiClass); } } + return ConcurrentFactoryMap.createMap(name -> { PsiClass result = cachedInners.get(name); - return result != null ? result : - internMember(ContainerUtil.getFirstItem(PsiAugmentProvider.collectAugments(myClass, PsiClass.class, name))); + return result != null + ? result + : internMember(ContainerUtil.getFirstItem(PsiAugmentProvider.collectAugments(myClass, PsiClass.class, name))); }); } - private static PsiMethod makeValuesMethod(PsiExtensibleClass enumClass) { + private static PsiMethod makeValuesMethod(KtExtensibleLightClass enumClass) { return new EnumSyntheticMethod(enumClass, EnumMethodKind.Values); } - private static PsiMethod makeValueOfMethod(PsiExtensibleClass enumClass) { + private static PsiMethod makeValueOfMethod(KtExtensibleLightClass enumClass) { return new EnumSyntheticMethod(enumClass, EnumMethodKind.ValueOf); } @@ -230,14 +292,14 @@ public final class ClassInnerStuffCache { Values, } - private static class EnumSyntheticMethod extends LightElement implements PsiMethod, SyntheticElement { - private final PsiClass myClass; + private static class EnumSyntheticMethod extends LightElement implements PsiMethod, SyntheticElement, KtLightMethod { + private final KtExtensibleLightClass myClass; private final EnumMethodKind myKind; private final PsiType myReturnType; private final LightParameterListBuilder myParameterList; private final LightModifierList myModifierList; - EnumSyntheticMethod(@NotNull PsiClass enumClass, EnumMethodKind kind) { + EnumSyntheticMethod(@NotNull KtExtensibleLightClass enumClass, EnumMethodKind kind) { super(enumClass.getManager(), enumClass.getLanguage()); myClass = enumClass; myKind = kind; @@ -256,6 +318,12 @@ public final class ClassInnerStuffCache { } } + private @NotNull PsiAnnotation[] createNotNullAnnotation() { + return new PsiAnnotation[] { + PsiElementFactory.getInstance(getProject()).createAnnotationFromText(NOT_NULL_ANNOTATION_QUALIFIER, myClass) + }; + } + private @NotNull PsiType createReturnType() { PsiClassType type = JavaPsiFacade.getElementFactory(getProject()).createType(myClass); if (myKind == EnumMethodKind.Values) { @@ -267,6 +335,20 @@ public final class ClassInnerStuffCache { @NotNull private LightModifierList createModifierList() { return new LightModifierList(myManager, getLanguage(), PsiModifier.PUBLIC, PsiModifier.STATIC) { + private final PsiAnnotation[] notNullAnnotations = createNotNullAnnotation(); + + @Override + @NotNull + public PsiAnnotation[] getAnnotations() { + return ClassInnerStuffCache.copy(notNullAnnotations); + } + + @Override + public PsiAnnotation findAnnotation(@NotNull String qualifiedName) { + PsiAnnotation notNullAnnotation = notNullAnnotations[0]; + return qualifiedName == notNullAnnotation.getQualifiedName() ? notNullAnnotation : null; + } + @Override public PsiElement getParent() { return EnumSyntheticMethod.this; @@ -279,12 +361,54 @@ public final class ClassInnerStuffCache { LightParameterListBuilder parameters = new LightParameterListBuilder(myManager, getLanguage()); if (myKind == EnumMethodKind.ValueOf) { PsiClassType string = PsiType.getJavaLangString(myManager, GlobalSearchScope.allScope(getProject())); - LightParameter parameter = new LightParameter("name", string, this, getLanguage(), false); + LightParameter parameter = new MyKtLightParameter(string, this); parameters.addParameter(parameter); } + return parameters; } + private static final class MyKtLightParameter extends LightParameter implements KtLightParameter { + private final @NotNull KtLightMethod myMethod; + + MyKtLightParameter(@NotNull PsiType type, @NotNull KtLightMethod declarationScope) { + super("name", type, declarationScope, declarationScope.getLanguage(), false); + myMethod = declarationScope; + } + + @Nullable + @Override + public KtParameter getKotlinOrigin() { + return null; + } + + @NotNull + @Override + public KtLightMethod getMethod() { + return myMethod; + } + + @Override + public PsiElement getParent() { + return myMethod; + } + + @Override + public PsiFile getContainingFile() { + return myMethod.getContainingFile(); + } + + @Override + public String getText() { + return getName(); + } + + @Override + public TextRange getTextRange() { + return TextRange.EMPTY_RANGE; + } + } + @Override public int getTextOffset() { return myClass.getTextOffset(); @@ -292,7 +416,17 @@ public final class ClassInnerStuffCache { @Override public String toString() { - return null; + return myClass.getText(); + } + + @Override + public String getText() { + return ""; + } + + @Override + public TextRange getTextRange() { + return TextRange.EMPTY_RANGE; } @Override @@ -319,7 +453,7 @@ public final class ClassInnerStuffCache { } @Override - public @Nullable PsiClass getContainingClass() { + public @NotNull KtExtensibleLightClass getContainingClass() { return myClass; } @@ -340,9 +474,15 @@ public final class ClassInnerStuffCache { @Override public @NotNull PsiReferenceList getThrowsList() { - LightReferenceListBuilder throwsList = new LightReferenceListBuilder(myManager, getLanguage(), PsiReferenceList.Role.THROWS_LIST); + LightReferenceListBuilder throwsList = new LightReferenceListBuilder( + myManager, + getLanguage(), + PsiReferenceList.Role.THROWS_LIST + ); + if (myKind == EnumMethodKind.ValueOf) { - throwsList.addReference("java.lang.IllegalArgumentException"); + throwsList.addReference(IllegalArgumentException.class.getName()); + throwsList.addReference(NullPointerException.class.getName()); } return throwsList; @@ -382,17 +522,20 @@ public final class ClassInnerStuffCache { } @Override - public PsiMethod @NotNull [] findSuperMethods() { + @NotNull + public PsiMethod[] findSuperMethods() { return PsiSuperMethodImplUtil.findSuperMethods(this); } @Override - public PsiMethod @NotNull [] findSuperMethods(boolean checkAccess) { + @NotNull + public PsiMethod[] findSuperMethods(boolean checkAccess) { return PsiSuperMethodImplUtil.findSuperMethods(this, checkAccess); } @Override - public PsiMethod @NotNull [] findSuperMethods(PsiClass parentClass) { + @NotNull + public PsiMethod[] findSuperMethods(PsiClass parentClass) { return PsiSuperMethodImplUtil.findSuperMethods(this, parentClass); } @@ -402,12 +545,14 @@ public final class ClassInnerStuffCache { } @Override + @Deprecated public @Nullable PsiMethod findDeepestSuperMethod() { return PsiSuperMethodImplUtil.findDeepestSuperMethod(this); } @Override - public PsiMethod @NotNull [] findDeepestSuperMethods() { + @NotNull + public PsiMethod[] findDeepestSuperMethods() { return PsiMethod.EMPTY_ARRAY; } @@ -431,6 +576,11 @@ public final class ClassInnerStuffCache { return PsiSuperMethodImplUtil.getHierarchicalMethodSignature(this); } + @Override + public @Nullable PsiAnnotationMemberValue getDefaultValue() { + return null; + } + @Override public boolean hasTypeParameters() { return false; @@ -447,8 +597,26 @@ public final class ClassInnerStuffCache { } @Override - public PsiTypeParameter @NotNull [] getTypeParameters() { + @NotNull + public PsiTypeParameter[] getTypeParameters() { return PsiTypeParameter.EMPTY_ARRAY; } + + @Override + public boolean isMangled() { + return false; + } + + @Nullable + @Override + public KtDeclaration getKotlinOrigin() { + return null; + } + + @Nullable + @Override + public LightMemberOrigin getLightMemberOrigin() { + return null; + } } } \ No newline at end of file diff --git a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KotlinClassInnerStuffCache.kt b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KotlinClassInnerStuffCache.kt index 7295ae69bcd..4dddbd0c049 100644 --- a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KotlinClassInnerStuffCache.kt +++ b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/KotlinClassInnerStuffCache.kt @@ -14,11 +14,12 @@ import com.intellij.psi.impl.PsiSuperMethodImplUtil import com.intellij.psi.impl.light.* import com.intellij.psi.javadoc.PsiDocComment import com.intellij.psi.search.GlobalSearchScope -import com.intellij.psi.util.* +import com.intellij.psi.util.MethodSignature +import com.intellij.psi.util.MethodSignatureBackedByPsiMethod +import com.intellij.psi.util.PsiUtil import com.intellij.util.ArrayUtil import com.intellij.util.IncorrectOperationException import gnu.trove.THashMap -import org.jetbrains.annotations.NotNull import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.elements.KtLightParameter @@ -288,7 +289,10 @@ private class KotlinEnumSyntheticMethod( private companion object { private fun makeNotNullAnnotation(context: PsiClass): PsiAnnotation { - return PsiElementFactory.getInstance(context.project).createAnnotationFromText("@" + NotNull::class.java.name, context) + return PsiElementFactory.getInstance(context.project).createAnnotationFromText( + ClassInnerStuffCache.NOT_NULL_ANNOTATION_QUALIFIER, + context, + ) } } } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassBase.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassBase.kt index 182b67ba0f2..961e1a2b437 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassBase.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassBase.kt @@ -7,15 +7,16 @@ package org.jetbrains.kotlin.light.classes.symbol.classes import com.intellij.navigation.ItemPresentation import com.intellij.navigation.ItemPresentationProviders -import com.intellij.openapi.project.Project import com.intellij.openapi.util.Pair import com.intellij.openapi.util.TextRange import com.intellij.psi.* -import com.intellij.psi.impl.* +import com.intellij.psi.impl.InheritanceImplUtil +import com.intellij.psi.impl.PsiClassImplUtil +import com.intellij.psi.impl.PsiImplUtil +import com.intellij.psi.impl.PsiSuperMethodImplUtil import com.intellij.psi.impl.light.LightElement import com.intellij.psi.javadoc.PsiDocComment import com.intellij.psi.scope.PsiScopeProcessor -import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.PsiUtil import org.jetbrains.annotations.NonNls import org.jetbrains.kotlin.analysis.project.structure.KtModule @@ -33,30 +34,15 @@ import javax.swing.Icon abstract class SymbolLightClassBase protected constructor(val ktModule: KtModule, manager: PsiManager) : LightElement(manager, KotlinLanguage.INSTANCE), PsiClass, KtExtensibleLightClass { - private class SymbolLightClassesLazyCreator(private val project: Project) : KotlinClassInnerStuffCache.LazyCreator() { - override fun get(initializer: () -> T, dependencies: List): Lazy = object : Lazy { - private val cachedValue = PsiCachedValueImpl(PsiManager.getInstance(project)) { - CachedValueProvider.Result.create(initializer(), dependencies) - } - override val value: T get() = cachedValue.value ?: error("Unexpected null value from PsiCachedValueImpl") - - override fun isInitialized(): Boolean { - // Lazy is a bad interface here as it has unneeded and unused in LC `isInitialized` method - // considering Interface Segregation Principle, Lazy should be repaced with a simpler interface with only `value` method - error("Should not be called for LC") - } - } + private val myInnersCache by lazyPub { + ClassInnerStuffCache( + /* aClass = */ this, + /* generateEnumMethods = */ false, + /* modificationTracker = */ project.createProjectWideOutOfBlockModificationTracker(), + ) } - @Suppress("LeakingThis") - private val myInnersCache = KotlinClassInnerStuffCache( - myClass = this@SymbolLightClassBase, - dependencies = listOf(manager.project.createProjectWideOutOfBlockModificationTracker()), - lazyCreator = SymbolLightClassesLazyCreator(project), - generateEnumMethods = false, - ) - override fun getFields(): Array = myInnersCache.fields override fun getMethods(): Array = myInnersCache.methods