diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassUtil.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassUtil.kt index d37a0936a4d..e04d5b2b224 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassUtil.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassUtil.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.asJava import com.intellij.openapi.progress.ProcessCanceledException -import com.intellij.openapi.util.Comparing import com.intellij.psi.* import com.intellij.psi.impl.java.stubs.PsiClassStub import com.intellij.psi.search.GlobalSearchScope @@ -30,26 +29,24 @@ import org.jetbrains.kotlin.asJava.elements.* import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName import org.jetbrains.kotlin.load.java.JvmAbi -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType object LightClassUtil { - fun findClass(fqn: FqName, stub: StubElement<*>): PsiClass? { - if (stub is PsiClassStub<*> && Comparing.equal(fqn.asString(), stub.qualifiedName)) { + fun findClass(stub: StubElement<*>, predicate: (PsiClassStub<*>) -> Boolean): PsiClass? { + if (stub is PsiClassStub<*> && predicate(stub)) { return stub.getPsi() } if (stub is PsiClassStub<*> || stub is PsiFileStub<*>) { for (child in stub.childrenStubs) { - val answer = findClass(fqn, child) + val answer = findClass(child, predicate) if (answer != null) return answer } } - return null - }/*package*/ + } fun getLightClassAccessorMethod(accessor: KtPropertyAccessor): PsiMethod? = getLightClassAccessorMethods(accessor).firstOrNull() diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/ClsWrapperStubPsiFactory.java b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/ClsWrapperStubPsiFactory.java index dde58ba3eb4..17051f68106 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/ClsWrapperStubPsiFactory.java +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/ClsWrapperStubPsiFactory.java @@ -73,7 +73,7 @@ public class ClsWrapperStubPsiFactory extends StubPsiFactory { } @Nullable - private static PsiElement getOriginalElement(@NotNull StubElement stub) { + public static PsiElement getOriginalElement(@NotNull StubElement stub) { LightElementOrigin origin = ((StubBase) stub).getUserData(ORIGIN); return origin != null ? origin.getOriginalElement() : null; } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForAnonymousDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForAnonymousDeclaration.kt index 8fff142e497..a3c495835e2 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForAnonymousDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForAnonymousDeclaration.kt @@ -21,13 +21,11 @@ import com.intellij.psi.* import com.intellij.psi.impl.InheritanceImplUtil import com.intellij.psi.search.GlobalSearchScope import com.intellij.reference.SoftReference -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.resolve.DescriptorUtils -internal open class KtLightClassForAnonymousDeclaration(fqNameFunction: ((KtClassOrObject) -> FqName), - classOrObject: KtClassOrObject) : - KtLightClassForLocalDeclaration(fqNameFunction, classOrObject), PsiAnonymousClass { +internal open class KtLightClassForAnonymousDeclaration(classOrObject: KtClassOrObject) : + KtLightClassForLocalDeclaration(classOrObject), PsiAnonymousClass { private var cachedBaseType: SoftReference? = null @@ -119,7 +117,7 @@ internal open class KtLightClassForAnonymousDeclaration(fqNameFunction: ((KtClas override fun getTypeParameterList() = null override fun isEnum() = false - override fun copy(): PsiElement = KtLightClassForAnonymousDeclaration(classFqNameFunction, classOrObject) + override fun copy(): PsiElement = KtLightClassForAnonymousDeclaration(classOrObject) companion object { private val LOG = Logger.getInstance(KtLightClassForAnonymousDeclaration::class.java) diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForEnumEntry.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForEnumEntry.kt index c3864e1f602..7f758eb5e7e 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForEnumEntry.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForEnumEntry.kt @@ -18,16 +18,14 @@ package org.jetbrains.kotlin.asJava.classes import com.intellij.psi.PsiEnumConstant import com.intellij.psi.PsiEnumConstantInitializer -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtEnumEntry internal class KtLightClassForEnumEntry( - fqName: FqName, enumEntry: KtEnumEntry, private val enumConstant: PsiEnumConstant -): KtLightClassForAnonymousDeclaration({ fqName }, enumEntry), PsiEnumConstantInitializer { +): KtLightClassForAnonymousDeclaration(enumEntry), PsiEnumConstantInitializer { override fun getEnumConstant(): PsiEnumConstant = enumConstant - override fun copy() = KtLightClassForEnumEntry(classFqName, classOrObject as KtEnumEntry, enumConstant) + override fun copy() = KtLightClassForEnumEntry(classOrObject as KtEnumEntry, enumConstant) override fun getParent() = enumConstant } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForFacade.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForFacade.kt index c2251a55b1c..8fd42294491 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForFacade.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForFacade.kt @@ -198,9 +198,9 @@ class KtLightClassForFacade private constructor( override val clsDelegate: PsiClass get() { - val psiClass = LightClassUtil.findClass(facadeClassFqName, lightClassDataCache.value.javaFileStub) - ?: throw IllegalStateException("Facade class $facadeClassFqName not found") - return psiClass + return LightClassUtil.findClass(lightClassDataCache.value.javaFileStub) { + facadeClassFqName.asString() == it.qualifiedName + } ?: throw IllegalStateException("Facade class $facadeClassFqName not found") } override fun getNavigationElement() = files.iterator().next() diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForInterfaceDefaultImpls.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForInterfaceDefaultImpls.kt index b6acf9eb5d2..9cffc3a4c31 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForInterfaceDefaultImpls.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForInterfaceDefaultImpls.kt @@ -17,21 +17,31 @@ package org.jetbrains.kotlin.asJava.classes import com.intellij.psi.* +import com.intellij.psi.impl.java.stubs.PsiJavaFileStub +import com.intellij.psi.stubs.StubElement import com.intellij.util.IncorrectOperationException -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.asJava.LightClassUtil +import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory +import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.psi.KtClassOrObject class KtLightClassForInterfaceDefaultImpls( - classFqName: FqName, classOrObject: KtClassOrObject) -: KtLightClassForSourceDeclaration({ classFqName }, classOrObject){ - override fun getQualifiedName(): String = classFqName.asString() +: KtLightClassForSourceDeclaration(classOrObject){ + override fun getQualifiedName(): String? = containingClass?.qualifiedName?.let { it + ".${JvmAbi.DEFAULT_IMPLS_CLASS_NAME}" } override fun getName() = JvmAbi.DEFAULT_IMPLS_CLASS_NAME override fun getParent() = containingClass override fun copy(): PsiElement { - return KtLightClassForInterfaceDefaultImpls(classFqName, classOrObject.copy() as KtClassOrObject) + return KtLightClassForInterfaceDefaultImpls(classOrObject.copy() as KtClassOrObject) + } + + override fun findDelegateClass(javaFileStub: PsiJavaFileStub): PsiClass? { + val interfaceClass = LightClassUtil.findClass(javaFileStub) { + ClsWrapperStubPsiFactory.getOriginalElement(it as StubElement<*>) == classOrObject + } + return interfaceClass?.findInnerClassByName(JvmAbi.DEFAULT_IMPLS_CLASS_NAME, false) } override fun getTypeParameterList(): PsiTypeParameterList? = null diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForLocalDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForLocalDeclaration.kt index 5cb08fe3c3d..236c9ee52a0 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForLocalDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForLocalDeclaration.kt @@ -24,16 +24,14 @@ import com.intellij.psi.impl.light.LightMethod import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType open class KtLightClassForLocalDeclaration( - classFqNameFunction: (KtClassOrObject) -> FqName, classOrObject: KtClassOrObject -) : KtLightClassForSourceDeclaration(classFqNameFunction, classOrObject) { +) : KtLightClassForSourceDeclaration(classOrObject) { - override fun copy(): PsiElement = KtLightClassForLocalDeclaration(classFqNameFunction, classOrObject.copy() as KtClassOrObject) + override fun copy(): PsiElement = KtLightClassForLocalDeclaration(classOrObject.copy() as KtClassOrObject) override fun getQualifiedName(): String? = null override fun getParent() = _parent diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt index 7daeed4cc22..8e20105c3fd 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassForSourceDeclaration.kt @@ -32,12 +32,19 @@ import com.intellij.psi.util.CachedValuesManager import com.intellij.util.IncorrectOperationException import com.intellij.util.containers.ContainerUtil import org.jetbrains.annotations.NonNls -import org.jetbrains.kotlin.asJava.* -import org.jetbrains.kotlin.asJava.builder.* +import org.jetbrains.kotlin.asJava.KtJavaMirrorMarker +import org.jetbrains.kotlin.asJava.LightClassGenerationSupport +import org.jetbrains.kotlin.asJava.LightClassUtil +import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory.getOriginalElement +import org.jetbrains.kotlin.asJava.builder.LightClassData +import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForClassOrObject +import org.jetbrains.kotlin.asJava.builder.OutermostKotlinClassLightClassData +import org.jetbrains.kotlin.asJava.builder.WithFileStubAndExtraDiagnostics import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass 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.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.lexer.KtTokens.* @@ -45,6 +52,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.debugText.getDebugText import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext import org.jetbrains.kotlin.psi.stubs.KotlinClassOrObjectStub import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -52,16 +60,10 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import java.util.* import javax.swing.Icon -abstract class KtLightClassForSourceDeclaration( - protected val classFqNameFunction: ((KtClassOrObject) -> FqName), - protected val classOrObject: KtClassOrObject) +abstract class KtLightClassForSourceDeclaration(protected val classOrObject: KtClassOrObject) : KtLightClassBase(classOrObject.manager), KtJavaMirrorMarker, StubBasedPsiElement> { private val lightIdentifier = KtLightIdentifier(this, classOrObject) - protected val classFqName : FqName by lazy(LazyThreadSafetyMode.PUBLICATION) { - classFqNameFunction(classOrObject) - } - private val _extendsList by lazy(LazyThreadSafetyMode.PUBLICATION) { val listDelegate = super.getExtendsList() ?: return@lazy null KtLightPsiReferenceList(listDelegate, this) @@ -81,7 +83,7 @@ abstract class KtLightClassForSourceDeclaration( override val clsDelegate: PsiClass by lazy(LazyThreadSafetyMode.PUBLICATION) { val javaFileStub = getJavaFileStub() - LightClassUtil.findClass(classFqName, javaFileStub) ?: run { + findDelegateClass(javaFileStub) ?: run { val outermostClassOrObject = getOutermostClassOrObject(classOrObject) val ktFileText: String? = try { outermostClassOrObject.containingFile.text @@ -91,7 +93,13 @@ abstract class KtLightClassForSourceDeclaration( } val stubFileText = DebugUtil.stubTreeToString(javaFileStub) - throw IllegalStateException("Class was not found $classFqName\nin $ktFileText\nstub: \n$stubFileText") + throw IllegalStateException("Couldn't get delegate for $this\nin $ktFileText\nstub: \n$stubFileText") + } + } + + protected open fun findDelegateClass(javaFileStub: PsiJavaFileStub): PsiClass? { + return LightClassUtil.findClass(javaFileStub) { + getOriginalElement(it as StubElement<*>) == classOrObject } } @@ -305,14 +313,14 @@ abstract class KtLightClassForSourceDeclaration( return this } - override fun toString() = "${KtLightClass::class.java.simpleName}:$classFqName" + override fun toString() = "${this.javaClass.simpleName}:${classOrObject.getDebugText()}" override fun getOwnInnerClasses(): List { val result = ArrayList() classOrObject.declarations.filterIsInstance().mapNotNullTo(result) { create(it) } if (classOrObject.hasInterfaceDefaultImpls) { - result.add(KtLightClassForInterfaceDefaultImpls(classFqName.defaultImplsChild(), classOrObject)) + result.add(KtLightClassForInterfaceDefaultImpls(classOrObject)) } return result } @@ -342,25 +350,20 @@ abstract class KtLightClassForSourceDeclaration( if (classOrObject is KtObjectDeclaration && classOrObject.isObjectLiteral()) { if (classOrObject.containingFile.virtualFile == null) return null - val data = getLightClassDataExactly(classOrObject) ?: return null - return KtLightClassForAnonymousDeclaration( - { data.jvmQualifiedName }, - classOrObject) + return KtLightClassForAnonymousDeclaration(classOrObject) } if (classOrObject.isLocal()) { if (classOrObject.containingFile.virtualFile == null) return null - val data = getLightClassDataExactly(classOrObject) ?: return null - return KtLightClassForLocalDeclaration({ data.jvmQualifiedName }, classOrObject) + return KtLightClassForLocalDeclaration(classOrObject) } if (isEnumEntryWithoutBody(classOrObject)) { return null } - val fqName = classOrObject.fqName ?: return null - return KtLightClassImpl({ fqName }, classOrObject) + return KtLightClassImpl(classOrObject) } private fun isEnumEntryWithoutBody(classOrObject: KtClassOrObject): Boolean { @@ -385,11 +388,6 @@ abstract class KtLightClassForSourceDeclaration( return value } - private fun getLightClassDataExactly(classOrObject: KtClassOrObject): LightClassDataForKotlinClass? { - val data = getLightClassData(classOrObject) as? OutermostKotlinClassLightClassData ?: return null - return data.dataForClass(classOrObject) - } - private fun getOutermostClassOrObject(classOrObject: KtClassOrObject): KtClassOrObject { val outermostClass = KtPsiUtil.getOutermostClassOrObject(classOrObject) ?: throw IllegalStateException("Attempt to build a light class for a local class: " + classOrObject.text) diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassImpl.kt index d05f9f81406..8ae76930cd3 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassImpl.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/KtLightClassImpl.kt @@ -16,17 +16,10 @@ package org.jetbrains.kotlin.asJava.classes -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtClassOrObject // light class for top level or (inner/nested of top level) source declarations -class KtLightClassImpl( - classFqNameFunction: (KtClassOrObject) -> FqName, - classOrObject: KtClassOrObject -) : KtLightClassForSourceDeclaration(classFqNameFunction, classOrObject) { - val fqName: FqName - get() = fqName - +class KtLightClassImpl(classOrObject: KtClassOrObject) : KtLightClassForSourceDeclaration(classOrObject) { override fun getQualifiedName() = classOrObject.fqName?.asString() override fun getParent() = if (classOrObject.isTopLevel()) @@ -34,5 +27,5 @@ class KtLightClassImpl( else containingClass - override fun copy() = KtLightClassImpl(classFqNameFunction, classOrObject.copy() as KtClassOrObject) + override fun copy() = KtLightClassImpl(classOrObject.copy() as KtClassOrObject) } \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt index 602bc216724..341d8f7e3f7 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightFieldImpl.kt @@ -26,9 +26,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.KtLightClassImpl import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtEnumEntry import org.jetbrains.kotlin.psi.KtNamedDeclaration @@ -141,8 +139,7 @@ sealed class KtLightFieldImpl( is PsiEnumConstant -> { val kotlinEnumEntry = (origin as? LightMemberOriginForDeclaration)?.originalElement as? KtEnumEntry val initializingClass = if (kotlinEnumEntry != null && kotlinEnumEntry.declarations.isNotEmpty()) { - val enumConstantFqName = FqName((containingClass as KtLightClassImpl).fqName.asString() + "." + kotlinEnumEntry.name) - KtLightClassForEnumEntry(enumConstantFqName, kotlinEnumEntry, delegate) + KtLightClassForEnumEntry(kotlinEnumEntry, delegate) } else null return KtLightEnumConstant(origin, delegate, containingClass, initializingClass)