FqName is not required to create source light classes

This commit is contained in:
Pavel V. Talanov
2016-07-26 17:16:46 +03:00
parent 5a1a1fc03a
commit 913a1baf56
10 changed files with 57 additions and 68 deletions
@@ -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()
@@ -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;
}
@@ -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<PsiClassType>? = 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)
@@ -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
}
@@ -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()
@@ -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
@@ -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
@@ -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<KotlinClassOrObjectStub<out KtClassOrObject>> {
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<PsiClass> {
val result = ArrayList<PsiClass>()
classOrObject.declarations.filterIsInstance<KtClassOrObject>().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)
@@ -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)
}
@@ -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)