diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt index 29c5724e273..05c4f62f84d 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt @@ -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, diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMethods.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMethods.kt index 1f9aad6b2f1..94b98c221ff 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMethods.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMethods.kt @@ -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() diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightParameters.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightParameters.kt index 12b4a124a16..703d4308475 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightParameters.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightParameters.kt @@ -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 } } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt index d7f24432b36..9da6ab57002 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt @@ -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 } \ No newline at end of file diff --git a/compiler/testData/asJava/ultraLightClasses/implementingKotlinCollections.kt b/compiler/testData/asJava/ultraLightClasses/implementingKotlinCollections.kt index 3130f492cd6..d9bae9e3f2c 100644 --- a/compiler/testData/asJava/ultraLightClasses/implementingKotlinCollections.kt +++ b/compiler/testData/asJava/ultraLightClasses/implementingKotlinCollections.kt @@ -1,21 +1,17 @@ import java.util.* -/** should load cls */ class MyList : List { override operator fun get(index: Int): String {} } -/** should load cls */ interface ASet : MutableCollection {} -/** should load cls */ abstract class MySet : ASet { override fun remove(elem: String): Boolean {} } -/** should load cls */ -abstract class SmartSet private constructor() : AbstractSet() { +abstract class SmartSet private constructor() : AbstractMutableSet() { override fun iterator(): MutableIterator = unresolved override fun add(element: T): Boolean { @@ -23,5 +19,4 @@ abstract class SmartSet private constructor() : AbstractSet() { } override fun contains(element: T): Boolean = true - -} +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt index 06bf32c5861..7f78aa8b706 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt @@ -20,8 +20,6 @@ import com.intellij.openapi.diagnostic.debug import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleUtilCore import com.intellij.openapi.project.Project -import com.intellij.openapi.util.text.StringUtil -import com.intellij.psi.PsiElement import com.intellij.psi.PsiManager import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.util.CachedValue @@ -40,11 +38,10 @@ import org.jetbrains.kotlin.codegen.JvmCodegenUtil import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor -import org.jetbrains.kotlin.extensions.LightClassApplicabilityType import org.jetbrains.kotlin.extensions.LightClassApplicabilityCheckExtension +import org.jetbrains.kotlin.extensions.LightClassApplicabilityType import org.jetbrains.kotlin.idea.caches.lightClasses.IDELightClassContexts import org.jetbrains.kotlin.idea.caches.lightClasses.LazyLightClassDataHolder import org.jetbrains.kotlin.idea.facet.KotlinFacet @@ -57,8 +54,6 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException import org.jetbrains.kotlin.resolve.source.getPsi @@ -69,12 +64,6 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG private inner class KtUltraLightSupportImpl(private val element: KtElement, private val module: Module) : KtUltraLightSupport { - private fun KtDeclaration.forLogString(): String? = when (this) { - is KtClassOrObject -> this.fqName?.asString() - is KtFile -> this.packageFqNameByTree.asString() - else -> this.text - } - override val isReleasedCoroutine get() = module.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines) @@ -103,14 +92,6 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG LOG.debug { "Using heavy light classes because of compiler plugins" } return true } - - val problem = findTooComplexDeclaration(element) - if (problem != null) { - LOG.debug { - "Using heavy light classes for ${element.forLogString()} because of ${StringUtil.trimLog(problem.text, 100)}" - } - return true - } return false } @@ -164,31 +145,6 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG namePreprocessor = ::tryGetPredefinedName ) } - - private fun findTooComplexDeclaration(declaration: KtDeclaration): PsiElement? { - - if (declaration is KtClassOrObject) { - declaration.primaryConstructor?.let { findTooComplexDeclaration(it) }?.let { return it } - - for (d in declaration.declarations) { - if (d is KtClassOrObject && !(d is KtObjectDeclaration && d.isCompanion())) continue - - findTooComplexDeclaration(d)?.let { return it } - } - - if (implementsKotlinCollection(declaration)) { - return declaration.getSuperTypeList() - } - } - if (declaration is KtCallableDeclaration) { - declaration.valueParameters.mapNotNull { findTooComplexDeclaration(it) }.firstOrNull()?.let { return it } - } - if (declaration is KtProperty) { - declaration.accessors.mapNotNull { findTooComplexDeclaration(it) }.firstOrNull()?.let { return it } - } - - return null - } } override fun createUltraLightClassForFacade( @@ -240,14 +196,6 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG } } - private fun implementsKotlinCollection(classOrObject: KtClassOrObject): Boolean { - if (classOrObject.superTypeListEntries.isEmpty()) return false - - return (resolveToDescriptor(classOrObject) as? ClassifierDescriptor)?.getAllSuperClassifiers()?.any { - it.fqNameSafe.asString().startsWith("kotlin.collections.") - } == true - } - private fun KtFile.hasAlias(shortName: Name?): Boolean { if (shortName == null) return false return allAliases(this)[shortName.asString()] == true @@ -307,10 +255,10 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG getResolutionFacade().frontendService() override fun resolveToDescriptor(declaration: KtDeclaration): DeclarationDescriptor? { - try { - return declaration.resolveToDescriptorIfAny(BodyResolveMode.FULL) + return try { + declaration.resolveToDescriptorIfAny(BodyResolveMode.FULL) } catch (e: NoDescriptorForDeclarationException) { - return null + null } } diff --git a/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendingMutableInterfaces.java b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendingMutableInterfaces.java index b025c7c7c8a..99a982d8001 100644 --- a/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendingMutableInterfaces.java +++ b/idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendingMutableInterfaces.java @@ -1,14 +1,14 @@ public class EtendingMutableInterfaces { public static class Lists { - public static class ExtendIList1 implements IMutableList { + public static class ExtendIList1 implements IMutableList { } - public static class ExtendIList2 implements IMutableList { + public static class ExtendIList2 implements IMutableList { } - // Compiler bug causes remove(int) to clash https://youtrack.jetbrains.com/issue/KT-17782 + // Compiler bug causes remove(int) to clash https://youtrack.jetbrains.com/issue/KT-17782 //public static class ExtendCList1 extends CMutableList { // //} @@ -24,14 +24,14 @@ public class EtendingMutableInterfaces { public static class ExtendAList extends AMutableList { } - } - + } + public static class Collections { - public static class ExtendICollection1 implements IMutableCollection { + public static class ExtendICollection1 implements IMutableCollection { } - public static class ExtendICollection2 implements IMutableCollection { + public static class ExtendICollection2 implements IMutableCollection { } @@ -50,14 +50,14 @@ public class EtendingMutableInterfaces { public static class ExtendACollection extends AMutableCollection { } - } - + } + public static class Sets { - public static class ExtendISet1 implements IMutableSet { + public static class ExtendISet1 implements IMutableSet { } - public static class ExtendISet2 implements IMutableSet { + public static class ExtendISet2 implements IMutableSet { } @@ -76,14 +76,14 @@ public class EtendingMutableInterfaces { public static class ExtendASet extends AMutableSet { } - } - + } + public static class Iterables { - public static class ExtendIIterable1 implements IMutableIterable { + public static class ExtendIIterable1 implements IMutableIterable { } - public static class ExtendIIterable2 implements IMutableIterable { + public static class ExtendIIterable2 implements IMutableIterable { } @@ -102,14 +102,14 @@ public class EtendingMutableInterfaces { public static class ExtendAIterable extends AMutableIterable { } - } - + } + public static class Iterators { - public static class ExtendIIterator1 implements IMutableIterator { + public static class ExtendIIterator1 implements IMutableIterator { } - public static class ExtendIIterator2 implements IMutableIterator { + public static class ExtendIIterator2 implements IMutableIterator { } @@ -129,13 +129,13 @@ public class EtendingMutableInterfaces { } } - + public static class Maps { - public static class ExtendIMap1 implements IMutableMap { + public static class ExtendIMap1 implements IMutableMap { } - public static class ExtendIMap2 implements IMutableMap { + public static class ExtendIMap2 implements IMutableMap { } @@ -159,11 +159,11 @@ public class EtendingMutableInterfaces { } public static class MapEntrys { - public static class ExtendIMapEntry1 implements IMutableMapEntry { + public static class ExtendIMapEntry1 implements IMutableMapEntry { } - public static class ExtendIMapEntry2 implements IMutableMapEntry { + public static class ExtendIMapEntry2 implements IMutableMapEntry { }