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:
Pavel V. Talanov
2017-05-03 14:34:32 +03:00
parent c56f74cc81
commit 798c80ed07
24 changed files with 1182 additions and 25 deletions
@@ -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);
@@ -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()
}
@@ -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>
@@ -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")
}
}
@@ -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 */ }
}
}
@@ -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>
}
}
@@ -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
@@ -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)
}
@@ -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>,
@@ -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)
@@ -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 {
}
}
}
@@ -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()
@@ -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 {
}
}
}
@@ -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()
@@ -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);
}
}
}
@@ -0,0 +1,2 @@
// kotlin.collections.List
abstract class CMutableList<Elem> : MutableList<Elem> by mutableListOf<Elem>()
@@ -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();
}
}
}
@@ -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()
@@ -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);
}
}
@@ -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");