Enable kotlin.collections support for UL classes
Removed restriction for classes derived from Kotlin collections Added type erasure for java collection overrided methods
This commit is contained in:
@@ -100,30 +100,72 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
||||
override fun getModifierList(): PsiModifierList? = _modifierList
|
||||
|
||||
private fun allSuperTypes() =
|
||||
getDescriptor()?.typeConstructor?.supertypes.orEmpty().asSequence()
|
||||
getDescriptor()?.typeConstructor?.supertypes.orEmpty()
|
||||
|
||||
private fun mapSupertype(supertype: KotlinType) =
|
||||
supertype.asPsiType(support, TypeMappingMode.SUPER_TYPE, this) as? PsiClassType
|
||||
private fun mapSupertype(supertype: KotlinType, kotlinCollectionAsIs: Boolean = false) =
|
||||
supertype.asPsiType(
|
||||
support,
|
||||
if (kotlinCollectionAsIs) TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS else TypeMappingMode.SUPER_TYPE,
|
||||
this
|
||||
) as? PsiClassType
|
||||
|
||||
override fun createExtendsList(): PsiReferenceList? {
|
||||
if (isAnnotationType) return KotlinLightReferenceListBuilder(manager, language, PsiReferenceList.Role.EXTENDS_LIST)
|
||||
override fun createExtendsList(): PsiReferenceList? = createInheritanceList(forExtendsList = true)
|
||||
|
||||
if (tooComplex) return super.createExtendsList()
|
||||
override fun createImplementsList(): PsiReferenceList? = createInheritanceList(forExtendsList = false)
|
||||
|
||||
return KotlinSuperTypeListBuilder(
|
||||
kotlinOrigin.getSuperTypeList(),
|
||||
manager,
|
||||
language,
|
||||
PsiReferenceList.Role.EXTENDS_LIST
|
||||
).also { list ->
|
||||
allSuperTypes()
|
||||
.filter(this::isTypeForExtendsList)
|
||||
.map(this::mapSupertype)
|
||||
.forEach(list::addReference)
|
||||
private fun createInheritanceList(forExtendsList: Boolean): PsiReferenceList? {
|
||||
|
||||
val role = if (forExtendsList) PsiReferenceList.Role.EXTENDS_LIST else PsiReferenceList.Role.IMPLEMENTS_LIST
|
||||
|
||||
if (isAnnotationType) return KotlinLightReferenceListBuilder(manager, language, role)
|
||||
|
||||
if (tooComplex) return if (forExtendsList) super.createExtendsList() else super.createImplementsList()
|
||||
|
||||
val superTypes = allSuperTypes().filter {
|
||||
isTypeForInheritanceList(it, forExtendsList)
|
||||
}
|
||||
|
||||
val listBuilder = KotlinSuperTypeListBuilder(
|
||||
kotlinOrigin = kotlinOrigin.getSuperTypeList(),
|
||||
manager = manager,
|
||||
language = language,
|
||||
role = role
|
||||
)
|
||||
|
||||
for (superType in superTypes) {
|
||||
addTypeToTypeList(
|
||||
listBuilder = listBuilder,
|
||||
superType = superType
|
||||
)
|
||||
}
|
||||
|
||||
return listBuilder
|
||||
}
|
||||
|
||||
private fun addTypeToTypeList(listBuilder: KotlinSuperTypeListBuilder, superType: KotlinType) {
|
||||
|
||||
val mappedType = mapSupertype(superType, kotlinCollectionAsIs = true) ?: return
|
||||
|
||||
listBuilder.addReference(mappedType)
|
||||
|
||||
if (mappedType.canonicalText.startsWith("kotlin.collections.")) {
|
||||
|
||||
val mappedToNoCollectionAsIs = mapSupertype(superType, kotlinCollectionAsIs = false)
|
||||
|
||||
if (mappedToNoCollectionAsIs !== null &&
|
||||
mappedType.canonicalText != mappedToNoCollectionAsIs.canonicalText
|
||||
) {
|
||||
//Add java supertype
|
||||
listBuilder.addReference(mappedToNoCollectionAsIs)
|
||||
//Add marker interface
|
||||
superType.tryResolveMarkerInterfaceFQName()?.let { marker ->
|
||||
listBuilder.addReference(marker)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isTypeForExtendsList(supertype: KotlinType): Boolean {
|
||||
private fun isTypeForInheritanceList(supertype: KotlinType, forExtendsList: Boolean): Boolean {
|
||||
// Do not add redundant "extends java.lang.Object" anywhere
|
||||
if (supertype.isAnyOrNullableAny()) return false
|
||||
|
||||
@@ -131,30 +173,9 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
||||
if (isEnum && KotlinBuiltIns.isEnum(supertype)) return false
|
||||
|
||||
// Interfaces have only extends lists
|
||||
if (isInterface) return true
|
||||
if (isInterface) return forExtendsList
|
||||
|
||||
return !JvmCodegenUtil.isJvmInterface(supertype)
|
||||
}
|
||||
|
||||
override fun createImplementsList(): PsiReferenceList? {
|
||||
|
||||
if (isAnnotationType) return KotlinLightReferenceListBuilder(manager, language, PsiReferenceList.Role.IMPLEMENTS_LIST)
|
||||
|
||||
if (tooComplex) return super.createImplementsList()
|
||||
|
||||
return KotlinSuperTypeListBuilder(
|
||||
kotlinOrigin.getSuperTypeList(),
|
||||
manager,
|
||||
language,
|
||||
PsiReferenceList.Role.IMPLEMENTS_LIST
|
||||
).also { list ->
|
||||
if (!isInterface) {
|
||||
allSuperTypes()
|
||||
.filter { JvmCodegenUtil.isJvmInterface(it) }
|
||||
.map(this::mapSupertype)
|
||||
.forEach(list::addReference)
|
||||
}
|
||||
}
|
||||
return forExtendsList == !JvmCodegenUtil.isJvmInterface(supertype)
|
||||
}
|
||||
|
||||
override fun buildTypeParameterList(): PsiTypeParameterList =
|
||||
@@ -278,7 +299,7 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor
|
||||
for (declaration in companion.declarations.filterNot { isHiddenByDeprecation(it) }) {
|
||||
when (declaration) {
|
||||
is KtNamedFunction ->
|
||||
if (isJvmStatic(declaration)) result.addAll(membersBuilder.createMethods(declaration,forceStatic = true))
|
||||
if (isJvmStatic(declaration)) result.addAll(membersBuilder.createMethods(declaration, forceStatic = true))
|
||||
is KtProperty -> result.addAll(
|
||||
membersBuilder.propertyAccessors(
|
||||
declaration,
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl
|
||||
import org.jetbrains.kotlin.codegen.FunctionCodegen
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.getSpecialSignatureInfo
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
@@ -93,6 +94,15 @@ internal abstract class KtUltraLightMethod(
|
||||
|
||||
abstract fun computeDescriptor(): FunctionDescriptor?
|
||||
|
||||
private val lazyTypeErasure = lazyPub {
|
||||
computeDescriptor()
|
||||
?.getSpecialSignatureInfo()
|
||||
?.isObjectReplacedWithTypeParameter
|
||||
?: false
|
||||
}
|
||||
|
||||
val checkNeedToErasureParametersTypes: Boolean by lazyTypeErasure
|
||||
|
||||
override fun equals(other: Any?): Boolean = this === other
|
||||
|
||||
override fun hashCode(): Int = name.hashCode()
|
||||
|
||||
+6
-1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.asJava.classes
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.LocalSearchScope
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.util.TypeConversionUtil
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.kotlin.asJava.elements.*
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
@@ -114,9 +115,13 @@ internal abstract class KtUltraLightParameter(
|
||||
kotlinType.asPsiType(support, TypeMappingMode.DEFAULT, this)
|
||||
} else {
|
||||
val containingDescriptor = computeContainingDescriptor() ?: return@lazyPub PsiType.NULL
|
||||
support.mapType(this) { typeMapper, sw ->
|
||||
val mappedType = support.mapType(this) { typeMapper, sw ->
|
||||
typeMapper.writeParameterType(sw, kotlinType, containingDescriptor)
|
||||
}
|
||||
|
||||
if (method is KtUltraLightMethod && method.checkNeedToErasureParametersTypes)
|
||||
TypeConversionUtil.erasure(mappedType)
|
||||
else mappedType
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||
import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterListBuilder
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
@@ -37,6 +38,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
@@ -361,4 +363,24 @@ private fun toQualifiedName(userType: KtUserType): FqName? {
|
||||
}
|
||||
|
||||
return FqName.fromSegments(ContainerUtil.reverse(reversedNames))
|
||||
}
|
||||
|
||||
/***
|
||||
* @see org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
||||
*/
|
||||
fun KotlinType.tryResolveMarkerInterfaceFQName(): String? {
|
||||
|
||||
val classId = constructor.declarationDescriptor.classId
|
||||
|
||||
for (mapping in JavaToKotlinClassMap.mutabilityMappings) {
|
||||
if (mapping.kotlinReadOnly == classId) {
|
||||
return "kotlin.jvm.internal.markers.KMappedMarker"
|
||||
} else if (mapping.kotlinMutable == classId) {
|
||||
return "kotlin.jvm.internal.markers.K" + classId.relativeClassName.asString()
|
||||
.replace("MutableEntry", "Entry") // kotlin.jvm.internal.markers.KMutableMap.Entry for some reason
|
||||
.replace(".", "$")
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
Reference in New Issue
Block a user