Use wrappers around java.util.* to emulate kotlin.collection.* behaviour
Backend: If kotlin class extends kotlin.collection.List
write it as it's super interface (light class mode only)
IDE: Provide wrapper classes to java resolve
that try to emulate backend behaviour
For example if kotlin class implements kotlin.collections.Map,
we provide a superinterface that has abstract 'getEntries' method
and 'entrySet' method that is considered default.
In reality all those methods are generated in the class itself.
In IDE supporting this case without hacks is not feasible performance-wise
since kotlin.collection.* may not be an immediate supertype and we need
to compute all supertypes just to calculate own methods of the class
This commit is contained in:
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode;
|
||||
import org.jetbrains.kotlin.name.ClassId;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
@@ -306,15 +307,24 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
for (KotlinType supertype : descriptor.getTypeConstructor().getSupertypes()) {
|
||||
if (isJvmInterface(supertype.getConstructor().getDeclarationDescriptor())) {
|
||||
FqName kotlinInterfaceName = DescriptorUtils.getFqName(supertype.getConstructor().getDeclarationDescriptor()).toSafe();
|
||||
|
||||
sw.writeInterface();
|
||||
Type jvmInterfaceType = typeMapper.mapSupertype(supertype, sw);
|
||||
sw.writeInterfaceEnd();
|
||||
String jvmInterfaceInternalName = jvmInterfaceType.getInternalName();
|
||||
|
||||
superInterfaces.add(jvmInterfaceInternalName);
|
||||
|
||||
FqName kotlinInterfaceName = DescriptorUtils.getFqName(supertype.getConstructor().getDeclarationDescriptor()).toSafe();
|
||||
String kotlinMarkerInterfaceInternalName = KOTLIN_MARKER_INTERFACES.get(kotlinInterfaceName);
|
||||
if (kotlinMarkerInterfaceInternalName != null) {
|
||||
if (typeMapper.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) {
|
||||
sw.writeInterface();
|
||||
Type kotlinCollectionType = typeMapper.mapType(supertype, sw, TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS);
|
||||
sw.writeInterfaceEnd();
|
||||
superInterfaces.add(kotlinCollectionType.getInternalName());
|
||||
}
|
||||
|
||||
kotlinMarkerInterfaces.add(kotlinMarkerInterfaceInternalName);
|
||||
}
|
||||
}
|
||||
@@ -357,9 +367,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
generateFunctionsForDataClasses();
|
||||
|
||||
new CollectionStubMethodGenerator(typeMapper, descriptor).generate(functionCodegen, v);
|
||||
if (state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) {
|
||||
new CollectionStubMethodGenerator(typeMapper, descriptor).generate(functionCodegen, v);
|
||||
|
||||
generateToArray();
|
||||
}
|
||||
|
||||
generateToArray();
|
||||
|
||||
if (context.closure != null)
|
||||
genClosureFields(context.closure, v, typeMapper);
|
||||
|
||||
+1
-1
@@ -163,7 +163,7 @@ class CliLightClassGenerationSupport(project: Project) : LightClassGenerationSup
|
||||
KtLightClassForFacade.createForFacade(psiManager, facadeFqName, scope, filesForFacade))
|
||||
}
|
||||
|
||||
override fun getMultifilePartClasses(partFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||
override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||
//
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ abstract class LightClassGenerationSupport {
|
||||
|
||||
abstract fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||
|
||||
abstract fun getMultifilePartClasses(partFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||
abstract fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||
|
||||
abstract fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||
|
||||
|
||||
+1
-1
@@ -92,7 +92,7 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
|
||||
findClassesAndObjects(qualifiedName, scope, answer);
|
||||
|
||||
answer.addAll(lightClassGenerationSupport.getFacadeClasses(qualifiedName, scope));
|
||||
answer.addAll(lightClassGenerationSupport.getMultifilePartClasses(qualifiedName, scope));
|
||||
answer.addAll(lightClassGenerationSupport.getKotlinInternalClasses(qualifiedName, scope));
|
||||
|
||||
return sortByClasspath(answer, scope).toArray(new PsiClass[answer.size()]);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
public final class TypeHierarchyMap <TValue> implements java.util.Map<java.lang.Class<?>,TValue>, kotlin.collections.Map<java.lang.Class<?>,TValue>, kotlin.jvm.internal.markers.KMappedMarker {
|
||||
public boolean containsKey(@org.jetbrains.annotations.NotNull java.lang.Class key) { /* compiled code */ }
|
||||
|
||||
public TypeHierarchyMap() { /* compiled code */ }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// p1.TypeHierarchyMap
|
||||
package p1
|
||||
|
||||
class TypeHierarchyMap<TValue> : Map<Class<*>, TValue> {
|
||||
override fun containsKey(key: Class<*>): Boolean {
|
||||
TODO("not implemented")
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
public final class SmartSet <T> extends kotlin.collections.AbstractSet<T> implements java.util.Set<T>, kotlin.collections.MutableSet<T>, kotlin.jvm.internal.markers.KMutableSet {
|
||||
private java.lang.Object data;
|
||||
private int size;
|
||||
private static final int ARRAY_THRESHOLD = 5;
|
||||
public static final SmartSet.Companion Companion;
|
||||
|
||||
public int getSize() { /* compiled code */ }
|
||||
|
||||
public void setSize(int i) { /* compiled code */ }
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public java.util.Iterator<T> iterator() { /* compiled code */ }
|
||||
|
||||
public boolean add(T element) { /* compiled code */ }
|
||||
|
||||
public void clear() { /* compiled code */ }
|
||||
|
||||
public boolean contains(java.lang.Object element) { /* compiled code */ }
|
||||
|
||||
private SmartSet() { /* compiled code */ }
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public static final <T> SmartSet<T> create() { /* compiled code */ }
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public static final <T> SmartSet<T> create(@org.jetbrains.annotations.NotNull java.util.Collection<? extends T> set) { /* compiled code */ }
|
||||
|
||||
public static final class Companion {
|
||||
private final int getARRAY_THRESHOLD() { /* compiled code */ }
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public final <T> SmartSet<T> create() { /* compiled code */ }
|
||||
|
||||
@kotlin.jvm.JvmStatic
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public final <T> SmartSet<T> create(@org.jetbrains.annotations.NotNull java.util.Collection<? extends T> set) { /* compiled code */ }
|
||||
|
||||
private Companion() { /* compiled code */ }
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// SmartSet
|
||||
|
||||
class SmartSet<T> private constructor() : AbstractSet<T>(), MutableSet<T> {
|
||||
companion object {
|
||||
private val ARRAY_THRESHOLD = 5
|
||||
|
||||
@JvmStatic
|
||||
fun <T> create() = SmartSet<T>()
|
||||
|
||||
@JvmStatic
|
||||
fun <T> create(set: Collection<T>): SmartSet<T> = TODO()
|
||||
}
|
||||
|
||||
private var data: Any? = null
|
||||
|
||||
override var size: Int = 0
|
||||
|
||||
|
||||
|
||||
override fun iterator(): MutableIterator<T> = TODO()
|
||||
|
||||
override fun add(element: T): Boolean = TODO()
|
||||
|
||||
override fun clear() {
|
||||
data = null
|
||||
size = 0
|
||||
}
|
||||
|
||||
override fun contains(element: T): Boolean = when {
|
||||
size == 0 -> false
|
||||
size == 1 -> data == element
|
||||
size < ARRAY_THRESHOLD -> element in data as Array<T>
|
||||
else -> element in data as Set<T>
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -50,7 +50,7 @@ private fun String.method(name: String, parameters: String, returnType: String)
|
||||
SignatureBuildingComponents.signature(this@method, "$name($parameters)$returnType"))
|
||||
|
||||
object BuiltinSpecialProperties {
|
||||
private val PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP = mapOf(
|
||||
val PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP = mapOf(
|
||||
BUILTIN_NAMES._enum.childSafe("name") to Name.identifier("name"),
|
||||
BUILTIN_NAMES._enum.childSafe("ordinal") to Name.identifier("ordinal"),
|
||||
BUILTIN_NAMES.collection.child("size") to Name.identifier("size"),
|
||||
@@ -99,6 +99,7 @@ object BuiltinMethodsWithSpecialGenericSignature {
|
||||
).map { "java/util/Collection".method(it, "Ljava/util/Collection;", JvmPrimitiveType.BOOLEAN.desc) }
|
||||
|
||||
private val ERASED_COLLECTION_PARAMETER_SIGNATURES = ERASED_COLLECTION_PARAMETER_NAME_AND_SIGNATURES.map { it.signature }
|
||||
val ERASED_COLLECTION_PARAMETER_NAMES = ERASED_COLLECTION_PARAMETER_NAME_AND_SIGNATURES.map { it.name.asString() }
|
||||
|
||||
enum class TypeSafeBarrierDescription(val defaultValue: Any?) {
|
||||
NULL(null), INDEX(-1), FALSE(false),
|
||||
@@ -144,7 +145,7 @@ object BuiltinMethodsWithSpecialGenericSignature {
|
||||
|
||||
private val SIGNATURE_TO_DEFAULT_VALUES_MAP = GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP.mapKeys { it.key.signature }
|
||||
private val ERASED_VALUE_PARAMETERS_SHORT_NAMES: Set<Name>
|
||||
private val ERASED_VALUE_PARAMETERS_SIGNATURES: Set<String>
|
||||
val ERASED_VALUE_PARAMETERS_SIGNATURES: Set<String>
|
||||
|
||||
init {
|
||||
val allMethods = GENERIC_PARAMETERS_METHODS_TO_DEFAULT_VALUES_MAP.keys + ERASED_COLLECTION_PARAMETER_NAME_AND_SIGNATURES
|
||||
|
||||
@@ -26,6 +26,7 @@ class TypeMappingMode private constructor(
|
||||
val skipDeclarationSiteWildcards: Boolean = false,
|
||||
val skipDeclarationSiteWildcardsIfPossible: Boolean = false,
|
||||
private val genericArgumentMode: TypeMappingMode? = null,
|
||||
val kotlinCollectionsToJavaCollections: Boolean = true,
|
||||
private val genericContravariantArgumentMode: TypeMappingMode? = genericArgumentMode,
|
||||
private val genericInvariantArgumentMode: TypeMappingMode? = genericArgumentMode
|
||||
) {
|
||||
@@ -49,6 +50,13 @@ class TypeMappingMode private constructor(
|
||||
@JvmField
|
||||
val SUPER_TYPE = TypeMappingMode(skipDeclarationSiteWildcards = true, genericArgumentMode = GENERIC_ARGUMENT)
|
||||
|
||||
@JvmField
|
||||
val SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS = TypeMappingMode(
|
||||
skipDeclarationSiteWildcards = true,
|
||||
genericArgumentMode = GENERIC_ARGUMENT,
|
||||
kotlinCollectionsToJavaCollections = false
|
||||
)
|
||||
|
||||
/**
|
||||
* kotlin.reflect.KClass mapped to java.lang.Class
|
||||
* Other types mapped as DEFAULT
|
||||
|
||||
+4
-1
@@ -81,7 +81,7 @@ fun <T : Any> mapType(
|
||||
)
|
||||
}
|
||||
|
||||
mapBuiltInType(kotlinType, factory, typeMappingConfiguration)?.let { builtInType ->
|
||||
mapBuiltInType(kotlinType, factory, mode, typeMappingConfiguration)?.let { builtInType ->
|
||||
val jvmType = factory.boxTypeIfNeeded(builtInType, mode.needPrimitiveBoxing)
|
||||
writeGenericType(kotlinType, jvmType, mode)
|
||||
return jvmType
|
||||
@@ -186,6 +186,7 @@ fun hasVoidReturnType(descriptor: CallableDescriptor): Boolean {
|
||||
private fun <T : Any> mapBuiltInType(
|
||||
type: KotlinType,
|
||||
typeFactory: JvmTypeFactory<T>,
|
||||
mode: TypeMappingMode,
|
||||
typeMappingConfiguration: TypeMappingConfiguration<T>
|
||||
): T? {
|
||||
val descriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null
|
||||
@@ -211,6 +212,8 @@ private fun <T : Any> mapBuiltInType(
|
||||
|
||||
val classId = JavaToKotlinClassMap.mapKotlinToJava(fqName)
|
||||
if (classId != null) {
|
||||
if (!mode.kotlinCollectionsToJavaCollections && JavaToKotlinClassMap.mutabilityMappings.any { it.javaClass == classId }) return null
|
||||
|
||||
return typeFactory.createObjectType(JvmClassName.byClassId(classId, typeMappingConfiguration).internalName)
|
||||
}
|
||||
|
||||
|
||||
+15
-16
@@ -18,10 +18,7 @@ package org.jetbrains.kotlin.idea.caches.resolve
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.ClassFileViewProvider
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.compiled.ClsClassImpl
|
||||
import com.intellij.psi.impl.compiled.ClsFileImpl
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
@@ -30,18 +27,12 @@ import org.jetbrains.kotlin.asJava.LightClassBuilder
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
||||
import org.jetbrains.kotlin.asJava.classes.FakeLightClassForFileOfPackage
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||
import org.jetbrains.kotlin.asJava.classes.*
|
||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.ClsJavaStubByVirtualFileCache
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.IDELightClassContexts
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtLightClassForDecompiledDeclaration
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.LazyLightClassDataHolder
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.*
|
||||
import org.jetbrains.kotlin.idea.decompiler.classFile.KtClsFile
|
||||
import org.jetbrains.kotlin.idea.decompiler.navigation.SourceNavigationHelper
|
||||
import org.jetbrains.kotlin.idea.stubindex.*
|
||||
@@ -162,11 +153,15 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMultifilePartClasses(partFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||
if (partFqName.isRoot) return emptyList()
|
||||
override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||
if (fqName.isRoot) return emptyList()
|
||||
|
||||
val facadeKtFiles = StaticFacadeIndexUtil.getMultifileClassForPart(partFqName, scope, project)
|
||||
val partShortName = partFqName.shortName().asString()
|
||||
return findPackageParts(fqName, scope) + findPlatformWrapper(fqName, scope)
|
||||
}
|
||||
|
||||
private fun findPackageParts(fqName: FqName, scope: GlobalSearchScope): List<KtLightClassForDecompiledDeclaration> {
|
||||
val facadeKtFiles = StaticFacadeIndexUtil.getMultifileClassForPart(fqName, scope, project)
|
||||
val partShortName = fqName.shortName().asString()
|
||||
val partClassFileShortName = partShortName + ".class"
|
||||
|
||||
return facadeKtFiles.mapNotNull { facadeKtFile ->
|
||||
@@ -182,6 +177,10 @@ class IDELightClassGenerationSupport(private val project: Project) : LightClassG
|
||||
}
|
||||
}
|
||||
|
||||
private fun findPlatformWrapper(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||
return platformMutabilityWrapper(fqName) { JavaPsiFacade.getInstance(project).findClass(it, scope) }?.let { listOf(it) }.orEmpty()
|
||||
}
|
||||
|
||||
fun createLightClassForFileFacade(
|
||||
facadeFqName: FqName,
|
||||
facadeFiles: List<KtFile>,
|
||||
|
||||
+417
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.caches.resolve.lightClasses
|
||||
|
||||
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.InheritanceImplUtil
|
||||
import com.intellij.psi.impl.PsiClassImplUtil
|
||||
import com.intellij.psi.impl.PsiSubstitutorImpl.createSubstitutor
|
||||
import com.intellij.psi.impl.PsiSuperMethodImplUtil
|
||||
import com.intellij.psi.impl.light.*
|
||||
import com.intellij.psi.impl.source.ClassInnerStuffCache
|
||||
import com.intellij.psi.impl.source.PsiExtensibleClass
|
||||
import com.intellij.psi.impl.source.PsiImmediateClassType
|
||||
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod
|
||||
import com.siyeh.ig.psiutils.TypeUtils
|
||||
import org.jetbrains.kotlin.asJava.classes.cannotModify
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.psi.UserDataProperty
|
||||
|
||||
private val readOnlyQualifiedNamesToJavaClass = JavaToKotlinClassMap.mutabilityMappings.associateBy {
|
||||
(_, readOnly, _) ->
|
||||
readOnly.asSingleFqName()
|
||||
}
|
||||
|
||||
private val mutableQualifiedNamesToJavaClass = JavaToKotlinClassMap.mutabilityMappings.associateBy {
|
||||
(_, _, mutable) ->
|
||||
mutable.asSingleFqName()
|
||||
}
|
||||
|
||||
private val membersWithSpecializedSignature: Set<String> =
|
||||
BuiltinMethodsWithSpecialGenericSignature.ERASED_VALUE_PARAMETERS_SIGNATURES.mapTo(LinkedHashSet()) {
|
||||
val fqNameString = it.substringBefore('(').replace('/', '.')
|
||||
FqName(fqNameString).shortName().asString()
|
||||
}
|
||||
|
||||
private val javaGetterNameToKotlinGetterName: Map<String, String> = BuiltinSpecialProperties.PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP.map {
|
||||
(propertyFqName, javaGetterShortName) ->
|
||||
Pair(javaGetterShortName.asString(), JvmAbi.getterName(propertyFqName.shortName().asString()))
|
||||
}.toMap()
|
||||
|
||||
fun platformMutabilityWrapper(fqName: FqName, findJavaClass: (String) -> PsiClass?): PsiClass? {
|
||||
readOnlyQualifiedNamesToJavaClass[fqName]?.let {
|
||||
(javaClass, kotlinReadOnly) ->
|
||||
val javaBaseClass = findJavaClass(javaClass.asSingleFqName().asString()) ?: return null
|
||||
return getOrCreateWrapper(javaBaseClass, kotlinReadOnly.asSingleFqName(), isMutable = false)
|
||||
}
|
||||
mutableQualifiedNamesToJavaClass[fqName]?.let {
|
||||
(javaClass, _, kotlinMutable) ->
|
||||
val javaBaseClass = findJavaClass(javaClass.asSingleFqName().asString()) ?: return null
|
||||
return getOrCreateWrapper(javaBaseClass, kotlinMutable.asSingleFqName(), isMutable = true)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getOrCreateWrapper(javaBaseClass: PsiClass, kotlinFqName: FqName, isMutable: Boolean): KtLightMutabilityPlatformWrapper {
|
||||
val userDataStorage = if (isMutable) javaBaseClass::mutableWrapper else javaBaseClass::readOnlyWrapper
|
||||
return userDataStorage.get() ?: KtLightMutabilityPlatformWrapper(javaBaseClass, kotlinFqName, isMutable).also { userDataStorage.set(it) }
|
||||
}
|
||||
|
||||
private var PsiClass.readOnlyWrapper: KtLightMutabilityPlatformWrapper? by UserDataProperty(Key.create("READ_ONLY_WRAPPER"))
|
||||
private var PsiClass.mutableWrapper: KtLightMutabilityPlatformWrapper? by UserDataProperty(Key.create("MUTABLE_WRAPPER"))
|
||||
|
||||
class KtLightMutabilityPlatformWrapper(
|
||||
private val javaBaseClass: PsiClass,
|
||||
private val kotlinInterfaceFqName: FqName,
|
||||
private val isMutable: Boolean
|
||||
) : KtAbstractContainerWrapper(kotlinInterfaceFqName, javaBaseClass), PsiClass {
|
||||
private val _methods by lazyPub { calcMethods() }
|
||||
|
||||
private fun calcMethods() = javaBaseClass.methods.flatMap { methodWrappers(it) }
|
||||
|
||||
override fun getOwnMethods() = _methods
|
||||
|
||||
private fun methodWrappers(method: PsiMethod): List<PsiMethod> {
|
||||
val methodName = method.name
|
||||
|
||||
javaGetterNameToKotlinGetterName.get(methodName)?.let { kotlinName ->
|
||||
val finalBridgeForJava = method.finalBridge()
|
||||
val abstractKotlinGetter = method.wrap(name = kotlinName)
|
||||
return listOf(finalBridgeForJava, abstractKotlinGetter)
|
||||
}
|
||||
|
||||
if (!method.isInKotlinInterface()) {
|
||||
// compiler generates stub override
|
||||
return listOf(method.openBridge())
|
||||
}
|
||||
|
||||
return methodsWithSpecializedSignature(method)
|
||||
}
|
||||
|
||||
private fun methodsWithSpecializedSignature(method: PsiMethod): List<PsiMethod> {
|
||||
val methodName = method.name
|
||||
|
||||
if (methodName !in membersWithSpecializedSignature) return emptyList()
|
||||
|
||||
if (javaBaseClass.qualifiedName == CommonClassNames.JAVA_UTIL_MAP) {
|
||||
val abstractKotlinVariantWithGeneric = javaUtilMapMethodWithSpecialSignature(method) ?: return emptyList()
|
||||
val finalBridgeWithObject = method.finalBridge()
|
||||
return listOf(finalBridgeWithObject, abstractKotlinVariantWithGeneric)
|
||||
}
|
||||
|
||||
if (methodName in BuiltinMethodsWithSpecialGenericSignature.ERASED_COLLECTION_PARAMETER_NAMES) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
if (methodName == "remove" && method.parameterList.parameters.singleOrNull()?.type == PsiType.INT) {
|
||||
// remove(int) -> abstract removeAt(int), final bridge remove(int)
|
||||
return listOf(method.finalBridge(), createRemoveAt(method))
|
||||
}
|
||||
|
||||
|
||||
val finalBridgeWithObject = method.finalBridge()
|
||||
val abstractKotlinVariantWithGeneric = method.wrap(substituteObjectWith = singleTypeParameterAsType())
|
||||
return listOf(finalBridgeWithObject, abstractKotlinVariantWithGeneric)
|
||||
}
|
||||
|
||||
private fun singleTypeParameterAsType() = typeParameters.single().asType()
|
||||
|
||||
private fun createRemoveAt(baseMethod: PsiMethod): PsiMethod {
|
||||
return baseMethod.wrap(
|
||||
name = "removeAt",
|
||||
signature = MethodSignature(
|
||||
parameterTypes = listOf(PsiType.INT),
|
||||
returnType = singleTypeParameterAsType()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun PsiMethod.finalBridge() = wrap(makeFinal = true, hasImplementation = true)
|
||||
private fun PsiMethod.openBridge() = wrap(makeFinal = false, hasImplementation = true)
|
||||
|
||||
private fun PsiMethod.wrap(
|
||||
makeFinal: Boolean = false,
|
||||
hasImplementation: Boolean = false,
|
||||
name: String = this.name,
|
||||
substituteObjectWith: PsiType? = null,
|
||||
signature: MethodSignature? = null
|
||||
) = KtLightMethodWrapper(
|
||||
this@KtLightMutabilityPlatformWrapper, this@wrap,
|
||||
isFinal = makeFinal,
|
||||
name = name,
|
||||
substituteObjectWith = substituteObjectWith,
|
||||
providedSignature = signature,
|
||||
hasImplementation = hasImplementation
|
||||
)
|
||||
|
||||
private fun javaUtilMapMethodWithSpecialSignature(method: PsiMethod): KtLightMethodWrapper? {
|
||||
val k = typeParameters[0].asType()
|
||||
val v = typeParameters[1].asType()
|
||||
|
||||
val signature = when (method.name) {
|
||||
"get" -> MethodSignature(
|
||||
parameterTypes = listOf(k),
|
||||
returnType = v
|
||||
)
|
||||
"getOrDefault" -> MethodSignature(
|
||||
parameterTypes = listOf(k, v),
|
||||
returnType = v
|
||||
)
|
||||
"containsKey" -> MethodSignature(
|
||||
parameterTypes = listOf(k),
|
||||
returnType = PsiType.BOOLEAN
|
||||
)
|
||||
"containsValue" -> MethodSignature(
|
||||
parameterTypes = listOf(v),
|
||||
returnType = PsiType.BOOLEAN
|
||||
)
|
||||
"remove" ->
|
||||
when (method.parameterList.parametersCount) {
|
||||
1 -> MethodSignature(
|
||||
parameterTypes = listOf(k),
|
||||
returnType = v
|
||||
)
|
||||
2 -> MethodSignature(
|
||||
parameterTypes = listOf(k, v),
|
||||
returnType = PsiType.BOOLEAN
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
else -> null
|
||||
} ?: return null
|
||||
|
||||
return method.wrap(signature = signature)
|
||||
}
|
||||
|
||||
private fun PsiMethod.isInKotlinInterface(): Boolean {
|
||||
if (javaBaseClass.qualifiedName == CommonClassNames.JAVA_UTIL_MAP_ENTRY) {
|
||||
when (name) {
|
||||
"getValue", "getKey" -> return true
|
||||
}
|
||||
}
|
||||
|
||||
val kotlinInterface = DefaultBuiltIns.Instance.getBuiltInClassByFqName(kotlinInterfaceFqName)
|
||||
val scope = kotlinInterface.unsubstitutedMemberScope
|
||||
|
||||
val methodName = Name.identifier(name)
|
||||
return scope.getContributedFunctions(methodName, NoLookupLocation.FROM_IDE).isNotEmpty()
|
||||
|| scope.getContributedVariables(methodName, NoLookupLocation.FROM_IDE).isNotEmpty()
|
||||
}
|
||||
|
||||
override fun getContainingFile() = javaBaseClass.containingFile
|
||||
}
|
||||
|
||||
private data class MethodSignature(val parameterTypes: List<PsiType>, val returnType: PsiType)
|
||||
|
||||
private class KtLightMethodWrapper(
|
||||
private val containingClass: KtAbstractContainerWrapper,
|
||||
private val baseMethod: PsiMethod,
|
||||
private val name: String,
|
||||
private val isFinal: Boolean,
|
||||
private val hasImplementation: Boolean,
|
||||
private val substituteObjectWith: PsiType?,
|
||||
private val providedSignature: MethodSignature?
|
||||
) : PsiMethod, KtLightElementBase(containingClass) {
|
||||
|
||||
init {
|
||||
if (!hasImplementation && isFinal) {
|
||||
error("Can't be final without an implementation")
|
||||
}
|
||||
}
|
||||
|
||||
private fun substituteType(psiType: PsiType): PsiType {
|
||||
val substituted = containingClass.substitutor.substitute(psiType)
|
||||
if (TypeUtils.isJavaLangObject(substituted) && substituteObjectWith != null) {
|
||||
return substituteObjectWith
|
||||
}
|
||||
else {
|
||||
return substituted
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPresentation() = baseMethod.presentation
|
||||
|
||||
override val kotlinOrigin get() = null
|
||||
|
||||
override fun hasModifierProperty(name: String) =
|
||||
when (name) {
|
||||
PsiModifier.DEFAULT -> hasImplementation
|
||||
PsiModifier.ABSTRACT -> !hasImplementation
|
||||
PsiModifier.FINAL -> isFinal
|
||||
else -> baseMethod.hasModifierProperty(name)
|
||||
}
|
||||
|
||||
override fun getParameterList(): PsiParameterList {
|
||||
return LightParameterListBuilder(manager, KotlinLanguage.INSTANCE).apply {
|
||||
baseMethod.parameterList.parameters.forEachIndexed { index, paramFromJava ->
|
||||
val type = providedSignature?.parameterTypes?.get(index) ?: substituteType(paramFromJava.type)
|
||||
addParameter(
|
||||
LightParameter(paramFromJava.name ?: "p$index", type,
|
||||
this@KtLightMethodWrapper, KotlinLanguage.INSTANCE, paramFromJava.isVarArgs)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getName() = name
|
||||
override fun getReturnType() = providedSignature?.returnType ?: baseMethod.returnType?.let { substituteType(it) }
|
||||
|
||||
override fun getTypeParameters() = baseMethod.typeParameters
|
||||
override fun getTypeParameterList() = baseMethod.typeParameterList
|
||||
|
||||
override fun findSuperMethods(checkAccess: Boolean) = PsiSuperMethodImplUtil.findSuperMethods(this, checkAccess)
|
||||
override fun findSuperMethods(parentClass: PsiClass) = PsiSuperMethodImplUtil.findSuperMethods(this, parentClass)
|
||||
override fun findSuperMethods() = PsiSuperMethodImplUtil.findSuperMethods(this)
|
||||
override fun findSuperMethodSignaturesIncludingStatic(checkAccess: Boolean) = PsiSuperMethodImplUtil.findSuperMethodSignaturesIncludingStatic(this, checkAccess)
|
||||
@Suppress("OverridingDeprecatedMember") override fun findDeepestSuperMethod() = PsiSuperMethodImplUtil.findDeepestSuperMethod(this)
|
||||
override fun findDeepestSuperMethods() = PsiSuperMethodImplUtil.findDeepestSuperMethods(this)
|
||||
override fun getHierarchicalMethodSignature() = PsiSuperMethodImplUtil.getHierarchicalMethodSignature(this)
|
||||
override fun getSignature(substitutor: PsiSubstitutor) = MethodSignatureBackedByPsiMethod.create(this, substitutor)
|
||||
override fun getReturnTypeElement(): PsiTypeElement? = null
|
||||
override fun getContainingClass() = containingClass
|
||||
override fun getThrowsList() = baseMethod.throwsList
|
||||
override fun hasTypeParameters() = baseMethod.hasTypeParameters()
|
||||
override fun isVarArgs() = baseMethod.isVarArgs
|
||||
override fun isConstructor() = false
|
||||
private val identifier by lazyPub { LightIdentifier(manager, name) }
|
||||
override fun getNameIdentifier() = identifier
|
||||
override fun getDocComment() = baseMethod.docComment
|
||||
override fun getModifierList() = baseMethod.modifierList
|
||||
override fun getBody() = null
|
||||
override fun isDeprecated() = baseMethod.isDeprecated
|
||||
override fun setName(name: String) = cannotModify()
|
||||
|
||||
override fun toString(): String {
|
||||
return "$javaClass:$name${parameterList.parameters.map { it.type }.joinToString(prefix = "(", postfix = ")", separator = ", ")}"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
abstract class KtAbstractContainerWrapper(internal val fqName: FqName, private val superInterface: PsiClass)
|
||||
: LightElement(superInterface.manager, KotlinLanguage.INSTANCE), PsiExtensibleClass {
|
||||
|
||||
private val memberCache = ClassInnerStuffCache(this)
|
||||
|
||||
private val superClassTypeParametersToMyTypeParameters: Map<PsiTypeParameter, PsiTypeParameter>
|
||||
= superInterface.typeParameters
|
||||
.mapIndexed { index, supersParameter ->
|
||||
supersParameter to LightTypeParameterBuilder(supersParameter.name ?: "T$index", this, index)
|
||||
}
|
||||
.toMap()
|
||||
|
||||
internal val substitutor = createSubstitutor(superClassTypeParametersToMyTypeParameters.mapValues {
|
||||
it.value.asType()
|
||||
})
|
||||
|
||||
override fun getSupers() = arrayOf(superInterface)
|
||||
|
||||
override fun getQualifiedName() = fqName.asString()
|
||||
|
||||
override fun toString() = "$javaClass:$name"
|
||||
|
||||
override fun hasModifierProperty(name: String) = name == PsiModifier.PUBLIC || name == PsiModifier.ABSTRACT
|
||||
|
||||
private val _typeParameterList by lazyPub {
|
||||
LightTypeParameterListBuilder(manager, KotlinLanguage.INSTANCE).apply {
|
||||
superClassTypeParametersToMyTypeParameters.values.forEach { addParameter(it) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getTypeParameterList() = _typeParameterList
|
||||
|
||||
private val identifier by lazyPub { LightIdentifier(manager, name) }
|
||||
override fun getNameIdentifier() = identifier
|
||||
|
||||
override fun getName() = fqName.shortName().asString()
|
||||
|
||||
private val _implementsList by lazyPub {
|
||||
LightReferenceListBuilder(manager, PsiReferenceList.Role.IMPLEMENTS_LIST).apply {
|
||||
addReference(superInterface)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getImplementsList() = _implementsList
|
||||
|
||||
override fun getSuperTypes() = arrayOf(PsiImmediateClassType(superInterface, substitutor))
|
||||
|
||||
override fun getMethods() = memberCache.methods
|
||||
|
||||
override fun getTypeParameters() = superClassTypeParametersToMyTypeParameters.values.toTypedArray()
|
||||
|
||||
override fun getInterfaces() = arrayOf(superInterface)
|
||||
|
||||
override fun getInitializers() = PsiClassInitializer.EMPTY_ARRAY
|
||||
|
||||
override fun getContainingClass() = null
|
||||
|
||||
override fun getFields() = PsiField.EMPTY_ARRAY
|
||||
|
||||
override fun isInterface() = true
|
||||
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean) = InheritanceImplUtil.isInheritor(this, baseClass, checkDeep)
|
||||
override fun getOwnInnerClasses() = emptyList<PsiClass>()
|
||||
override fun getSuperClass() = null
|
||||
override fun findInnerClassByName(name: String?, checkBases: Boolean) = null
|
||||
override fun getExtendsListTypes() = PsiClassType.EMPTY_ARRAY
|
||||
override fun isInheritorDeep(baseClass: PsiClass, classToByPass: PsiClass?) = InheritanceImplUtil.isInheritorDeep(this, baseClass, classToByPass)
|
||||
override fun isAnnotationType() = false
|
||||
override fun findMethodsAndTheirSubstitutorsByName(name: String?, checkBases: Boolean)
|
||||
= PsiClassImplUtil.findMethodsAndTheirSubstitutorsByName(this, name, checkBases)
|
||||
|
||||
override fun getInnerClasses() = PsiClass.EMPTY_ARRAY
|
||||
override fun findMethodBySignature(patternMethod: PsiMethod, checkBases: Boolean)
|
||||
= PsiClassImplUtil.findMethodBySignature(this, patternMethod, checkBases)
|
||||
|
||||
override fun findFieldByName(name: String?, checkBases: Boolean) = null
|
||||
override fun getAllFields() = PsiClassImplUtil.getAllFields(this)
|
||||
override fun getAllInnerClasses() = PsiClassImplUtil.getAllInnerClasses(this)
|
||||
override fun findMethodsByName(name: String?, checkBases: Boolean) = memberCache.findMethodsByName(name, checkBases)
|
||||
override fun getAllMethods() = PsiClassImplUtil.getAllMethods(this)
|
||||
override fun getOwnFields() = emptyList<PsiField>()
|
||||
override fun getAllMethodsAndTheirSubstitutors() =
|
||||
PsiClassImplUtil.getAllWithSubstitutorsByMap<PsiMethod>(this, PsiClassImplUtil.MemberType.METHOD)
|
||||
|
||||
override fun hasTypeParameters() = true
|
||||
override fun getRBrace() = null
|
||||
override fun getLBrace() = null
|
||||
override fun getVisibleSignatures() = PsiSuperMethodImplUtil.getVisibleSignatures(this)
|
||||
override fun getExtendsList() = null
|
||||
override fun getDocComment() = null
|
||||
override fun isEnum() = false
|
||||
private val _modifierList by lazyPub { LightModifierList(manager, KotlinLanguage.INSTANCE, PsiModifier.PUBLIC) }
|
||||
override fun getModifierList() = _modifierList
|
||||
override fun getScope() = superInterface.scope
|
||||
override fun getImplementsListTypes() = superTypes
|
||||
override fun getConstructors() = PsiMethod.EMPTY_ARRAY
|
||||
override fun isDeprecated() = false
|
||||
override fun setName(name: String) = cannotModify()
|
||||
override fun findMethodsBySignature(patternMethod: PsiMethod, checkBases: Boolean)
|
||||
= PsiClassImplUtil.findMethodsBySignature(this, patternMethod, checkBases)
|
||||
}
|
||||
|
||||
private fun PsiTypeParameter.asType() = PsiImmediateClassType(this, PsiSubstitutor.EMPTY)
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
public class EtendingMutableInterfaces {
|
||||
public static class Lists {
|
||||
<error>public static class ExtendIList1 implements IMutableList<String></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendIList2<E> implements IMutableList<E></error> {
|
||||
|
||||
}
|
||||
|
||||
// Compiler bug causes remove(int) to clash https://youtrack.jetbrains.com/issue/KT-17782
|
||||
//public static class ExtendCList1<E> extends CMutableList<E> {
|
||||
//
|
||||
//}
|
||||
//
|
||||
//public static class ExtendCList2<E> extends CMutableList<String> {
|
||||
//
|
||||
//}
|
||||
|
||||
public static class ExtendSList extends SMutableList {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendAList extends AMutableList {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class Collections {
|
||||
<error>public static class ExtendICollection1 implements IMutableCollection<String></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendICollection2<E> implements IMutableCollection<E></error> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCCollection1<E> extends CMutableCollection<E> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCCollection2<E> extends CMutableCollection<String> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendSCollection extends SMutableCollection {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendACollection extends AMutableCollection {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class Sets {
|
||||
<error>public static class ExtendISet1 implements IMutableSet<String></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendISet2<E> implements IMutableSet<E></error> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCSet1<E> extends CMutableSet<E> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCSet2<E> extends CMutableSet<String> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendSSet extends SMutableSet {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendASet extends AMutableSet {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class Iterables {
|
||||
<error>public static class ExtendIIterable1 implements IMutableIterable<String></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendIIterable2<E> implements IMutableIterable<E></error> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCIterable1<E> extends CMutableIterable<E> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCIterable2<E> extends CMutableIterable<String> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendSIterable extends SMutableIterable {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendAIterable extends AMutableIterable {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class Iterators {
|
||||
<error>public static class ExtendIIterator1 implements IMutableIterator<String></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendIIterator2<E> implements IMutableIterator<E></error> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCIterator1<E> extends CMutableIterator<E> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCIterator2<E> extends CMutableIterator<String> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendSIterator extends SMutableIterator {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendAIterator extends AMutableIterator {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class Maps {
|
||||
<error>public static class ExtendIMap1 implements IMutableMap<String, Integer></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendIMap2<E> implements IMutableMap<String, E></error> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCMap1<K, V> extends CMutableMap<K, V> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCMap2<V> extends CMutableMap<String, V> {
|
||||
|
||||
}
|
||||
|
||||
// NOTE: looks like a bug in compiler see KT-17738
|
||||
|
||||
//public static class ExtendSMap extends SMutableMap<A> {
|
||||
//
|
||||
//}
|
||||
//
|
||||
//public static class ExtendABMap extends ABMutableMap {
|
||||
//
|
||||
//}
|
||||
}
|
||||
|
||||
public static class MapEntrys {
|
||||
<error>public static class ExtendIMapEntry1 implements IMutableMapEntry<String, Integer></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendIMapEntry2<E> implements IMutableMapEntry<String, E></error> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCMapEntry1<K, V> extends CMutableMapEntry<K, V> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCMapEntry2<V> extends CMutableMapEntry<String, V> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendSMapEntry extends SMutableMapEntry<A> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendAMapEntry extends ABMutableMapEntry {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
class A
|
||||
class B
|
||||
|
||||
// kotlin.collection.MutableCollection
|
||||
interface IMutableCollection<Elem> : MutableCollection<Elem>
|
||||
abstract class CMutableCollection<Elem> : MutableCollection<Elem> by mutableListOf<Elem>()
|
||||
abstract class SMutableCollection : MutableCollection<String> by mutableListOf<String>()
|
||||
abstract class AMutableCollection : MutableCollection<A> by mutableListOf<A>()
|
||||
|
||||
// kotlin.collections.MutableIterable
|
||||
interface IMutableIterable<Elem> : MutableIterable<Elem>
|
||||
abstract class CMutableIterable<Elem> : MutableIterable<Elem> by mutableListOf<Elem>()
|
||||
abstract class SMutableIterable : MutableIterable<String> by mutableListOf<String>()
|
||||
abstract class AMutableIterable : MutableIterable<A> by mutableListOf<A>()
|
||||
|
||||
// kotlin.collections.MutableList
|
||||
interface IMutableList<Elem> : MutableList<Elem>
|
||||
abstract class CMutableList<Elem> : MutableList<Elem> by mutableListOf<Elem>()
|
||||
abstract class SMutableList : MutableList<String> by mutableListOf<String>()
|
||||
abstract class AMutableList : MutableList<A> by mutableListOf<A>()
|
||||
|
||||
// kotlin.collections.Set
|
||||
interface IMutableSet<Elem> : MutableSet<Elem>
|
||||
abstract class CMutableSet<Elem> : MutableSet<Elem> by mutableSetOf<Elem>()
|
||||
abstract class SMutableSet : MutableSet<String> by mutableSetOf<String>()
|
||||
abstract class AMutableSet : MutableSet<A> by mutableSetOf<A>()
|
||||
|
||||
// kotlin.collections.Iterator
|
||||
interface IMutableIterator<Elem> : MutableIterator<Elem>
|
||||
abstract class CMutableIterator<Elem> : MutableIterator<Elem> by mutableListOf<Elem>().iterator()
|
||||
abstract class SMutableIterator : MutableIterator<String> by mutableListOf<String>().iterator()
|
||||
abstract class AMutableIterator : MutableIterator<A> by mutableListOf<A>().iterator()
|
||||
|
||||
// kotlin.collections.Map
|
||||
interface IMutableMap<KElem, VElem> : MutableMap<KElem, VElem>
|
||||
abstract class CMutableMap<KElem, VElem> : MutableMap<KElem, VElem> by mutableMapOf<KElem, VElem>()
|
||||
abstract class SMutableMap<VElem> : MutableMap<String, VElem> by mutableMapOf<String, VElem>()
|
||||
abstract class ABMutableMap : MutableMap<A, B> by mutableMapOf<A, B>()
|
||||
|
||||
// kotlin.collections.Map.Entry
|
||||
interface IMutableMapEntry<KElem, VElem> : MutableMap.MutableEntry<KElem, VElem>
|
||||
abstract class CMutableMapEntry<KElem, VElem> : MutableMap.MutableEntry<KElem, VElem> by mutableMapOf<KElem, VElem>().entries.first()
|
||||
abstract class SMutableMapEntry<VElem> : MutableMap.MutableEntry<String, VElem> by mutableMapOf<String, VElem>().entries.first()
|
||||
abstract class ABMutableMapEntry : MutableMap.MutableEntry<A, B> by mutableMapOf<A, B>().entries.first()
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
public class EtendingReadOnlyInterfaces {
|
||||
public static class Lists {
|
||||
<error>public static class ExtendIList1 implements IList<String></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendIList2<E> implements IList<E></error> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCList1<E> extends CList<E> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCList2<E> extends CList<String> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendSList extends SList {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendAList extends AList {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class Collections {
|
||||
<error>public static class ExtendICollection1 implements ICollection<String></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendICollection2<E> implements ICollection<E></error> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCCollection1<E> extends CCollection<E> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCCollection2<E> extends CCollection<String> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendSCollection extends SCollection {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendACollection extends ACollection {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class Sets {
|
||||
<error>public static class ExtendISet1 implements ISet<String></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendISet2<E> implements ISet<E></error> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCSet1<E> extends CSet<E> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCSet2<E> extends CSet<String> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendSSet extends SSet {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendASet extends ASet {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class Iterables {
|
||||
<error>public static class ExtendIIterable1 implements IIterable<String></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendIIterable2<E> implements IIterable<E></error> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCIterable1<E> extends CIterable<E> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCIterable2<E> extends CIterable<String> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendSIterable extends SIterable {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendAIterable extends AIterable {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class Iterators {
|
||||
<error>public static class ExtendIIterator1 implements IIterator<String></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendIIterator2<E> implements IIterator<E></error> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCIterator1<E> extends CIterator<E> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCIterator2<E> extends CIterator<String> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendSIterator extends SIterator {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendAIterator extends AIterator {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class Maps {
|
||||
<error>public static class ExtendIMap1 implements IMap<String, Integer></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendIMap2<E> implements IMap<String, E></error> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCMap1<K, V> extends CMap<K, V> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCMap2<V> extends CMap<String, V> {
|
||||
|
||||
}
|
||||
|
||||
// NOTE: looks like a bug in compiler see KT-17738
|
||||
|
||||
//public static class ExtendSMap extends SMap<A> {
|
||||
//
|
||||
//}
|
||||
//
|
||||
//public static class ExtendABMap extends ABMap {
|
||||
//
|
||||
//}
|
||||
}
|
||||
|
||||
public static class MapEntrys {
|
||||
<error>public static class ExtendIMapEntry1 implements IMapEntry<String, Integer></error> {
|
||||
|
||||
}
|
||||
|
||||
<error>public static class ExtendIMapEntry2<E> implements IMapEntry<String, E></error> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCMapEntry1<K, V> extends CMapEntry<K, V> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendCMapEntry2<V> extends CMapEntry<String, V> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendSMapEntry extends SMapEntry<A> {
|
||||
|
||||
}
|
||||
|
||||
public static class ExtendAMapEntry extends ABMapEntry {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
class A
|
||||
class B
|
||||
|
||||
// kotlin.collections.Collection
|
||||
interface ICollection<Elem> : Collection<Elem>
|
||||
abstract class CCollection<Elem> : Collection<Elem> by emptyList<Elem>()
|
||||
abstract class SCollection : Collection<String> by emptyList<String>()
|
||||
abstract class ACollection : Collection<A> by emptyList<A>()
|
||||
|
||||
// kotlin.collections.Iterable
|
||||
interface IIterable<Elem> : Iterable<Elem>
|
||||
abstract class CIterable<Elem> : Iterable<Elem> by emptyList<Elem>()
|
||||
abstract class SIterable : Iterable<String> by emptyList<String>()
|
||||
abstract class AIterable : Iterable<A> by emptyList<A>()
|
||||
|
||||
// kotlin.collections.List
|
||||
interface IList<Elem> : List<Elem>
|
||||
abstract class CList<Elem> : List<Elem> by emptyList<Elem>()
|
||||
abstract class SList : List<String> by emptyList<String>()
|
||||
abstract class AList : List<A> by emptyList<A>()
|
||||
|
||||
// kotlin.collections.Set
|
||||
interface ISet<Elem> : Set<Elem>
|
||||
abstract class CSet<Elem> : Set<Elem> by emptySet<Elem>()
|
||||
abstract class SSet : Set<String> by emptySet<String>()
|
||||
abstract class ASet : Set<A> by emptySet<A>()
|
||||
|
||||
// kotlin.collections.Iterator
|
||||
interface IIterator<Elem> : Iterator<Elem>
|
||||
abstract class CIterator<Elem> : Iterator<Elem> by emptyList<Elem>().iterator()
|
||||
abstract class SIterator : Iterator<String> by emptyList<String>().iterator()
|
||||
abstract class AIterator : Iterator<A> by emptyList<A>().iterator()
|
||||
|
||||
// kotlin.collections.Map
|
||||
interface IMap<KElem, VElem> : Map<KElem, VElem>
|
||||
abstract class CMap<KElem, VElem> : Map<KElem, VElem> by emptyMap<KElem, VElem>()
|
||||
abstract class SMap<VElem> : Map<String, VElem> by emptyMap<String, VElem>()
|
||||
abstract class ABMap : Map<A, B> by emptyMap<A, B>()
|
||||
|
||||
// kotlin.collections.Map.Entry
|
||||
interface IMapEntry<KElem, VElem> : Map.Entry<KElem, VElem>
|
||||
abstract class CMapEntry<KElem, VElem> : Map.Entry<KElem, VElem> by emptyMap<KElem, VElem>().entries.first()
|
||||
abstract class SMapEntry<VElem> : Map.Entry<String, VElem> by emptyMap<String, VElem>().entries.first()
|
||||
abstract class ABMapEntry : Map.Entry<A, B> by emptyMap<A, B>().entries.first()
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
public class UsingMutableInterfaces {
|
||||
public static class Lists {
|
||||
public static <E> void useCMutableList(CMutableList<E> cMutableList, E elem, java.util.Collection<E> other) {
|
||||
java.util.Iterator<E> iter = cMutableList.iterator();
|
||||
cMutableList.addAll(other);
|
||||
cMutableList.add(elem);
|
||||
cMutableList.isEmpty();
|
||||
cMutableList.clear();
|
||||
cMutableList.getSize();
|
||||
cMutableList.size();
|
||||
boolean b = cMutableList.remove(elem);
|
||||
E e1 = cMutableList.remove(3);
|
||||
E e2 = cMutableList.removeAt(6);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
// kotlin.collections.List
|
||||
abstract class CMutableList<Elem> : MutableList<Elem> by mutableListOf<Elem>()
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
public class UsingReadOnlyInterfaces {
|
||||
public static class Collections {
|
||||
public static <E> void useICollection(ICollection<E> iCollection, E elem, java.util.Collection<E> other) {
|
||||
java.util.Iterator<E> iter = iCollection.iterator();
|
||||
iCollection.addAll(other);
|
||||
iCollection.add(elem);
|
||||
iCollection.isEmpty();
|
||||
iCollection.clear();
|
||||
iCollection.<error>getSize</error>(); // this is not an error when analyzing against kotlin sources (which is a bug), this inconsistency is hard to fix with the current approach
|
||||
iCollection.size();
|
||||
}
|
||||
|
||||
public static <E> void useCCollection(CCollection<E> cCollection, E elem, java.util.Collection<E> other) {
|
||||
java.util.Iterator<E> iter = cCollection.iterator();
|
||||
cCollection.addAll(other);
|
||||
cCollection.add(elem);
|
||||
cCollection.isEmpty();
|
||||
cCollection.clear();
|
||||
cCollection.getSize();
|
||||
cCollection.size();
|
||||
cCollection.contains(elem);
|
||||
cCollection.contains("sasd");
|
||||
cCollection.removeAll(other);
|
||||
cCollection.retainAll(other);
|
||||
}
|
||||
|
||||
public static class ExtendCCollection extends CCollection<String> {
|
||||
@Override
|
||||
public void clear() {}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Maps {
|
||||
public static <E, V> void useCMap(CMap<E, V> cMap) {
|
||||
cMap.isEmpty();
|
||||
java.util.Set<E> s = cMap.getKeys();
|
||||
s = cMap.keySet();
|
||||
java.util.Collection<V> v = cMap.getValues();
|
||||
v = cMap.values();
|
||||
java.util.Set<java.util.Map.Entry<E, V>> e = cMap.entrySet();
|
||||
e = cMap.getEntries();
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
class A
|
||||
class B
|
||||
|
||||
// kotlin.collections.Collection
|
||||
interface ICollection<Elem> : Collection<Elem>
|
||||
abstract class CCollection<Elem> : Collection<Elem> by emptyList<Elem>()
|
||||
abstract class SCollection : Collection<String> by emptyList<String>()
|
||||
abstract class ACollection : Collection<A> by emptyList<A>()
|
||||
|
||||
// kotlin.collections.Iterable
|
||||
interface IIterable<Elem> : Iterable<Elem>
|
||||
abstract class CIterable<Elem> : Iterable<Elem> by emptyList<Elem>()
|
||||
abstract class SIterable : Iterable<String> by emptyList<String>()
|
||||
abstract class AIterable : Iterable<A> by emptyList<A>()
|
||||
|
||||
// kotlin.collections.List
|
||||
interface IList<Elem> : List<Elem>
|
||||
abstract class CList<Elem> : List<Elem> by emptyList<Elem>()
|
||||
abstract class SList : List<String> by emptyList<String>()
|
||||
abstract class AList : List<A> by emptyList<A>()
|
||||
|
||||
// kotlin.collections.Set
|
||||
interface ISet<Elem> : Set<Elem>
|
||||
abstract class CSet<Elem> : Set<Elem> by emptySet<Elem>()
|
||||
abstract class SSet : Set<String> by emptySet<String>()
|
||||
abstract class ASet : Set<A> by emptySet<A>()
|
||||
|
||||
// kotlin.collections.Iterator
|
||||
interface IIterator<Elem> : Iterator<Elem>
|
||||
abstract class CIterator<Elem> : Iterator<Elem> by emptyList<Elem>().iterator()
|
||||
abstract class SIterator : Iterator<String> by emptyList<String>().iterator()
|
||||
abstract class AIterator : Iterator<A> by emptyList<A>().iterator()
|
||||
|
||||
// kotlin.collections.Map
|
||||
interface IMap<KElem, VElem> : Map<KElem, VElem>
|
||||
abstract class CMap<KElem, VElem> : Map<KElem, VElem> by emptyMap<KElem, VElem>()
|
||||
abstract class SMap<VElem> : Map<String, VElem> by emptyMap<String, VElem>()
|
||||
abstract class ABMap : Map<A, B> by emptyMap<A, B>()
|
||||
|
||||
// kotlin.collections.Map.Entry
|
||||
interface IMapEntry<KElem, VElem> : Map.Entry<KElem, VElem>
|
||||
abstract class CMapEntry<KElem, VElem> : Map.Entry<KElem, VElem> by emptyMap<KElem, VElem>().entries.first()
|
||||
abstract class SMapEntry<VElem> : Map.Entry<String, VElem> by emptyMap<String, VElem>().entries.first()
|
||||
abstract class ABMapEntry : Map.Entry<A, B> by emptyMap<A, B>().entries.first()
|
||||
+24
@@ -90,6 +90,18 @@ public class JavaAgainstKotlinBinariesCheckerTestGenerated extends AbstractJavaA
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ExtendingMutableInterfaces.kt")
|
||||
public void testExtendingMutableInterfaces() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendingMutableInterfaces.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ExtendingReadOnlyInterfaces.kt")
|
||||
public void testExtendingReadOnlyInterfaces() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendingReadOnlyInterfaces.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("FunctionInNestedClassInDataFlowInspection.kt")
|
||||
public void testFunctionInNestedClassInDataFlowInspection() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/FunctionInNestedClassInDataFlowInspection.kt");
|
||||
@@ -179,4 +191,16 @@ public class JavaAgainstKotlinBinariesCheckerTestGenerated extends AbstractJavaA
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/UsingKotlinPackageDeclarations.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("UsingMutableInterfaces.kt")
|
||||
public void testUsingMutableInterfaces() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/UsingMutableInterfaces.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("UsingReadOnlyInterfaces.kt")
|
||||
public void testUsingReadOnlyInterfaces() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/UsingReadOnlyInterfaces.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
+24
@@ -92,6 +92,18 @@ public class JavaAgainstKotlinSourceCheckerTestGenerated extends AbstractJavaAga
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ExtendingMutableInterfaces.kt")
|
||||
public void testExtendingMutableInterfaces() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendingMutableInterfaces.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ExtendingReadOnlyInterfaces.kt")
|
||||
public void testExtendingReadOnlyInterfaces() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ExtendingReadOnlyInterfaces.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("FunctionInNestedClassInDataFlowInspection.kt")
|
||||
public void testFunctionInNestedClassInDataFlowInspection() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/FunctionInNestedClassInDataFlowInspection.kt");
|
||||
@@ -181,6 +193,18 @@ public class JavaAgainstKotlinSourceCheckerTestGenerated extends AbstractJavaAga
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/UsingKotlinPackageDeclarations.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("UsingMutableInterfaces.kt")
|
||||
public void testUsingMutableInterfaces() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/UsingMutableInterfaces.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("UsingReadOnlyInterfaces.kt")
|
||||
public void testUsingReadOnlyInterfaces() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/UsingReadOnlyInterfaces.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/kotlinAndJavaChecker/javaWithKotlin")
|
||||
|
||||
@@ -236,6 +236,18 @@ public class IdeLightClassTestGenerated extends AbstractIdeLightClassTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/ideRegression"), Pattern.compile("^([^.]+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("ImplementingMap.kt")
|
||||
public void testImplementingMap() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/ideRegression/ImplementingMap.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ImplementingMutableSet.kt")
|
||||
public void testImplementingMutableSet() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/ideRegression/ImplementingMutableSet.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InheritingInterfaceDefaultImpls.kt")
|
||||
public void testInheritingInterfaceDefaultImpls() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/ideRegression/InheritingInterfaceDefaultImpls.kt");
|
||||
|
||||
Reference in New Issue
Block a user