[Commonizer] Classifiers
This commit is contained in:
@@ -159,8 +159,11 @@ public final class FqNameUnsafe {
|
||||
}
|
||||
|
||||
public boolean startsWith(@NotNull Name segment) {
|
||||
if (isRoot())
|
||||
return false;
|
||||
|
||||
int firstDot = fqName.indexOf('.');
|
||||
return !isRoot() && fqName.regionMatches(0, segment.asString(), 0, firstDot == -1 ? fqName.length() : firstDot);
|
||||
return fqName.regionMatches(0, segment.asString(), 0, firstDot == -1 ? fqName.length() : firstDot);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.builder
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorBase
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.computeSealedSubclasses
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.StaticScopeForKotlinEnum
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.AbstractClassTypeConstructor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
||||
|
||||
class CommonizedClassDescriptor(
|
||||
storageManager: StorageManager,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
override val annotations: Annotations,
|
||||
name: Name,
|
||||
private val kind: ClassKind,
|
||||
private val modality: Modality,
|
||||
private val visibility: Visibility,
|
||||
private val isCompanion: Boolean,
|
||||
private val isData: Boolean,
|
||||
private val isInline: Boolean,
|
||||
private val isInner: Boolean,
|
||||
isExternal: Boolean,
|
||||
private val isExpect: Boolean,
|
||||
private val isActual: Boolean,
|
||||
companionObjectName: Name?,
|
||||
supertypes: Collection<KotlinType>
|
||||
) : ClassDescriptorBase(storageManager, containingDeclaration, name, SourceElement.NO_SOURCE, isExternal) {
|
||||
private lateinit var _unsubstitutedMemberScope: MemberScope
|
||||
private lateinit var constructors: Collection<ClassConstructorDescriptor>
|
||||
private var primaryConstructor: ClassConstructorDescriptor? = null
|
||||
private val staticScope = if (kind == ClassKind.ENUM_CLASS) StaticScopeForKotlinEnum(storageManager, this) else MemberScope.Empty
|
||||
private lateinit var declaredTypeParameters: List<TypeParameterDescriptor>
|
||||
private val typeConstructor = CommonizedClassTypeConstructor(storageManager, supertypes)
|
||||
private val sealedSubclasses = storageManager.createLazyValue { computeSealedSubclasses(this) }
|
||||
|
||||
private val companionObjectDescriptor = storageManager.createNullableLazyValue {
|
||||
if (companionObjectName != null)
|
||||
unsubstitutedMemberScope.getContributedClassifier(companionObjectName, NoLookupLocation.FOR_ALREADY_TRACKED) as? ClassDescriptor
|
||||
else
|
||||
null
|
||||
}
|
||||
|
||||
override fun getKind() = kind
|
||||
override fun getModality() = modality
|
||||
override fun getVisibility() = visibility
|
||||
override fun isCompanionObject() = isCompanion
|
||||
override fun isData() = isData
|
||||
override fun isInline() = isInline
|
||||
override fun isInner() = isInner
|
||||
override fun isExpect() = isExpect
|
||||
override fun isActual() = isActual
|
||||
|
||||
override fun getUnsubstitutedMemberScope(kotlinTypeRefiner: KotlinTypeRefiner): MemberScope {
|
||||
check(kotlinTypeRefiner == KotlinTypeRefiner.Default) {
|
||||
"${kotlinTypeRefiner::class.java} is not supported in ${this::class.java}"
|
||||
}
|
||||
return _unsubstitutedMemberScope
|
||||
}
|
||||
|
||||
override fun getDeclaredTypeParameters() = declaredTypeParameters
|
||||
fun setDeclaredTypeParameters(declaredTypeParameters: List<TypeParameterDescriptor>) {
|
||||
this.declaredTypeParameters = declaredTypeParameters
|
||||
}
|
||||
|
||||
override fun getConstructors() = constructors
|
||||
override fun getUnsubstitutedPrimaryConstructor() = primaryConstructor
|
||||
override fun getStaticScope(): MemberScope = staticScope
|
||||
override fun getTypeConstructor(): TypeConstructor = typeConstructor
|
||||
override fun getCompanionObjectDescriptor() = companionObjectDescriptor()
|
||||
override fun getSealedSubclasses() = sealedSubclasses()
|
||||
|
||||
fun initialize(
|
||||
unsubstitutedMemberScope: MemberScope,
|
||||
constructors: Collection<CommonizedClassConstructorDescriptor>
|
||||
) {
|
||||
_unsubstitutedMemberScope = unsubstitutedMemberScope
|
||||
|
||||
if (isExpect && kind.isSingleton) {
|
||||
check(constructors.isEmpty())
|
||||
|
||||
primaryConstructor = createPrimaryConstructorForObject(this, SourceElement.NO_SOURCE).apply { returnType = getDefaultType() }
|
||||
this.constructors = listOf(primaryConstructor!!)
|
||||
} else {
|
||||
constructors.forEach { it.returnType = getDefaultType() }
|
||||
|
||||
primaryConstructor = constructors.firstOrNull { it.isPrimary }
|
||||
this.constructors = constructors
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString() = (if (isExpect) "expect " else if (isActual) "actual " else "") + "class " + name.toString()
|
||||
|
||||
private inner class CommonizedClassTypeConstructor(
|
||||
storageManager: StorageManager,
|
||||
private val computedSupertypes: Collection<KotlinType>
|
||||
) : AbstractClassTypeConstructor(storageManager) {
|
||||
private val parameters = storageManager.createLazyValue {
|
||||
this@CommonizedClassDescriptor.computeConstructorTypeParameters()
|
||||
}
|
||||
|
||||
override fun getParameters() = parameters()
|
||||
override fun computeSupertypes() = computedSupertypes
|
||||
override fun isDenotable() = true
|
||||
override fun getDeclarationDescriptor() = this@CommonizedClassDescriptor
|
||||
override val supertypeLoopChecker get() = SupertypeLoopChecker.EMPTY
|
||||
}
|
||||
}
|
||||
|
||||
class CommonizedClassConstructorDescriptor(
|
||||
containingDeclaration: ClassDescriptor,
|
||||
annotations: Annotations,
|
||||
isPrimary: Boolean,
|
||||
kind: CallableMemberDescriptor.Kind
|
||||
) : ClassConstructorDescriptorImpl(containingDeclaration, null, annotations, isPrimary, kind, SourceElement.NO_SOURCE)
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.builder
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.AbstractTypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.asSimpleType
|
||||
|
||||
class CommonizedTypeAliasDescriptor(
|
||||
override val storageManager: StorageManager,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
annotations: Annotations,
|
||||
name: Name,
|
||||
visibility: Visibility,
|
||||
private val isActual: Boolean
|
||||
) : AbstractTypeAliasDescriptor(containingDeclaration, annotations, name, SourceElement.NO_SOURCE, visibility) {
|
||||
|
||||
override lateinit var underlyingType: SimpleType
|
||||
override lateinit var expandedType: SimpleType
|
||||
|
||||
private lateinit var defaultType: SimpleType
|
||||
override fun getDefaultType() = defaultType
|
||||
|
||||
override val classDescriptor get() = expandedType.constructor.declarationDescriptor as? ClassDescriptor
|
||||
|
||||
private lateinit var typeConstructorParameters: List<TypeParameterDescriptor>
|
||||
override fun getTypeConstructorTypeParameters() = typeConstructorParameters
|
||||
|
||||
override lateinit var constructors: Collection<TypeAliasConstructorDescriptor>
|
||||
|
||||
override fun isActual() = isActual
|
||||
|
||||
fun initialize(underlyingType: SimpleType, expandedType: SimpleType) {
|
||||
super.initialize(emptyList())
|
||||
this.underlyingType = underlyingType
|
||||
this.expandedType = expandedType
|
||||
typeConstructorParameters = computeConstructorTypeParameters()
|
||||
defaultType = computeDefaultType()
|
||||
constructors = getTypeAliasConstructors()
|
||||
}
|
||||
|
||||
override fun substitute(substitutor: TypeSubstitutor): ClassifierDescriptorWithTypeParameters {
|
||||
if (substitutor.isEmpty) return this
|
||||
val substituted = CommonizedTypeAliasDescriptor(
|
||||
storageManager = storageManager,
|
||||
containingDeclaration = containingDeclaration,
|
||||
annotations = annotations,
|
||||
name = name,
|
||||
visibility = visibility,
|
||||
isActual = isActual
|
||||
)
|
||||
substituted.initialize(
|
||||
substitutor.safeSubstitute(underlyingType, Variance.INVARIANT).asSimpleType(),
|
||||
substitutor.safeSubstitute(expandedType, Variance.INVARIANT).asSimpleType()
|
||||
)
|
||||
return substituted
|
||||
}
|
||||
}
|
||||
+64
-2
@@ -13,16 +13,18 @@ import org.jetbrains.kotlin.descriptors.commonizer.builder.CommonizedMemberScope
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.builder.CommonizedPackageFragmentProvider.Companion.plusAssign
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
/** Builds and initializes the new tree of common descriptors */
|
||||
internal class DeclarationsBuilderVisitor(
|
||||
private val storageManager: StorageManager,
|
||||
private val builtIns: KotlinBuiltIns,
|
||||
private val collector: (TargetId, Collection<ModuleDescriptor>) -> Unit
|
||||
) : NodeVisitor<List<DeclarationDescriptor?>, List<DeclarationDescriptor?>> {
|
||||
override fun visitRootNode(node: RootNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
|
||||
val allTargets = (node.target + node.common).map { it.targetId }
|
||||
val allTargets = (node.target + node.common()!!).map { it.targetId }
|
||||
|
||||
val modulesByTargets = HashMap<TargetId, MutableList<ModuleDescriptorImpl>>()
|
||||
|
||||
@@ -63,7 +65,7 @@ internal class DeclarationsBuilderVisitor(
|
||||
}
|
||||
|
||||
// initialize module descriptors:
|
||||
moduleDescriptors.asListContaining<ModuleDescriptorImpl>().forEachIndexed { index, moduleDescriptor ->
|
||||
moduleDescriptors.forEachIndexed { index, moduleDescriptor ->
|
||||
moduleDescriptor?.initialize(packageFragmentProviders[index])
|
||||
}
|
||||
|
||||
@@ -86,6 +88,12 @@ internal class DeclarationsBuilderVisitor(
|
||||
for (functionNode in node.functions) {
|
||||
packageMemberScopes += functionNode.accept(this, packageFragments)
|
||||
}
|
||||
for (classNode in node.classes) {
|
||||
packageMemberScopes += classNode.accept(this, packageFragments)
|
||||
}
|
||||
for (typeAliasNode in node.typeAliases) {
|
||||
packageMemberScopes += typeAliasNode.accept(this, packageFragments)
|
||||
}
|
||||
|
||||
// initialize package fragments:
|
||||
packageFragments.forEachIndexed { index, packageFragment ->
|
||||
@@ -109,6 +117,60 @@ internal class DeclarationsBuilderVisitor(
|
||||
return functionDescriptorsGroup.toList()
|
||||
}
|
||||
|
||||
override fun visitClassNode(node: ClassNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
|
||||
val classesGroup = CommonizedGroup<ClassifierDescriptorWithTypeParameters>(node.dimension)
|
||||
node.buildDescriptors(classesGroup, data, storageManager)
|
||||
val classes = classesGroup.toList().asListContaining<CommonizedClassDescriptor>()
|
||||
|
||||
// build class constructors:
|
||||
val allConstructorsByTargets = Array<MutableList<CommonizedClassConstructorDescriptor>>(node.dimension) { ArrayList() }
|
||||
for (constructorNode in node.constructors) {
|
||||
val constructorsByTargets = constructorNode.accept(this, classes).asListContaining<CommonizedClassConstructorDescriptor>()
|
||||
constructorsByTargets.forEachIndexed { index, constructor ->
|
||||
if (constructor != null) allConstructorsByTargets[index].add(constructor)
|
||||
}
|
||||
}
|
||||
|
||||
// build class members:
|
||||
val classMemberScopes = CommonizedMemberScope.createArray(node.dimension)
|
||||
for (propertyNode in node.properties) {
|
||||
classMemberScopes += propertyNode.accept(this, classes)
|
||||
}
|
||||
for (functionNode in node.functions) {
|
||||
classMemberScopes += functionNode.accept(this, classes)
|
||||
}
|
||||
for (classNode in node.classes) {
|
||||
classMemberScopes += classNode.accept(this, classes)
|
||||
}
|
||||
|
||||
// initialize classes
|
||||
classes.forEachIndexed { index, clazz ->
|
||||
clazz?.initialize(classMemberScopes[index], allConstructorsByTargets[index])
|
||||
}
|
||||
|
||||
return classes
|
||||
}
|
||||
|
||||
override fun visitClassConstructorNode(node: ClassConstructorNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
|
||||
val containingDeclarations = data.asListContaining<ClassDescriptor>()
|
||||
|
||||
val constructorsGroup = CommonizedGroup<ClassConstructorDescriptor>(node.dimension)
|
||||
node.buildDescriptors(constructorsGroup, containingDeclarations)
|
||||
|
||||
return constructorsGroup.toList()
|
||||
}
|
||||
|
||||
override fun visitTypeAliasNode(node: TypeAliasNode, data: List<DeclarationDescriptor?>): List<DeclarationDescriptor?> {
|
||||
val typeAliasesGroup = CommonizedGroup<ClassifierDescriptorWithTypeParameters>(node.dimension)
|
||||
node.buildDescriptors(typeAliasesGroup, data, storageManager)
|
||||
val typeAliases = typeAliasesGroup.toList()
|
||||
|
||||
val commonClass = typeAliases[node.indexOfCommon] as CommonizedClassDescriptor?
|
||||
commonClass?.initialize(MemberScope.Empty, emptyList())
|
||||
|
||||
return typeAliases
|
||||
}
|
||||
|
||||
companion object {
|
||||
inline fun <reified T : DeclarationDescriptor> noContainingDeclarations() = emptyList<T?>()
|
||||
inline fun <reified T : DeclarationDescriptor> noReturningDeclarations() = emptyList<T?>()
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.builder
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroup
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.indexOfCommon
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
internal fun ClassNode.buildDescriptors(
|
||||
output: CommonizedGroup<ClassifierDescriptorWithTypeParameters>,
|
||||
containingDeclarations: List<DeclarationDescriptor?>,
|
||||
storageManager: StorageManager
|
||||
) {
|
||||
val commonClass = common()
|
||||
|
||||
target.forEachIndexed { index, clazz ->
|
||||
clazz?.buildDescriptor(output, index, containingDeclarations, storageManager, isActual = commonClass != null)
|
||||
}
|
||||
|
||||
commonClass?.buildDescriptor(output, indexOfCommon, containingDeclarations, storageManager, isExpect = true)
|
||||
}
|
||||
|
||||
internal fun ClassDeclaration.buildDescriptor(
|
||||
output: CommonizedGroup<in ClassifierDescriptorWithTypeParameters>,
|
||||
index: Int,
|
||||
containingDeclarations: List<DeclarationDescriptor?>,
|
||||
storageManager: StorageManager,
|
||||
isExpect: Boolean = false,
|
||||
isActual: Boolean = false
|
||||
) {
|
||||
val containingDeclaration = containingDeclarations[index] ?: error("No containing declaration for class $this")
|
||||
|
||||
val classDescriptor = CommonizedClassDescriptor(
|
||||
storageManager = storageManager,
|
||||
containingDeclaration = containingDeclaration,
|
||||
annotations = annotations,
|
||||
name = name,
|
||||
kind = kind,
|
||||
modality = modality,
|
||||
visibility = visibility,
|
||||
isCompanion = isCompanion,
|
||||
isData = isData,
|
||||
isInline = isInline,
|
||||
isInner = isInner,
|
||||
isExternal = isExternal,
|
||||
isExpect = isExpect,
|
||||
isActual = isActual,
|
||||
companionObjectName = companion?.shortName(),
|
||||
supertypes = supertypes
|
||||
)
|
||||
|
||||
classDescriptor.declaredTypeParameters = typeParameters.buildDescriptors(classDescriptor)
|
||||
|
||||
output[index] = classDescriptor
|
||||
}
|
||||
|
||||
internal fun ClassConstructorNode.buildDescriptors(
|
||||
output: CommonizedGroup<ClassConstructorDescriptor>,
|
||||
containingDeclarations: List<ClassDescriptor?>
|
||||
) {
|
||||
val commonConstructor = common()
|
||||
|
||||
target.forEachIndexed { index, constructor ->
|
||||
constructor?.buildDescriptor(output, index, containingDeclarations, isActual = commonConstructor != null)
|
||||
}
|
||||
|
||||
commonConstructor?.buildDescriptor(output, indexOfCommon, containingDeclarations, isExpect = true)
|
||||
|
||||
}
|
||||
|
||||
private fun ClassConstructor.buildDescriptor(
|
||||
output: CommonizedGroup<ClassConstructorDescriptor>,
|
||||
index: Int,
|
||||
containingDeclarations: List<ClassDescriptor?>,
|
||||
isExpect: Boolean = false,
|
||||
isActual: Boolean = false
|
||||
) {
|
||||
val containingDeclaration = containingDeclarations[index] ?: error("No containing declaration for constructor $this")
|
||||
|
||||
val constructorDescriptor = CommonizedClassConstructorDescriptor(
|
||||
containingDeclaration = containingDeclaration,
|
||||
annotations = annotations,
|
||||
isPrimary = isPrimary,
|
||||
kind = kind
|
||||
)
|
||||
|
||||
constructorDescriptor.isExpect = isExpect
|
||||
constructorDescriptor.isActual = isActual
|
||||
|
||||
constructorDescriptor.setHasStableParameterNames(hasStableParameterNames)
|
||||
constructorDescriptor.setHasSynthesizedParameterNames(hasSynthesizedParameterNames)
|
||||
|
||||
constructorDescriptor.initialize(
|
||||
valueParameters.buildDescriptors(constructorDescriptor),
|
||||
visibility,
|
||||
typeParameters.buildDescriptors(constructorDescriptor)
|
||||
)
|
||||
|
||||
output[index] = constructorDescriptor
|
||||
}
|
||||
+8
-28
@@ -8,28 +8,23 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroup
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.Function
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.FunctionNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ValueParameter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.indexOfCommon
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
internal fun FunctionNode.buildDescriptors(
|
||||
output: CommonizedGroup<SimpleFunctionDescriptor>,
|
||||
containingDeclarations: List<DeclarationDescriptor?>
|
||||
) {
|
||||
val isCommonized = common != null
|
||||
val commonFunction = common()
|
||||
|
||||
target.forEachIndexed { index, function ->
|
||||
function?.buildDescriptor(output, index, containingDeclarations, isActual = isCommonized)
|
||||
function?.buildDescriptor(output, index, containingDeclarations, isActual = commonFunction != null)
|
||||
}
|
||||
|
||||
common?.buildDescriptor(output, indexOfCommon, containingDeclarations, isExpect = isCommonized)
|
||||
commonFunction?.buildDescriptor(output, indexOfCommon, containingDeclarations, isExpect = true)
|
||||
}
|
||||
|
||||
private fun Function.buildDescriptor(
|
||||
@@ -39,7 +34,7 @@ private fun Function.buildDescriptor(
|
||||
isExpect: Boolean = false,
|
||||
isActual: Boolean = false
|
||||
) {
|
||||
val containingDeclaration = containingDeclarations[index] ?: error("No containing declaration for property $this")
|
||||
val containingDeclaration = containingDeclarations[index] ?: error("No containing declaration for function $this")
|
||||
|
||||
val functionDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
containingDeclaration,
|
||||
@@ -59,11 +54,14 @@ private fun Function.buildDescriptor(
|
||||
functionDescriptor.isExpect = isExpect
|
||||
functionDescriptor.isActual = isActual
|
||||
|
||||
functionDescriptor.setHasStableParameterNames(hasStableParameterNames)
|
||||
functionDescriptor.setHasSynthesizedParameterNames(hasSynthesizedParameterNames)
|
||||
|
||||
functionDescriptor.initialize(
|
||||
extensionReceiver?.buildExtensionReceiver(functionDescriptor),
|
||||
buildDispatchReceiver(functionDescriptor),
|
||||
typeParameters.buildDescriptors(functionDescriptor),
|
||||
valueParameters.buildValueParameters(functionDescriptor),
|
||||
valueParameters.buildDescriptors(functionDescriptor),
|
||||
returnType,
|
||||
modality,
|
||||
visibility
|
||||
@@ -71,21 +69,3 @@ private fun Function.buildDescriptor(
|
||||
|
||||
output[index] = functionDescriptor
|
||||
}
|
||||
|
||||
private fun List<ValueParameter>.buildValueParameters(
|
||||
functionDescriptor: SimpleFunctionDescriptor
|
||||
) = mapIndexed { index, param ->
|
||||
ValueParameterDescriptorImpl(
|
||||
functionDescriptor,
|
||||
null,
|
||||
index,
|
||||
param.annotations,
|
||||
param.name,
|
||||
param.returnType,
|
||||
param.declaresDefaultValue,
|
||||
param.isCrossinline,
|
||||
param.isNoinline,
|
||||
param.varargElementType,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ internal fun ModuleNode.buildDescriptors(
|
||||
module?.buildDescriptor(output, index, storageManager, builtIns)
|
||||
}
|
||||
|
||||
common?.buildDescriptor(output, indexOfCommon, storageManager, builtIns)
|
||||
common()?.buildDescriptor(output, indexOfCommon, storageManager, builtIns)
|
||||
}
|
||||
|
||||
private fun Module.buildDescriptor(
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ internal fun PackageNode.buildDescriptors(
|
||||
pkg?.buildDescriptor(output, index, modules)
|
||||
}
|
||||
|
||||
common?.buildDescriptor(output, indexOfCommon, modules)
|
||||
common()?.buildDescriptor(output, indexOfCommon, modules)
|
||||
}
|
||||
|
||||
private fun Package.buildDescriptor(
|
||||
|
||||
+4
-4
@@ -22,13 +22,13 @@ internal fun PropertyNode.buildDescriptors(
|
||||
containingDeclarations: List<DeclarationDescriptor?>,
|
||||
storageManager: StorageManager
|
||||
) {
|
||||
val isCommonized = common != null
|
||||
val commonProperty = common()
|
||||
|
||||
target.forEachIndexed { index, property ->
|
||||
property?.buildDescriptor(output, index, containingDeclarations, storageManager, isActual = isCommonized)
|
||||
property?.buildDescriptor(output, index, containingDeclarations, storageManager, isActual = commonProperty != null)
|
||||
}
|
||||
|
||||
common?.buildDescriptor(output, indexOfCommon, containingDeclarations, storageManager, isExpect = isCommonized)
|
||||
commonProperty?.buildDescriptor(output, indexOfCommon, containingDeclarations, storageManager, isExpect = true)
|
||||
}
|
||||
|
||||
private fun Property.buildDescriptor(
|
||||
@@ -50,7 +50,7 @@ private fun Property.buildDescriptor(
|
||||
name,
|
||||
kind,
|
||||
SourceElement.NO_SOURCE,
|
||||
lateInit,
|
||||
isLateInit,
|
||||
isConst,
|
||||
isExpect,
|
||||
isActual,
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.builder
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroup
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassDeclaration
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.TypeAlias
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.TypeAliasNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.indexOfCommon
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
internal fun TypeAliasNode.buildDescriptors(
|
||||
output: CommonizedGroup<ClassifierDescriptorWithTypeParameters>,
|
||||
containingDeclarations: List<DeclarationDescriptor?>,
|
||||
storageManager: StorageManager
|
||||
) {
|
||||
val commonClass: ClassDeclaration? = common()
|
||||
|
||||
target.forEachIndexed { index, typeAlias ->
|
||||
typeAlias?.buildDescriptor(output, index, containingDeclarations, storageManager, isActual = commonClass != null)
|
||||
}
|
||||
|
||||
commonClass?.buildDescriptor(output, indexOfCommon, containingDeclarations, storageManager, isExpect = true)
|
||||
}
|
||||
|
||||
private fun TypeAlias.buildDescriptor(
|
||||
output: CommonizedGroup<ClassifierDescriptorWithTypeParameters>,
|
||||
index: Int,
|
||||
containingDeclarations: List<DeclarationDescriptor?>,
|
||||
storageManager: StorageManager,
|
||||
isActual: Boolean = false
|
||||
) {
|
||||
val containingDeclaration = containingDeclarations[index] ?: error("No containing declaration for type alias $this")
|
||||
|
||||
val typeAliasDescriptor = CommonizedTypeAliasDescriptor(
|
||||
storageManager = storageManager,
|
||||
containingDeclaration = containingDeclaration,
|
||||
annotations = annotations,
|
||||
name = name,
|
||||
visibility = visibility,
|
||||
isActual = isActual
|
||||
)
|
||||
|
||||
typeAliasDescriptor.initialize(underlyingType, expandedType)
|
||||
|
||||
output[index] = typeAliasDescriptor
|
||||
}
|
||||
@@ -5,13 +5,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.builder
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ExtensionReceiver
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.TypeParameter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ValueParameter
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
@@ -36,6 +35,24 @@ internal fun List<TypeParameter>.buildDescriptors(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun List<ValueParameter>.buildDescriptors(
|
||||
containingDeclaration: CallableDescriptor
|
||||
) = mapIndexed { index, param ->
|
||||
ValueParameterDescriptorImpl(
|
||||
containingDeclaration,
|
||||
null,
|
||||
index,
|
||||
param.annotations,
|
||||
param.name,
|
||||
param.returnType,
|
||||
param.declaresDefaultValue,
|
||||
param.isCrossinline,
|
||||
param.isNoinline,
|
||||
param.varargElementType,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
}
|
||||
|
||||
internal fun ExtensionReceiver.buildExtensionReceiver(
|
||||
containingDeclaration: CallableDescriptor
|
||||
) = DescriptorFactory.createExtensionReceiverParameterForCallable(
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer
|
||||
|
||||
// Fixed-size list that represents a commonized group of same-rank elements
|
||||
/** Fixed-size ordered collection that represents a commonized group of same-rank elements */
|
||||
internal class CommonizedGroup<T : Any>(
|
||||
val size: Int,
|
||||
initialize: (Int) -> T?
|
||||
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CallableMember
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class AbstractCallableMemberCommonizer<T : CallableMemberDescriptor, R: CallableMember> : Commonizer<T, R> {
|
||||
protected enum class State {
|
||||
EMPTY,
|
||||
ERROR,
|
||||
IN_PROGRESS
|
||||
}
|
||||
|
||||
protected lateinit var name: Name
|
||||
protected val modality = ModalityCommonizer.default()
|
||||
// TODO: visibility - what if virtual declaration?
|
||||
protected val visibility = VisibilityCommonizer.lowering()
|
||||
protected val extensionReceiver = ExtensionReceiverCommonizer.default()
|
||||
protected val returnType = TypeCommonizer.default()
|
||||
protected val typeParameters = TypeParameterListCommonizer.default()
|
||||
|
||||
protected var state = State.EMPTY
|
||||
|
||||
final override fun commonizeWith(next: T): Boolean {
|
||||
if (state == State.ERROR)
|
||||
return false
|
||||
|
||||
if (state == State.EMPTY)
|
||||
name = next.name
|
||||
|
||||
val result = canBeCommonized(next)
|
||||
&& modality.commonizeWith(next.modality)
|
||||
&& visibility.commonizeWith(next.visibility)
|
||||
&& extensionReceiver.commonizeWith(next.extensionReceiverParameter)
|
||||
&& returnType.commonizeWith(next.returnType!!)
|
||||
&& typeParameters.commonizeWith(next.typeParameters)
|
||||
&& commonizeSpecifics(next)
|
||||
|
||||
state = if (!result) State.ERROR else State.IN_PROGRESS
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
protected abstract fun canBeCommonized(next: T): Boolean
|
||||
protected abstract fun commonizeSpecifics(next: T): Boolean
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassifiersCache
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.FunctionOrProperty
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class AbstractFunctionOrPropertyCommonizer<T : FunctionOrProperty>(cache: ClassifiersCache) : AbstractStandardCommonizer<T, T>() {
|
||||
protected lateinit var name: Name
|
||||
protected val modality = ModalityCommonizer.default()
|
||||
protected val visibility = VisibilityCommonizer.lowering()
|
||||
protected val extensionReceiver = ExtensionReceiverCommonizer.default(cache)
|
||||
protected val returnType = TypeCommonizer.default(cache)
|
||||
protected val typeParameters = TypeParameterListCommonizer.default(cache)
|
||||
|
||||
override fun initialize(first: T) {
|
||||
name = first.name
|
||||
}
|
||||
|
||||
override fun doCommonizeWith(next: T) =
|
||||
!next.isNonAbstractCallableMemberInInterface // non-abstract callable members declared in interface can't be commonized
|
||||
&& modality.commonizeWith(next.modality)
|
||||
&& visibility.commonizeWith(next)
|
||||
&& extensionReceiver.commonizeWith(next.extensionReceiver)
|
||||
&& returnType.commonizeWith(next.returnType)
|
||||
&& typeParameters.commonizeWith(next.typeParameters)
|
||||
}
|
||||
+13
-1
@@ -5,6 +5,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
|
||||
/**
|
||||
* Unlike [Commonizer] which commonizes only single elements, this [AbstractListCommonizer] commonizes lists of elements using
|
||||
* [Commonizer]s produced by [singleElementCommonizerFactory].
|
||||
*
|
||||
* Example:
|
||||
* Input: N lists of [KotlinType]
|
||||
* Output: list of [UnwrappedType]
|
||||
*/
|
||||
abstract class AbstractListCommonizer<T, R>(
|
||||
private val singleElementCommonizerFactory: () -> Commonizer<T, R>
|
||||
) : Commonizer<List<T>, List<R>> {
|
||||
@@ -27,13 +38,14 @@ abstract class AbstractListCommonizer<T, R>(
|
||||
this.commonizers = it
|
||||
}
|
||||
|
||||
if (commonizers.size != next.size)
|
||||
if (commonizers.size != next.size) // lists must be of the same size
|
||||
error = true
|
||||
else
|
||||
for (index in 0 until next.size) {
|
||||
val commonizer = commonizers[index]
|
||||
val nextElement = next[index]
|
||||
|
||||
// commonize each element in the list:
|
||||
if (!commonizer.commonizeWith(nextElement)) {
|
||||
error = true
|
||||
break
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Named
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class AbstractNamedListCommonizer<T : Named, R>(
|
||||
private val singleElementCommonizerFactory: () -> Commonizer<T, R>
|
||||
) : Commonizer<List<T>, List<R>> {
|
||||
private var commonizers: List<Pair<Name, Commonizer<T, R>>>? = null
|
||||
private var error = false
|
||||
|
||||
final override val result: List<R>
|
||||
get() = commonizers?.takeIf { !error }?.map { it.second.result } ?: throw IllegalCommonizerStateException()
|
||||
|
||||
final override fun commonizeWith(next: List<T>): Boolean {
|
||||
if (error)
|
||||
return false
|
||||
|
||||
val commonizers = commonizers
|
||||
?: next.map { it.name to singleElementCommonizerFactory() }.also { this.commonizers = it }
|
||||
|
||||
if (commonizers.size != next.size)
|
||||
error = true
|
||||
else
|
||||
for (index in 0 until next.size) {
|
||||
val (name, commonizer) = commonizers[index]
|
||||
val nextElement = next[index]
|
||||
|
||||
if (name != nextElement.name || !commonizer.commonizeWith(nextElement)) {
|
||||
error = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return !error
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -5,6 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
/**
|
||||
* A wrapper around [Commonizer] that checks that
|
||||
* - either all commonized elements are null
|
||||
* - or all commonized elements are non-null and can be commonized according to the wrapped commonized
|
||||
*/
|
||||
abstract class AbstractNullableCommonizer<T : Any, R : Any, WT, WR>(
|
||||
private val wrappedCommonizerFactory: () -> Commonizer<WT, WR>,
|
||||
private val extractor: (T) -> WT,
|
||||
@@ -41,6 +46,7 @@ abstract class AbstractNullableCommonizer<T : Any, R : Any, WT, WR>(
|
||||
return state != State.ERROR
|
||||
}
|
||||
|
||||
private fun doCommonizeWith(next: T) =
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun doCommonizeWith(next: T) =
|
||||
if (wrapped.commonizeWith(extractor(next))) State.WITH_WRAPPED else State.ERROR
|
||||
}
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassDeclaration
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassifiersCache
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CommonClassDeclaration
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class ClassCommonizer(cache: ClassifiersCache) : AbstractStandardCommonizer<ClassDeclaration, ClassDeclaration>() {
|
||||
private lateinit var name: Name
|
||||
private lateinit var kind: ClassKind
|
||||
private val typeParameters = TypeParameterListCommonizer.default(cache)
|
||||
private val modality = ModalityCommonizer.default()
|
||||
private val visibility = VisibilityCommonizer.equalizing()
|
||||
private var isInner = false
|
||||
private var isInline = false
|
||||
private var isCompanion = false
|
||||
|
||||
override fun commonizationResult() = CommonClassDeclaration(
|
||||
name = name,
|
||||
typeParameters = typeParameters.result,
|
||||
kind = kind,
|
||||
modality = modality.result,
|
||||
visibility = visibility.result,
|
||||
isCompanion = isCompanion,
|
||||
isInline = isInline,
|
||||
isInner = isInner
|
||||
)
|
||||
|
||||
override fun initialize(first: ClassDeclaration) {
|
||||
name = first.name
|
||||
kind = first.kind
|
||||
isInner = first.isInner
|
||||
isInline = first.isInline
|
||||
isCompanion = first.isCompanion
|
||||
}
|
||||
|
||||
override fun doCommonizeWith(next: ClassDeclaration) =
|
||||
kind == next.kind
|
||||
&& isInner == next.isInner
|
||||
&& isInline == next.isInline
|
||||
&& isCompanion == next.isCompanion
|
||||
&& next.sealedSubclasses.isEmpty() // commonization of sealed classes is not supported, but their subclasses can be commonized
|
||||
&& modality.commonizeWith(next.modality)
|
||||
&& visibility.commonizeWith(next)
|
||||
&& typeParameters.commonizeWith(next.typeParameters)
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassConstructor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassifiersCache
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CommonClassConstructor
|
||||
|
||||
class ClassConstructorCommonizer(cache: ClassifiersCache) : AbstractStandardCommonizer<ClassConstructor, ClassConstructor>() {
|
||||
private var isPrimary = false
|
||||
private lateinit var kind: CallableMemberDescriptor.Kind
|
||||
private val visibility = VisibilityCommonizer.equalizing()
|
||||
private val typeParameters = TypeParameterListCommonizer.default(cache)
|
||||
private val valueParameters = ValueParameterListCommonizer.default(cache)
|
||||
private var hasStableParameterNames = true
|
||||
private var hasSynthesizedParameterNames = false
|
||||
|
||||
override fun commonizationResult() = CommonClassConstructor(
|
||||
isPrimary = isPrimary,
|
||||
kind = kind,
|
||||
visibility = visibility.result,
|
||||
typeParameters = typeParameters.result,
|
||||
valueParameters = valueParameters.result,
|
||||
hasStableParameterNames = hasStableParameterNames,
|
||||
hasSynthesizedParameterNames = hasSynthesizedParameterNames
|
||||
)
|
||||
|
||||
override fun initialize(first: ClassConstructor) {
|
||||
isPrimary = first.isPrimary
|
||||
kind = first.kind
|
||||
}
|
||||
|
||||
override fun doCommonizeWith(next: ClassConstructor): Boolean {
|
||||
val result = isPrimary == next.isPrimary
|
||||
&& kind == next.kind
|
||||
&& visibility.commonizeWith(next)
|
||||
&& typeParameters.commonizeWith(next.typeParameters)
|
||||
&& valueParameters.commonizeWith(next.valueParameters)
|
||||
|
||||
if (result) {
|
||||
hasStableParameterNames = hasStableParameterNames && next.hasStableParameterNames
|
||||
hasSynthesizedParameterNames = hasSynthesizedParameterNames || next.hasSynthesizedParameterNames
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroupMap
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.fqNameWithTypeParameters
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.lang.IllegalStateException
|
||||
|
||||
internal class CommonizationVisitor(
|
||||
private val root: RootNode
|
||||
) : NodeVisitor<Unit, Unit> {
|
||||
override fun visitRootNode(node: RootNode, data: Unit) {
|
||||
check(node === root)
|
||||
check(node.common() != null) // root should already be commonized
|
||||
|
||||
node.modules.forEach { module ->
|
||||
module.accept(this, Unit)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitModuleNode(node: ModuleNode, data: Unit) {
|
||||
node.common() // commonize module
|
||||
|
||||
node.packages.forEach { pkg ->
|
||||
pkg.accept(this, Unit)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitPackageNode(node: PackageNode, data: Unit) {
|
||||
node.common() // commonize package
|
||||
|
||||
node.properties.forEach { property ->
|
||||
property.accept(this, Unit)
|
||||
}
|
||||
|
||||
node.functions.forEach { function ->
|
||||
function.accept(this, Unit)
|
||||
}
|
||||
|
||||
node.classes.forEach { clazz ->
|
||||
clazz.accept(this, Unit)
|
||||
}
|
||||
|
||||
node.typeAliases.forEach { typeAlias ->
|
||||
typeAlias.accept(this, Unit)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitPropertyNode(node: PropertyNode, data: Unit) {
|
||||
node.common() // commonize property
|
||||
}
|
||||
|
||||
override fun visitFunctionNode(node: FunctionNode, data: Unit) {
|
||||
node.common() // commonize function
|
||||
}
|
||||
|
||||
override fun visitClassNode(node: ClassNode, data: Unit) {
|
||||
val commonClass = node.common() as CommonClassDeclaration? // commonize class
|
||||
|
||||
node.constructors.forEach { constructor ->
|
||||
constructor.accept(this, Unit)
|
||||
}
|
||||
|
||||
node.properties.forEach { property ->
|
||||
property.accept(this, Unit)
|
||||
}
|
||||
|
||||
node.functions.forEach { function ->
|
||||
function.accept(this, Unit)
|
||||
}
|
||||
|
||||
node.classes.forEach { clazz ->
|
||||
clazz.accept(this, Unit)
|
||||
}
|
||||
|
||||
if (commonClass != null) {
|
||||
// companion object should have the same FQ name for each target class, then it could be set to common class
|
||||
val companionObjectFqName = node.target.mapTo(HashSet()) { it!!.companion }.singleOrNull()
|
||||
if (companionObjectFqName != null) {
|
||||
val companionObjectNode = root.cache.classes[companionObjectFqName]
|
||||
?: throw IllegalStateException("Can't find companion object with FQ name $companionObjectFqName")
|
||||
|
||||
if (companionObjectNode.common() != null) {
|
||||
// companion object has been successfully commonized
|
||||
commonClass.companion = companionObjectFqName
|
||||
}
|
||||
}
|
||||
|
||||
// find out common (and commonized) supertypes
|
||||
val supertypesMap = CommonizedGroupMap<String, KotlinType>(node.target.size)
|
||||
node.target.forEachIndexed { index, clazz ->
|
||||
for (supertype in clazz!!.supertypes) {
|
||||
supertypesMap[supertype.fqNameWithTypeParameters][index] = supertype
|
||||
}
|
||||
}
|
||||
|
||||
for ((_, supertypesGroup) in supertypesMap) {
|
||||
val commonSupertype = commonize(supertypesGroup.toList(), TypeCommonizer.default(root.cache))
|
||||
if (commonSupertype != null)
|
||||
commonClass.supertypes += commonSupertype
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitClassConstructorNode(node: ClassConstructorNode, data: Unit) {
|
||||
node.common() // commonize constructor
|
||||
}
|
||||
|
||||
override fun visitTypeAliasNode(node: TypeAliasNode, data: Unit) {
|
||||
node.common() // commonize type alias
|
||||
}
|
||||
}
|
||||
@@ -10,4 +10,38 @@ interface Commonizer<T, R> {
|
||||
fun commonizeWith(next: T): Boolean
|
||||
}
|
||||
|
||||
abstract class AbstractStandardCommonizer<T, R> : Commonizer<T, R> {
|
||||
private enum class State {
|
||||
EMPTY,
|
||||
ERROR,
|
||||
IN_PROGRESS
|
||||
}
|
||||
|
||||
private var state = State.EMPTY
|
||||
|
||||
final override val result: R
|
||||
get() = when (state) {
|
||||
State.EMPTY, State.ERROR -> throw IllegalCommonizerStateException()
|
||||
State.IN_PROGRESS -> commonizationResult()
|
||||
}
|
||||
|
||||
final override fun commonizeWith(next: T): Boolean {
|
||||
if (state == State.ERROR)
|
||||
return false
|
||||
|
||||
if (state == State.EMPTY)
|
||||
initialize(next)
|
||||
|
||||
val result = doCommonizeWith(next)
|
||||
state = if (!result) State.ERROR else State.IN_PROGRESS
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
protected abstract fun commonizationResult(): R
|
||||
|
||||
protected abstract fun initialize(first: T)
|
||||
protected abstract fun doCommonizeWith(next: T): Boolean
|
||||
}
|
||||
|
||||
class IllegalCommonizerStateException : IllegalStateException("Illegal commonizer state: error or empty")
|
||||
|
||||
+12
-38
@@ -5,47 +5,21 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassifiersCache
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ExtensionReceiver
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
|
||||
interface ExtensionReceiverCommonizer : Commonizer<ReceiverParameterDescriptor?, UnwrappedType?> {
|
||||
interface ExtensionReceiverCommonizer : Commonizer<ExtensionReceiver?, UnwrappedType?> {
|
||||
companion object {
|
||||
fun default(): ExtensionReceiverCommonizer = DefaultExtensionReceiverCommonizer()
|
||||
fun default(cache: ClassifiersCache): ExtensionReceiverCommonizer = DefaultExtensionReceiverCommonizer(cache)
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultExtensionReceiverCommonizer : ExtensionReceiverCommonizer {
|
||||
private enum class State {
|
||||
EMPTY,
|
||||
ERROR,
|
||||
WITH_RECEIVER,
|
||||
WITHOUT_RECEIVER
|
||||
}
|
||||
|
||||
private var state = State.EMPTY
|
||||
private lateinit var receiverType: TypeCommonizer
|
||||
|
||||
override val result: UnwrappedType?
|
||||
get() = when (state) {
|
||||
State.EMPTY, State.ERROR -> throw IllegalCommonizerStateException()
|
||||
State.WITH_RECEIVER -> receiverType.result
|
||||
State.WITHOUT_RECEIVER -> null // null receiverType means there is no extension receiver
|
||||
}
|
||||
|
||||
override fun commonizeWith(next: ReceiverParameterDescriptor?): Boolean {
|
||||
state = when (state) {
|
||||
State.ERROR -> State.ERROR
|
||||
State.EMPTY -> next?.let {
|
||||
receiverType = TypeCommonizer.default()
|
||||
doCommonizeWith(next)
|
||||
} ?: State.WITHOUT_RECEIVER
|
||||
State.WITH_RECEIVER -> next?.let(::doCommonizeWith) ?: State.ERROR
|
||||
State.WITHOUT_RECEIVER -> next?.let { State.ERROR } ?: State.WITHOUT_RECEIVER
|
||||
}
|
||||
|
||||
return state != State.ERROR
|
||||
}
|
||||
|
||||
private fun doCommonizeWith(receiverParameter: ReceiverParameterDescriptor) =
|
||||
if (receiverType.commonizeWith(receiverParameter.type)) State.WITH_RECEIVER else State.ERROR
|
||||
}
|
||||
private class DefaultExtensionReceiverCommonizer(cache: ClassifiersCache) :
|
||||
ExtensionReceiverCommonizer,
|
||||
AbstractNullableCommonizer<ExtensionReceiver, UnwrappedType, KotlinType, UnwrappedType>(
|
||||
wrappedCommonizerFactory = { TypeCommonizer.default(cache) },
|
||||
extractor = { it.type },
|
||||
builder = { it }
|
||||
)
|
||||
|
||||
+28
-20
@@ -5,32 +5,40 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassifiersCache
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CommonFunction
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ExtensionReceiver.Companion.toReceiverNoAnnotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.Function
|
||||
|
||||
class FunctionCommonizer : AbstractCallableMemberCommonizer<SimpleFunctionDescriptor, Function>() {
|
||||
class FunctionCommonizer(cache: ClassifiersCache) : AbstractFunctionOrPropertyCommonizer<Function>(cache) {
|
||||
private val modifiers = FunctionModifiersCommonizer.default()
|
||||
private val valueParameters = ValueParameterListCommonizer.default()
|
||||
private val valueParameters = ValueParameterListCommonizer.default(cache)
|
||||
private var hasStableParameterNames = true
|
||||
private var hasSynthesizedParameterNames = false
|
||||
|
||||
override val result: Function
|
||||
get() = when (state) {
|
||||
State.EMPTY, State.ERROR -> throw IllegalCommonizerStateException()
|
||||
State.IN_PROGRESS -> CommonFunction(
|
||||
name = name,
|
||||
modality = modality.result,
|
||||
visibility = visibility.result,
|
||||
extensionReceiver = extensionReceiver.result?.toReceiverNoAnnotations(),
|
||||
returnType = returnType.result,
|
||||
modifiers = modifiers.result,
|
||||
valueParameters = valueParameters.result,
|
||||
typeParameters = typeParameters.result
|
||||
)
|
||||
override fun commonizationResult() = CommonFunction(
|
||||
name = name,
|
||||
modality = modality.result,
|
||||
visibility = visibility.result,
|
||||
extensionReceiver = extensionReceiver.result?.toReceiverNoAnnotations(),
|
||||
returnType = returnType.result,
|
||||
modifiers = modifiers.result,
|
||||
valueParameters = valueParameters.result,
|
||||
typeParameters = typeParameters.result,
|
||||
hasStableParameterNames = hasStableParameterNames,
|
||||
hasSynthesizedParameterNames = hasSynthesizedParameterNames
|
||||
)
|
||||
|
||||
override fun doCommonizeWith(next: Function): Boolean {
|
||||
val result = super.doCommonizeWith(next)
|
||||
&& modifiers.commonizeWith(next)
|
||||
&& valueParameters.commonizeWith(next.valueParameters)
|
||||
|
||||
if (result) {
|
||||
hasStableParameterNames = hasStableParameterNames && next.hasStableParameterNames
|
||||
hasSynthesizedParameterNames = hasSynthesizedParameterNames || next.hasSynthesizedParameterNames
|
||||
}
|
||||
|
||||
override fun canBeCommonized(next: SimpleFunctionDescriptor) = true
|
||||
|
||||
override fun commonizeSpecifics(next: SimpleFunctionDescriptor) =
|
||||
modifiers.commonizeWith(next) && valueParameters.commonizeWith(next.valueParameters)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
+3
-4
@@ -5,10 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.FunctionModifiers
|
||||
|
||||
interface FunctionModifiersCommonizer : Commonizer<SimpleFunctionDescriptor, FunctionModifiers> {
|
||||
interface FunctionModifiersCommonizer : Commonizer<FunctionModifiers, FunctionModifiers> {
|
||||
companion object {
|
||||
fun default(): FunctionModifiersCommonizer = DefaultFunctionModifiersCommonizer()
|
||||
}
|
||||
@@ -21,7 +20,7 @@ private class DefaultFunctionModifiersCommonizer : FunctionModifiersCommonizer {
|
||||
override val result: FunctionModifiers
|
||||
get() = modifiers?.takeIf { !error } ?: throw IllegalCommonizerStateException()
|
||||
|
||||
override fun commonizeWith(next: SimpleFunctionDescriptor): Boolean {
|
||||
override fun commonizeWith(next: FunctionModifiers): Boolean {
|
||||
if (error)
|
||||
return false
|
||||
|
||||
@@ -51,7 +50,7 @@ private class DefaultFunctionModifiersCommonizer : FunctionModifiersCommonizer {
|
||||
override var isSuspend: Boolean,
|
||||
override var isExternal: Boolean
|
||||
) : FunctionModifiers {
|
||||
constructor(function: SimpleFunctionDescriptor) : this(
|
||||
constructor(function: FunctionModifiers) : this(
|
||||
function.isOperator,
|
||||
function.isInfix,
|
||||
function.isInline,
|
||||
|
||||
+23
-23
@@ -5,39 +5,39 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassifiersCache
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CommonProperty
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ExtensionReceiver.Companion.toReceiverNoAnnotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.Property
|
||||
|
||||
class PropertyCommonizer : AbstractCallableMemberCommonizer<PropertyDescriptor, Property>() {
|
||||
class PropertyCommonizer(cache: ClassifiersCache) : AbstractFunctionOrPropertyCommonizer<Property>(cache) {
|
||||
private val setter = PropertySetterCommonizer.default()
|
||||
private var isExternal = true
|
||||
|
||||
override val result: Property
|
||||
get() = when (state) {
|
||||
State.EMPTY, State.ERROR -> throw IllegalCommonizerStateException()
|
||||
State.IN_PROGRESS -> CommonProperty(
|
||||
name = name,
|
||||
modality = modality.result,
|
||||
visibility = visibility.result,
|
||||
isExternal = isExternal,
|
||||
extensionReceiver = extensionReceiver.result?.toReceiverNoAnnotations(),
|
||||
returnType = returnType.result,
|
||||
setter = setter.result,
|
||||
typeParameters = typeParameters.result
|
||||
)
|
||||
override fun commonizationResult() = CommonProperty(
|
||||
name = name,
|
||||
modality = modality.result,
|
||||
visibility = visibility.result,
|
||||
isExternal = isExternal,
|
||||
extensionReceiver = extensionReceiver.result?.toReceiverNoAnnotations(),
|
||||
returnType = returnType.result,
|
||||
setter = setter.result,
|
||||
typeParameters = typeParameters.result
|
||||
)
|
||||
|
||||
override fun doCommonizeWith(next: Property): Boolean {
|
||||
when {
|
||||
next.isConst -> return false // expect property can't be const because expect can't have initializer
|
||||
next.isLateInit -> return false // expect property can't be lateinit
|
||||
}
|
||||
|
||||
override fun canBeCommonized(next: PropertyDescriptor) = when {
|
||||
next.isConst -> false // expect property can't be const because expect can't have initializer
|
||||
next.isLateInit -> false // expect property can't be lateinit
|
||||
else -> true
|
||||
}
|
||||
val result = super.doCommonizeWith(next)
|
||||
&& setter.commonizeWith(next.setter)
|
||||
|
||||
override fun commonizeSpecifics(next: PropertyDescriptor): Boolean {
|
||||
isExternal = isExternal && next.isExternal
|
||||
if (result) {
|
||||
isExternal = isExternal && next.isExternal
|
||||
}
|
||||
|
||||
return setter.commonizeWith(next.setter)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -5,11 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.PropertySetterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.DeclarationWithVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.Setter
|
||||
|
||||
interface PropertySetterCommonizer : Commonizer<PropertySetterDescriptor?, Setter?> {
|
||||
interface PropertySetterCommonizer : Commonizer<Setter?, Setter?> {
|
||||
companion object {
|
||||
fun default(): PropertySetterCommonizer = DefaultPropertySetterCommonizer()
|
||||
}
|
||||
@@ -17,8 +17,8 @@ interface PropertySetterCommonizer : Commonizer<PropertySetterDescriptor?, Sette
|
||||
|
||||
private class DefaultPropertySetterCommonizer :
|
||||
PropertySetterCommonizer,
|
||||
AbstractNullableCommonizer<PropertySetterDescriptor, Setter, Visibility, Visibility>(
|
||||
AbstractNullableCommonizer<Setter, Setter, DeclarationWithVisibility, Visibility>(
|
||||
wrappedCommonizerFactory = { VisibilityCommonizer.equalizing() },
|
||||
extractor = { it.visibility },
|
||||
extractor = { it },
|
||||
builder = { Setter.createDefaultNoAnnotations(it) }
|
||||
)
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.checker.isClassType
|
||||
|
||||
class TypeAliasCommonizer(cache: ClassifiersCache) : AbstractStandardCommonizer<TypeAlias, ClassDeclaration>() {
|
||||
private lateinit var name: Name
|
||||
private val underlyingType = TypeCommonizer.default(cache)
|
||||
private val visibility = VisibilityCommonizer.lowering(allowPrivate = true)
|
||||
|
||||
override fun commonizationResult() = CommonClassDeclaration(
|
||||
name = name,
|
||||
typeParameters = emptyList(),
|
||||
kind = ClassKind.CLASS,
|
||||
modality = Modality.FINAL,
|
||||
visibility = visibility.result,
|
||||
isCompanion = false,
|
||||
isInline = false,
|
||||
isInner = false
|
||||
)
|
||||
|
||||
override fun initialize(first: TypeAlias) {
|
||||
name = first.name
|
||||
}
|
||||
|
||||
override fun doCommonizeWith(next: TypeAlias) =
|
||||
next.typeParameters.isEmpty() // TAs with declared type parameters can't be commonized
|
||||
&& next.underlyingType.arguments.isEmpty() // TAs with functional types or types with parameters at the right-hand side can't be commonized
|
||||
&& next.underlyingType.isClassType // right-hand side could have only class
|
||||
&& underlyingType.commonizeWith(next.underlyingType)
|
||||
&& visibility.commonizeWith(next)
|
||||
}
|
||||
+61
-111
@@ -5,73 +5,60 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.isUnderStandardKotlinPackages
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassifiersCache
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.Node
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.isClassType
|
||||
|
||||
interface TypeCommonizer : Commonizer<KotlinType, UnwrappedType> {
|
||||
companion object {
|
||||
fun default(): TypeCommonizer = DefaultTypeCommonizer()
|
||||
fun default(cache: ClassifiersCache): TypeCommonizer = DefaultTypeCommonizer(cache)
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultTypeCommonizer : TypeCommonizer {
|
||||
private enum class State {
|
||||
EMPTY,
|
||||
ERROR,
|
||||
IN_PROGRESS
|
||||
}
|
||||
private class DefaultTypeCommonizer(private val cache: ClassifiersCache) :
|
||||
TypeCommonizer,
|
||||
AbstractStandardCommonizer<KotlinType, UnwrappedType>() {
|
||||
|
||||
private var state = State.EMPTY
|
||||
private lateinit var temp: UnwrappedType
|
||||
|
||||
override val result: UnwrappedType
|
||||
get() = when (state) {
|
||||
State.EMPTY, State.ERROR -> throw IllegalCommonizerStateException()
|
||||
State.IN_PROGRESS -> temp
|
||||
}
|
||||
override fun commonizationResult() = temp
|
||||
|
||||
override fun commonizeWith(next: KotlinType): Boolean {
|
||||
state = when (state) {
|
||||
State.ERROR -> State.ERROR
|
||||
State.EMPTY -> {
|
||||
temp = next.unwrap()
|
||||
State.IN_PROGRESS
|
||||
}
|
||||
// TODO: maybe cache type comparison results?
|
||||
State.IN_PROGRESS -> {
|
||||
if (!areTypesEqual(temp, next.unwrap())) State.ERROR else State.IN_PROGRESS
|
||||
}
|
||||
}
|
||||
|
||||
return state != State.ERROR
|
||||
override fun initialize(first: KotlinType) {
|
||||
temp = first.unwrap()
|
||||
}
|
||||
|
||||
override fun doCommonizeWith(next: KotlinType) = areTypesEqual(cache, temp, next.unwrap())
|
||||
}
|
||||
|
||||
/**
|
||||
* See also [AbstractStrictEqualityTypeChecker].
|
||||
*/
|
||||
internal fun areTypesEqual(a: UnwrappedType, b: UnwrappedType): Boolean = when {
|
||||
internal fun areTypesEqual(cache: ClassifiersCache, a: UnwrappedType, b: UnwrappedType): Boolean = when {
|
||||
a === b -> true
|
||||
a is SimpleType -> (b is SimpleType) && areSimpleTypesEqual(a, b)
|
||||
a is SimpleType -> (b is SimpleType) && areSimpleTypesEqual(cache, a, b)
|
||||
a is FlexibleType -> (b is FlexibleType)
|
||||
&& areSimpleTypesEqual(a.lowerBound, b.lowerBound) && areSimpleTypesEqual(a.upperBound, b.upperBound)
|
||||
&& areSimpleTypesEqual(cache, a.lowerBound, b.lowerBound) && areSimpleTypesEqual(cache, a.upperBound, b.upperBound)
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun areSimpleTypesEqual(a: SimpleType, b: SimpleType): Boolean = areAbbreviatedTypesEqual(
|
||||
private fun areSimpleTypesEqual(cache: ClassifiersCache, a: SimpleType, b: SimpleType): Boolean = areAbbreviatedTypesEqual(
|
||||
cache,
|
||||
a = a.getAbbreviation() ?: a,
|
||||
aExpanded = a,
|
||||
b = b.getAbbreviation() ?: b,
|
||||
bExpandedType = b
|
||||
)
|
||||
|
||||
private fun areAbbreviatedTypesEqual(a: SimpleType, aExpanded: SimpleType, b: SimpleType, bExpandedType: SimpleType): Boolean {
|
||||
private fun areAbbreviatedTypesEqual(
|
||||
cache: ClassifiersCache,
|
||||
a: SimpleType,
|
||||
aExpanded: SimpleType,
|
||||
b: SimpleType,
|
||||
bExpandedType: SimpleType
|
||||
): Boolean {
|
||||
if (a.arguments.size != b.arguments.size
|
||||
|| a.isMarkedNullable != b.isMarkedNullable
|
||||
|| a.isDefinitelyNotNullType != b.isDefinitelyNotNullType
|
||||
@@ -82,27 +69,36 @@ private fun areAbbreviatedTypesEqual(a: SimpleType, aExpanded: SimpleType, b: Si
|
||||
val aDescriptor = requireNotNull(a.constructor.declarationDescriptor, a::nonNullDescriptorExpectedErrorMessage)
|
||||
val bDescriptor = requireNotNull(b.constructor.declarationDescriptor, b::nonNullDescriptorExpectedErrorMessage)
|
||||
|
||||
val isUnderStandardKotlinPackages = if (
|
||||
val aFqName = aDescriptor.fqNameSafe
|
||||
val bFqName = bDescriptor.fqNameSafe
|
||||
|
||||
if (aFqName != bFqName)
|
||||
return false
|
||||
|
||||
val isClassOrTypeAliasUnderStandardKotlinPackages =
|
||||
// N.B. only for descriptors that represent classes or type aliases, but not type parameters!
|
||||
aDescriptor is ClassifierDescriptorWithTypeParameters
|
||||
&& bDescriptor is ClassifierDescriptorWithTypeParameters
|
||||
) {
|
||||
// N.B. only for descriptors that represent classes or type aliases, but not type parameters:
|
||||
|
||||
val aFqName = aDescriptor.fqNameSafe
|
||||
|
||||
aFqName.isUnderStandardKotlinPackages
|
||||
// make sure that FQ names of abbreviated types (e.g. representing type aliases) are equal
|
||||
&& aFqName == bDescriptor.fqNameSafe
|
||||
// if classes are from the standard Kotlin packages, compare them only by type constructors
|
||||
// effectively, this includes 1) comparison of FQ names and 2) number of type constructor parameters
|
||||
// see org.jetbrains.kotlin.types.AbstractClassTypeConstructor.equals() for details
|
||||
&& bDescriptor is ClassifierDescriptorWithTypeParameters
|
||||
&& aFqName.isUnderStandardKotlinPackages
|
||||
// If classes are from the standard Kotlin packages, compare them only by type constructors.
|
||||
// Effectively, this includes 1) comparison of FQ names and 2) number of type constructor parameters.
|
||||
// See org.jetbrains.kotlin.types.AbstractClassTypeConstructor.equals() for details.
|
||||
&& aExpanded.constructor == bExpandedType.constructor
|
||||
} else false
|
||||
|
||||
val descriptorsCanBeCommonized = isUnderStandardKotlinPackages || when (aDescriptor) {
|
||||
is TypeParameterDescriptor -> (bDescriptor is TypeParameterDescriptor) && canBeCommonized(aDescriptor, bDescriptor)
|
||||
is TypeAliasDescriptor -> (bDescriptor is TypeAliasDescriptor) && canBeCommonized(aDescriptor, bDescriptor)
|
||||
is ClassDescriptor -> (bDescriptor is ClassDescriptor) && canBeCommonized(aDescriptor, bDescriptor)
|
||||
val descriptorsCanBeCommonized =
|
||||
/* either class or type alias from Kotlin stdlib */ isClassOrTypeAliasUnderStandardKotlinPackages
|
||||
|| /* or descriptors themselves can be commonized */ when (aDescriptor) {
|
||||
is TypeParameterDescriptor -> {
|
||||
// Real type parameter commonization is performed in TypeParameterCommonizer.
|
||||
// Here it is enough to check that FQ names are equal (already done above).
|
||||
bDescriptor is TypeParameterDescriptor
|
||||
}
|
||||
is ClassDescriptor -> {
|
||||
(bDescriptor is ClassDescriptor) && cache.classes[aFqName].canBeCommonized()
|
||||
}
|
||||
is TypeAliasDescriptor -> {
|
||||
(bDescriptor is TypeAliasDescriptor) && cache.typeAliases[aFqName].canBeCommonized()
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
||||
@@ -121,7 +117,7 @@ private fun areAbbreviatedTypesEqual(a: SimpleType, aExpanded: SimpleType, b: Si
|
||||
if (aArg.projectionKind != bArg.projectionKind)
|
||||
return false
|
||||
|
||||
if (!areTypesEqual(aArg.type.unwrap(), bArg.type.unwrap()))
|
||||
if (!areTypesEqual(cache, aArg.type.unwrap(), bArg.type.unwrap()))
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -133,59 +129,13 @@ private fun areAbbreviatedTypesEqual(a: SimpleType, aExpanded: SimpleType, b: Si
|
||||
private inline fun SimpleType.nonNullDescriptorExpectedErrorMessage() =
|
||||
"${TypeCommonizer::class} couldn't obtain non-null descriptor from: $this, ${this::class}"
|
||||
|
||||
private val standardKotlinPackages = setOf(
|
||||
KotlinBuiltIns.BUILT_INS_PACKAGE_NAME,
|
||||
Name.identifier("kotlinx")
|
||||
)
|
||||
|
||||
private val FqName.isUnderStandardKotlinPackages: Boolean
|
||||
get() = pathSegments().firstOrNull() in standardKotlinPackages
|
||||
|
||||
// TODO: extract this method to class commonizer
|
||||
private fun canBeCommonized(a: ClassDescriptor, b: ClassDescriptor) = when {
|
||||
a.kind != b.kind -> false
|
||||
!areFqNamesEqual(a, b) -> false
|
||||
// TODO: compare class descriptors (visibility, modifiers, etc)
|
||||
else -> true
|
||||
}
|
||||
|
||||
// TODO: extract this method to type alias commonizer
|
||||
private fun canBeCommonized(a: TypeAliasDescriptor, b: TypeAliasDescriptor): Boolean {
|
||||
if (!areFqNamesEqual(a, b))
|
||||
return false
|
||||
|
||||
val aUnderlyingType = a.underlyingType
|
||||
val bUnderlyingType = b.underlyingType
|
||||
|
||||
if (aUnderlyingType.arguments.isNotEmpty() || bUnderlyingType.arguments.isNotEmpty())
|
||||
return false // type aliases with functional types at the right-hand side can't be commonized
|
||||
|
||||
if (!aUnderlyingType.isClassType || !bUnderlyingType.isClassType)
|
||||
return false // right-hand side could have only classes
|
||||
|
||||
return areTypesEqual(aUnderlyingType, bUnderlyingType)
|
||||
}
|
||||
|
||||
private fun canBeCommonized(a: TypeParameterDescriptor, b: TypeParameterDescriptor): Boolean {
|
||||
// real type parameter commonization is performed in TypeParameterCommonizer,
|
||||
// here it is enough to check FQ names
|
||||
return areFqNamesEqual(a, b)
|
||||
}
|
||||
|
||||
private fun <T : ClassifierDescriptor> areFqNamesEqual(d1: T, d2: T): Boolean {
|
||||
val p1 = d1.parentsWithSelf.iterator()
|
||||
val p2 = d2.parentsWithSelf.iterator()
|
||||
|
||||
while (p1.hasNext() && p2.hasNext()) {
|
||||
val n1 = p1.next()
|
||||
val n2 = p2.next()
|
||||
|
||||
when (n1) {
|
||||
is ModuleDescriptor -> return n2 is ModuleDescriptor
|
||||
is PackageFragmentDescriptor -> return (n2 is PackageFragmentDescriptor) && n1.fqName == n2.fqName
|
||||
else -> if (n1.name != n2.name) return false
|
||||
}
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun Node<*, *>?.canBeCommonized() =
|
||||
if (this == null) {
|
||||
// No node means that the class or type alias was not subject for commonization at all, probably it lays
|
||||
// not in commonized module descriptors but somewhere in their dependencies.
|
||||
true
|
||||
} else {
|
||||
// If entry is present, then contents (common declaration) should not be null.
|
||||
common() != null
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
+30
-47
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassifiersCache
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CommonTypeParameter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.TypeParameter
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -13,70 +13,53 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
interface TypeParameterCommonizer : Commonizer<TypeParameterDescriptor, TypeParameter> {
|
||||
interface TypeParameterCommonizer : Commonizer<TypeParameter, TypeParameter> {
|
||||
companion object {
|
||||
fun default(): TypeParameterCommonizer = DefaultTypeParameterCommonizer()
|
||||
fun default(cache: ClassifiersCache): TypeParameterCommonizer = DefaultTypeParameterCommonizer(cache)
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultTypeParameterCommonizer : TypeParameterCommonizer {
|
||||
private enum class State {
|
||||
EMPTY,
|
||||
ERROR,
|
||||
IN_PROGRESS
|
||||
}
|
||||
private class DefaultTypeParameterCommonizer(cache: ClassifiersCache) :
|
||||
TypeParameterCommonizer,
|
||||
AbstractStandardCommonizer<TypeParameter, TypeParameter>() {
|
||||
|
||||
private var state = State.EMPTY
|
||||
private lateinit var name: Name
|
||||
private var isReified = false
|
||||
private lateinit var variance: Variance
|
||||
private val upperBounds = TypeParameterUpperBoundsCommonizer()
|
||||
private val upperBounds = TypeParameterUpperBoundsCommonizer(cache)
|
||||
|
||||
override val result: TypeParameter
|
||||
get() = when (state) {
|
||||
State.EMPTY, State.ERROR -> throw IllegalCommonizerStateException()
|
||||
State.IN_PROGRESS -> CommonTypeParameter(
|
||||
name = name,
|
||||
isReified = isReified,
|
||||
variance = variance,
|
||||
upperBounds = upperBounds.result
|
||||
)
|
||||
}
|
||||
override fun commonizationResult() = CommonTypeParameter(
|
||||
name = name,
|
||||
isReified = isReified,
|
||||
variance = variance,
|
||||
upperBounds = upperBounds.result
|
||||
)
|
||||
|
||||
override fun commonizeWith(next: TypeParameterDescriptor): Boolean {
|
||||
state = when (state) {
|
||||
State.ERROR -> State.ERROR
|
||||
State.EMPTY -> {
|
||||
name = next.name
|
||||
isReified = next.isReified
|
||||
variance = next.variance
|
||||
|
||||
if (!upperBounds.commonizeWith(next.upperBounds)) State.ERROR else State.IN_PROGRESS
|
||||
}
|
||||
State.IN_PROGRESS -> {
|
||||
if (isReified != next.isReified
|
||||
|| variance != next.variance
|
||||
|| !upperBounds.commonizeWith(next.upperBounds)
|
||||
) State.ERROR else State.IN_PROGRESS
|
||||
}
|
||||
}
|
||||
|
||||
return state != State.ERROR
|
||||
override fun initialize(first: TypeParameter) {
|
||||
name = first.name
|
||||
isReified = first.isReified
|
||||
variance = first.variance
|
||||
}
|
||||
|
||||
override fun doCommonizeWith(next: TypeParameter) =
|
||||
name == next.name
|
||||
&& isReified == next.isReified
|
||||
&& variance == next.variance
|
||||
&& upperBounds.commonizeWith(next.upperBounds)
|
||||
}
|
||||
|
||||
private class TypeParameterUpperBoundsCommonizer : AbstractListCommonizer<KotlinType, UnwrappedType>(
|
||||
singleElementCommonizerFactory = { TypeCommonizer.default() }
|
||||
private class TypeParameterUpperBoundsCommonizer(cache: ClassifiersCache) : AbstractListCommonizer<KotlinType, UnwrappedType>(
|
||||
singleElementCommonizerFactory = { TypeCommonizer.default(cache) }
|
||||
)
|
||||
|
||||
interface TypeParameterListCommonizer : Commonizer<List<TypeParameterDescriptor>, List<TypeParameter>> {
|
||||
interface TypeParameterListCommonizer : Commonizer<List<TypeParameter>, List<TypeParameter>> {
|
||||
companion object {
|
||||
fun default(): TypeParameterListCommonizer = DefaultTypeParameterListCommonizer()
|
||||
fun default(cache: ClassifiersCache): TypeParameterListCommonizer = DefaultTypeParameterListCommonizer(cache)
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultTypeParameterListCommonizer :
|
||||
private class DefaultTypeParameterListCommonizer(cache: ClassifiersCache) :
|
||||
TypeParameterListCommonizer,
|
||||
AbstractNamedListCommonizer<TypeParameterDescriptor, TypeParameter>(
|
||||
singleElementCommonizerFactory = { TypeParameterCommonizer.default() }
|
||||
AbstractListCommonizer<TypeParameter, TypeParameter>(
|
||||
singleElementCommonizerFactory = { TypeParameterCommonizer.default(cache) }
|
||||
)
|
||||
|
||||
+47
-63
@@ -5,83 +5,67 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CommonValueParameter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ValueParameter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.isNull
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassifiersCache
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
|
||||
interface ValueParameterCommonizer : Commonizer<ValueParameterDescriptor, ValueParameter> {
|
||||
interface ValueParameterCommonizer : Commonizer<ValueParameter, ValueParameter> {
|
||||
companion object {
|
||||
fun default(): ValueParameterCommonizer = DefaultValueParameterCommonizer()
|
||||
fun default(cache: ClassifiersCache): ValueParameterCommonizer = DefaultValueParameterCommonizer(cache)
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultValueParameterCommonizer : ValueParameterCommonizer {
|
||||
private enum class State {
|
||||
EMPTY,
|
||||
ERROR,
|
||||
IN_PROGRESS
|
||||
}
|
||||
private class DefaultValueParameterCommonizer(cache: ClassifiersCache) :
|
||||
ValueParameterCommonizer,
|
||||
AbstractStandardCommonizer<ValueParameter, ValueParameter>() {
|
||||
|
||||
private lateinit var name: Name
|
||||
private val returnType = TypeCommonizer.default()
|
||||
private val returnType = TypeCommonizer.default(cache)
|
||||
private var varargElementType: UnwrappedType? = null
|
||||
private var isCrossinline = true
|
||||
private var isNoinline = true
|
||||
|
||||
private var state = State.EMPTY
|
||||
|
||||
override val result: ValueParameter
|
||||
get() = when (state) {
|
||||
State.EMPTY, State.ERROR -> throw IllegalCommonizerStateException()
|
||||
State.IN_PROGRESS -> CommonValueParameter(
|
||||
name = name,
|
||||
returnType = returnType.result,
|
||||
varargElementType = varargElementType,
|
||||
isCrossinline = isCrossinline,
|
||||
isNoinline = isNoinline
|
||||
)
|
||||
}
|
||||
|
||||
override fun commonizeWith(next: ValueParameterDescriptor): Boolean {
|
||||
if (state == State.ERROR)
|
||||
return true
|
||||
|
||||
val result = !next.declaresDefaultValue() && returnType.commonizeWith(next.type)
|
||||
state = if (!result)
|
||||
State.ERROR
|
||||
else when {
|
||||
state == State.EMPTY -> {
|
||||
name = next.name
|
||||
varargElementType = next.varargElementType?.unwrap()
|
||||
isCrossinline = next.isCrossinline
|
||||
isNoinline = next.isNoinline
|
||||
|
||||
State.IN_PROGRESS
|
||||
}
|
||||
varargElementType.isNull() != next.varargElementType.isNull() -> State.ERROR
|
||||
else -> {
|
||||
isCrossinline = isCrossinline && next.isCrossinline
|
||||
isNoinline = isNoinline && next.isNoinline
|
||||
|
||||
State.IN_PROGRESS
|
||||
}
|
||||
}
|
||||
|
||||
return state != State.ERROR
|
||||
}
|
||||
}
|
||||
|
||||
interface ValueParameterListCommonizer : Commonizer<List<ValueParameterDescriptor>, List<ValueParameter>> {
|
||||
companion object {
|
||||
fun default(): ValueParameterListCommonizer = DefaultValueParameterListCommonizer()
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultValueParameterListCommonizer :
|
||||
ValueParameterListCommonizer,
|
||||
AbstractNamedListCommonizer<ValueParameterDescriptor, ValueParameter>(
|
||||
singleElementCommonizerFactory = { ValueParameterCommonizer.default() }
|
||||
override fun commonizationResult() = CommonValueParameter(
|
||||
name = name,
|
||||
returnType = returnType.result,
|
||||
varargElementType = varargElementType,
|
||||
isCrossinline = isCrossinline,
|
||||
isNoinline = isNoinline
|
||||
)
|
||||
|
||||
override fun initialize(first: ValueParameter) {
|
||||
name = first.name
|
||||
varargElementType = first.varargElementType
|
||||
isCrossinline = first.isCrossinline
|
||||
isNoinline = first.isNoinline
|
||||
}
|
||||
|
||||
override fun doCommonizeWith(next: ValueParameter): Boolean {
|
||||
val result = !next.declaresDefaultValue
|
||||
&& varargElementType.isNull() == next.varargElementType.isNull()
|
||||
&& name == next.name
|
||||
&& returnType.commonizeWith(next.returnType)
|
||||
|
||||
if (result) {
|
||||
isCrossinline = isCrossinline && next.isCrossinline
|
||||
isNoinline = isNoinline && next.isNoinline
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
interface ValueParameterListCommonizer : Commonizer<List<ValueParameter>, List<ValueParameter>> {
|
||||
companion object {
|
||||
fun default(cache: ClassifiersCache): ValueParameterListCommonizer = DefaultValueParameterListCommonizer(cache)
|
||||
}
|
||||
}
|
||||
|
||||
private class DefaultValueParameterListCommonizer(cache: ClassifiersCache) :
|
||||
ValueParameterListCommonizer,
|
||||
AbstractListCommonizer<ValueParameter, ValueParameter>(
|
||||
singleElementCommonizerFactory = { ValueParameterCommonizer.default(cache) }
|
||||
)
|
||||
|
||||
+37
-9
@@ -5,13 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.DeclarationWithVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.MaybeVirtualCallableMember
|
||||
|
||||
abstract class VisibilityCommonizer : Commonizer<Visibility, Visibility> {
|
||||
abstract class VisibilityCommonizer(private val allowPrivate: Boolean) : Commonizer<DeclarationWithVisibility, Visibility> {
|
||||
|
||||
companion object {
|
||||
fun lowering(): VisibilityCommonizer = LoweringVisibilityCommonizer()
|
||||
fun lowering(allowPrivate: Boolean = false): VisibilityCommonizer = LoweringVisibilityCommonizer(allowPrivate)
|
||||
fun equalizing(): VisibilityCommonizer = EqualizingVisibilityCommonizer()
|
||||
}
|
||||
|
||||
@@ -22,33 +23,60 @@ abstract class VisibilityCommonizer : Commonizer<Visibility, Visibility> {
|
||||
return temp?.takeIf { it != Visibilities.UNKNOWN } ?: throw IllegalCommonizerStateException()
|
||||
}
|
||||
|
||||
override fun commonizeWith(next: Visibility): Boolean {
|
||||
override fun commonizeWith(next: DeclarationWithVisibility): Boolean {
|
||||
if (temp == Visibilities.UNKNOWN)
|
||||
return false
|
||||
|
||||
if (Visibilities.isPrivate(next)) {
|
||||
val nextVisibility = next.visibility
|
||||
if (!allowPrivate && Visibilities.isPrivate(nextVisibility) || !canBeCommonized(next)) {
|
||||
temp = Visibilities.UNKNOWN
|
||||
return false
|
||||
}
|
||||
|
||||
temp = temp?.let { temp -> getNext(temp, next) } ?: next
|
||||
temp = temp?.let { temp -> getNext(temp, nextVisibility) } ?: nextVisibility
|
||||
|
||||
return temp != Visibilities.UNKNOWN
|
||||
}
|
||||
|
||||
protected abstract fun canBeCommonized(next: DeclarationWithVisibility): Boolean
|
||||
protected abstract fun getNext(current: Visibility, next: Visibility): Visibility
|
||||
}
|
||||
|
||||
private class LoweringVisibilityCommonizer : VisibilityCommonizer() {
|
||||
/**
|
||||
* Choose the lowest possible visibility ignoring private for all given member descriptors, if possible.
|
||||
* If at least one member descriptor is virtual, then the commonizer succeeds only if all visibilities are equal.
|
||||
*/
|
||||
private class LoweringVisibilityCommonizer(allowPrivate: Boolean) : VisibilityCommonizer(allowPrivate) {
|
||||
private var atLeastOneVirtualCallableMet = false
|
||||
private var atLeastTwoVisibilitiesMet = false
|
||||
|
||||
override fun canBeCommonized(next: DeclarationWithVisibility): Boolean {
|
||||
if (!atLeastOneVirtualCallableMet)
|
||||
atLeastOneVirtualCallableMet = (next as? MaybeVirtualCallableMember)?.isVirtual == true
|
||||
|
||||
return !atLeastOneVirtualCallableMet || !atLeastTwoVisibilitiesMet
|
||||
}
|
||||
|
||||
override fun getNext(current: Visibility, next: Visibility): Visibility {
|
||||
val comparisonResult: Int = Visibilities.compare(current, next)
|
||||
?: return Visibilities.UNKNOWN // two visibilities that can't be compared against each one, ex: protected vs internal
|
||||
|
||||
if (!atLeastTwoVisibilitiesMet)
|
||||
atLeastTwoVisibilitiesMet = comparisonResult != 0
|
||||
|
||||
if (atLeastOneVirtualCallableMet && atLeastTwoVisibilitiesMet)
|
||||
return Visibilities.UNKNOWN
|
||||
|
||||
return if (comparisonResult <= 0) current else next
|
||||
}
|
||||
}
|
||||
|
||||
private class EqualizingVisibilityCommonizer : VisibilityCommonizer() {
|
||||
/**
|
||||
* Make sure that visibilities of all member descriptors are equal are not private according to [Visibilities.isPrivate].
|
||||
*/
|
||||
private class EqualizingVisibilityCommonizer : VisibilityCommonizer(false) {
|
||||
override fun canBeCommonized(next: DeclarationWithVisibility) = true
|
||||
|
||||
override fun getNext(current: Visibility, next: Visibility) =
|
||||
if (Visibilities.compare(current, next) == 0) current else Visibilities.UNKNOWN
|
||||
}
|
||||
|
||||
@@ -8,12 +8,13 @@ package org.jetbrains.kotlin.descriptors.commonizer
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.builder.DeclarationsBuilderVisitor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.core.CommonizationVisitor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.mergeRoots
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
|
||||
class CommonizationSession {
|
||||
// TODO: add progress tracker
|
||||
// TODO: add logger
|
||||
// TODO (???): add progress tracker
|
||||
// TODO (???): add logger
|
||||
}
|
||||
|
||||
class CommonizationParameters {
|
||||
@@ -63,13 +64,17 @@ fun runCommonization(parameters: CommonizationParameters): CommonizationResult {
|
||||
if (!parameters.hasIntersection())
|
||||
return NothingToCommonize
|
||||
|
||||
val mergedTree = mergeRoots(parameters.getModulesByTargets())
|
||||
|
||||
// build merged tree:
|
||||
val storageManager = LockBasedStorageManager("Declaration descriptors commonization")
|
||||
val mergedTree = mergeRoots(storageManager, parameters.getModulesByTargets())
|
||||
|
||||
// commonize:
|
||||
mergedTree.accept(CommonizationVisitor(mergedTree), Unit)
|
||||
|
||||
var commonModules: Collection<ModuleDescriptor>? = null
|
||||
val otherModulesByTargets = LinkedHashMap<String, Collection<ModuleDescriptor>>()
|
||||
|
||||
// build resulting descriptors:
|
||||
val visitor = DeclarationsBuilderVisitor(storageManager, DefaultBuiltIns.Instance) { targetId, commonizedModules ->
|
||||
when (targetId) {
|
||||
is CommonTargetId -> {
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassifiersCache
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildClassConstructorNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildFunctionNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildPropertyNode
|
||||
import org.jetbrains.kotlin.storage.NullableLazyValue
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
internal fun mergeProperties(
|
||||
storageManager: StorageManager,
|
||||
cache: ClassifiersCache,
|
||||
containingDeclarationCommon: NullableLazyValue<*>?,
|
||||
properties: List<PropertyDescriptor?>
|
||||
) = buildPropertyNode(storageManager, cache, containingDeclarationCommon, properties)
|
||||
|
||||
internal fun mergeFunctions(
|
||||
storageManager: StorageManager,
|
||||
cache: ClassifiersCache,
|
||||
containingDeclarationCommon: NullableLazyValue<*>?,
|
||||
properties: List<SimpleFunctionDescriptor?>
|
||||
) = buildFunctionNode(storageManager, cache, containingDeclarationCommon, properties)
|
||||
|
||||
internal fun mergeClassConstructors(
|
||||
storageManager: StorageManager,
|
||||
cache: ClassifiersCache,
|
||||
containingDeclarationCommon: NullableLazyValue<*>?,
|
||||
constructors: List<ClassConstructorDescriptor?>
|
||||
) = buildClassConstructorNode(storageManager, cache, containingDeclarationCommon, constructors)
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroupMap
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.RootNode.ClassifiersCacheImpl
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildClassNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildTypeAliasNode
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.storage.NullableLazyValue
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
internal fun mergeClasses(
|
||||
storageManager: StorageManager,
|
||||
cacheRW: ClassifiersCacheImpl,
|
||||
containingDeclarationCommon: NullableLazyValue<*>?,
|
||||
classes: List<ClassDescriptor?>
|
||||
): ClassNode {
|
||||
val node = buildClassNode(storageManager, cacheRW, containingDeclarationCommon, classes)
|
||||
|
||||
val constructorsMap = CommonizedGroupMap<ConstructorApproximationKey, ClassConstructorDescriptor>(classes.size)
|
||||
val propertiesMap = CommonizedGroupMap<PropertyApproximationKey, PropertyDescriptor>(classes.size)
|
||||
val functionsMap = CommonizedGroupMap<FunctionApproximationKey, SimpleFunctionDescriptor>(classes.size)
|
||||
val classesMap = CommonizedGroupMap<Name, ClassDescriptor>(classes.size)
|
||||
|
||||
classes.forEachIndexed { index, clazz ->
|
||||
clazz?.constructors?.forEach { constructorsMap[ConstructorApproximationKey(it)][index] = it }
|
||||
clazz?.unsubstitutedMemberScope?.collectMembers(
|
||||
CallableMemberCollector<PropertyDescriptor> { propertiesMap[PropertyApproximationKey(it)][index] = it },
|
||||
CallableMemberCollector<SimpleFunctionDescriptor> { functionsMap[FunctionApproximationKey(it)][index] = it },
|
||||
Collector<ClassDescriptor> { classesMap[it.name][index] = it }
|
||||
)
|
||||
}
|
||||
|
||||
for ((_, constructorsGroup) in constructorsMap) {
|
||||
node.constructors += mergeClassConstructors(storageManager, cacheRW, node.common, constructorsGroup.toList())
|
||||
}
|
||||
|
||||
for ((_, propertiesGroup) in propertiesMap) {
|
||||
node.properties += mergeProperties(storageManager, cacheRW, node.common, propertiesGroup.toList())
|
||||
}
|
||||
|
||||
for ((_, functionsGroup) in functionsMap) {
|
||||
node.functions += mergeFunctions(storageManager, cacheRW, node.common, functionsGroup.toList())
|
||||
}
|
||||
|
||||
for ((_, classesGroup) in classesMap) {
|
||||
node.classes += mergeClasses(storageManager, cacheRW, node.common, classesGroup.toList())
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
internal fun mergeTypeAliases(
|
||||
storageManager: StorageManager,
|
||||
cacheRW: ClassifiersCacheImpl,
|
||||
typeAliases: List<TypeAliasDescriptor?>
|
||||
) = buildTypeAliasNode(storageManager, cacheRW, typeAliases)
|
||||
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildFunctionNode
|
||||
|
||||
internal fun mergeFunctions(properties: List<SimpleFunctionDescriptor?>) = buildFunctionNode(properties)
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ExtensionReceiver.Companion.toReceiver
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
|
||||
interface CallableMember : DeclarationWithTypeParameters {
|
||||
val annotations: Annotations
|
||||
val name: Name
|
||||
val modality: Modality
|
||||
val visibility: Visibility
|
||||
val isExternal: Boolean
|
||||
val extensionReceiver: ExtensionReceiver?
|
||||
val returnType: UnwrappedType
|
||||
val kind: CallableMemberDescriptor.Kind
|
||||
}
|
||||
|
||||
abstract class CommonCallableMember : CallableMember {
|
||||
final override val annotations: Annotations get() = Annotations.EMPTY
|
||||
final override val kind get() = CallableMemberDescriptor.Kind.DECLARATION
|
||||
}
|
||||
|
||||
abstract class TargetCallableMember<T : CallableMemberDescriptor>(protected val descriptor: T) : CallableMember {
|
||||
final override val annotations: Annotations get() = descriptor.annotations
|
||||
final override val name: Name get() = descriptor.name
|
||||
final override val modality: Modality get() = descriptor.modality
|
||||
final override val visibility: Visibility get() = descriptor.visibility
|
||||
final override val isExternal: Boolean get() = descriptor.isExternal
|
||||
final override val extensionReceiver: ExtensionReceiver? get() = descriptor.extensionReceiverParameter?.toReceiver()
|
||||
final override val returnType: UnwrappedType get() = descriptor.returnType!!.unwrap()
|
||||
final override val kind: CallableMemberDescriptor.Kind get() = descriptor.kind
|
||||
final override val typeParameters: List<TypeParameter> get() = descriptor.typeParameters.map(::TargetTypeParameter)
|
||||
}
|
||||
|
||||
data class ExtensionReceiver(
|
||||
val annotations: Annotations,
|
||||
val type: UnwrappedType
|
||||
) {
|
||||
companion object {
|
||||
fun UnwrappedType.toReceiverNoAnnotations() = ExtensionReceiver(Annotations.EMPTY, this)
|
||||
fun ReceiverParameterDescriptor.toReceiver() = ExtensionReceiver(annotations, type.unwrap())
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
|
||||
interface ClassDeclaration : AnnotatedDeclaration, NamedDeclaration, DeclarationWithTypeParameters, DeclarationWithVisibility {
|
||||
val companion: FqName? // null means no companion object
|
||||
val kind: ClassKind
|
||||
val modality: Modality
|
||||
val isCompanion: Boolean
|
||||
val isData: Boolean
|
||||
val isInline: Boolean
|
||||
val isInner: Boolean
|
||||
val isExternal: Boolean
|
||||
val sealedSubclasses: Collection<FqName>
|
||||
val supertypes: Collection<KotlinType>
|
||||
}
|
||||
|
||||
interface ClassConstructor : AnnotatedDeclaration, DeclarationWithTypeParameters, DeclarationWithVisibility, CallableMemberWithParameters {
|
||||
val isPrimary: Boolean
|
||||
val kind: CallableMemberDescriptor.Kind
|
||||
}
|
||||
|
||||
data class CommonClassDeclaration(
|
||||
override val name: Name,
|
||||
override val typeParameters: List<TypeParameter>,
|
||||
override val kind: ClassKind,
|
||||
override val modality: Modality,
|
||||
override val visibility: Visibility,
|
||||
override val isCompanion: Boolean,
|
||||
override val isInline: Boolean,
|
||||
override val isInner: Boolean
|
||||
) : ClassDeclaration {
|
||||
override val annotations get() = Annotations.EMPTY
|
||||
override val isData get() = false
|
||||
override val isExternal get() = false
|
||||
override var companion: FqName? = null
|
||||
override val sealedSubclasses: Collection<FqName> get() = emptyList()
|
||||
override val supertypes: MutableCollection<KotlinType> = ArrayList()
|
||||
}
|
||||
|
||||
data class CommonClassConstructor(
|
||||
override val isPrimary: Boolean,
|
||||
override val kind: CallableMemberDescriptor.Kind,
|
||||
override val visibility: Visibility,
|
||||
override val typeParameters: List<TypeParameter>,
|
||||
override val valueParameters: List<ValueParameter>,
|
||||
override val hasStableParameterNames: Boolean,
|
||||
override val hasSynthesizedParameterNames: Boolean
|
||||
) : ClassConstructor {
|
||||
override val annotations: Annotations get() = Annotations.EMPTY
|
||||
}
|
||||
|
||||
class TargetClassDeclaration(private val descriptor: ClassDescriptor) : ClassDeclaration {
|
||||
override val annotations get() = descriptor.annotations
|
||||
override val name get() = descriptor.name
|
||||
override val typeParameters by lazy(PUBLICATION) { descriptor.declaredTypeParameters.map(::TargetTypeParameter) }
|
||||
override val companion by lazy(PUBLICATION) { descriptor.companionObjectDescriptor?.fqNameSafe }
|
||||
override val kind get() = descriptor.kind
|
||||
override val modality get() = descriptor.modality
|
||||
override val visibility get() = descriptor.visibility
|
||||
override val isCompanion get() = descriptor.isCompanionObject
|
||||
override val isData get() = descriptor.isData
|
||||
override val isInline get() = descriptor.isInline
|
||||
override val isInner get() = descriptor.isInner
|
||||
override val isExternal get() = descriptor.isExternal
|
||||
override val sealedSubclasses by lazy(PUBLICATION) { descriptor.sealedSubclasses.map { it.fqNameSafe } }
|
||||
override val supertypes: Collection<KotlinType> get() = descriptor.typeConstructor.supertypes
|
||||
}
|
||||
|
||||
class TargetClassConstructor(private val descriptor: ClassConstructorDescriptor) : ClassConstructor {
|
||||
override val isPrimary: Boolean get() = descriptor.isPrimary
|
||||
override val kind: CallableMemberDescriptor.Kind get() = descriptor.kind
|
||||
override val annotations: Annotations get() = descriptor.annotations
|
||||
override val visibility: Visibility get() = descriptor.visibility
|
||||
override val typeParameters: List<TypeParameter> by lazy(PUBLICATION) { descriptor.typeParameters.map(::TargetTypeParameter) }
|
||||
override val valueParameters: List<ValueParameter> by lazy(PUBLICATION) { descriptor.valueParameters.map(::PlatformValueParameter) }
|
||||
override val hasStableParameterNames: Boolean get() = descriptor.hasStableParameterNames()
|
||||
override val hasSynthesizedParameterNames: Boolean get() = descriptor.hasSynthesizedParameterNames()
|
||||
}
|
||||
|
||||
object ClassDeclarationRecursionMarker : ClassDeclaration, RecursionMarker {
|
||||
override val companion: FqName? get() = unsupported()
|
||||
override val kind: ClassKind get() = unsupported()
|
||||
override val modality: Modality get() = unsupported()
|
||||
override val isCompanion: Boolean get() = unsupported()
|
||||
override val isData: Boolean get() = unsupported()
|
||||
override val isInline: Boolean get() = unsupported()
|
||||
override val isInner: Boolean get() = unsupported()
|
||||
override val isExternal: Boolean get() = unsupported()
|
||||
override val sealedSubclasses: Collection<FqName> get() = unsupported()
|
||||
override val supertypes: Collection<KotlinType> get() = unsupported()
|
||||
override val annotations: Annotations get() = unsupported()
|
||||
override val name: Name get() = unsupported()
|
||||
override val visibility: Visibility get() = unsupported()
|
||||
override val typeParameters: List<TypeParameter> get() = unsupported()
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
/**
|
||||
* An intermediate representation of [DeclarationDescriptor]s for commonization purposes.
|
||||
*
|
||||
* The most essential subclasses are:
|
||||
* - [ClassDeclaration] - represents [ClassDescriptor]
|
||||
* - [TypeAlias] - [TypeAliasDescriptor]
|
||||
* - [Function] - [SimpleFunctionDescriptor]
|
||||
* - [Property] - [PropertyDescriptor]
|
||||
* - [Package] - union of multiple [PackageFragmentDescriptor]s with the same [FqName] contributed by commonized [ModuleDescriptor]s
|
||||
* - [Module] - [ModuleDescriptor]
|
||||
* - [Root] - the root of the whole IR tree
|
||||
*/
|
||||
interface Declaration
|
||||
|
||||
interface AnnotatedDeclaration : Declaration {
|
||||
val annotations: Annotations
|
||||
}
|
||||
|
||||
interface NamedDeclaration : Declaration {
|
||||
val name: Name
|
||||
}
|
||||
|
||||
interface DeclarationWithVisibility : Declaration {
|
||||
val visibility: Visibility
|
||||
}
|
||||
|
||||
interface MaybeVirtualCallableMember : DeclarationWithVisibility {
|
||||
val isVirtual: Boolean
|
||||
}
|
||||
|
||||
interface DeclarationWithTypeParameters : Declaration {
|
||||
val typeParameters: List<TypeParameter>
|
||||
}
|
||||
|
||||
/** Indicates presence of recursion in lazy calculations. */
|
||||
interface RecursionMarker : Declaration
|
||||
|
||||
@Suppress("unused")
|
||||
internal fun Declaration.unsupported(): Nothing = error("This method should never be called")
|
||||
+28
-19
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
|
||||
interface FunctionModifiers {
|
||||
val isOperator: Boolean
|
||||
@@ -22,10 +23,14 @@ interface FunctionModifiers {
|
||||
val isExternal: Boolean
|
||||
}
|
||||
|
||||
interface Function : CallableMember, FunctionModifiers, Declaration {
|
||||
interface CallableMemberWithParameters {
|
||||
val valueParameters: List<ValueParameter>
|
||||
val hasStableParameterNames: Boolean
|
||||
val hasSynthesizedParameterNames: Boolean
|
||||
}
|
||||
|
||||
interface Function : FunctionOrProperty, FunctionModifiers, CallableMemberWithParameters
|
||||
|
||||
data class CommonFunction(
|
||||
override val name: Name,
|
||||
override val modality: Modality,
|
||||
@@ -34,16 +39,20 @@ data class CommonFunction(
|
||||
override val returnType: UnwrappedType,
|
||||
private val modifiers: FunctionModifiers,
|
||||
override val valueParameters: List<ValueParameter>,
|
||||
override val typeParameters: List<TypeParameter>
|
||||
) : CommonCallableMember(), Function, FunctionModifiers by modifiers
|
||||
override val typeParameters: List<TypeParameter>,
|
||||
override val hasStableParameterNames: Boolean,
|
||||
override val hasSynthesizedParameterNames: Boolean
|
||||
) : CommonFunctionOrProperty(), Function, FunctionModifiers by modifiers
|
||||
|
||||
class TargetFunction(descriptor: SimpleFunctionDescriptor) : TargetCallableMember<SimpleFunctionDescriptor>(descriptor), Function {
|
||||
override val isOperator: Boolean get() = descriptor.isOperator
|
||||
override val isInfix: Boolean get() = descriptor.isInfix
|
||||
override val isInline: Boolean get() = descriptor.isInline
|
||||
override val isTailrec: Boolean get() = descriptor.isTailrec
|
||||
override val isSuspend: Boolean get() = descriptor.isSuspend
|
||||
override val valueParameters: List<ValueParameter> get() = descriptor.valueParameters.map(::PlatformValueParameter)
|
||||
class TargetFunction(descriptor: SimpleFunctionDescriptor) : TargetFunctionOrProperty<SimpleFunctionDescriptor>(descriptor), Function {
|
||||
override val isOperator get() = descriptor.isOperator
|
||||
override val isInfix get() = descriptor.isInfix
|
||||
override val isInline get() = descriptor.isInline
|
||||
override val isTailrec get() = descriptor.isTailrec
|
||||
override val isSuspend get() = descriptor.isSuspend
|
||||
override val valueParameters by lazy(PUBLICATION) { descriptor.valueParameters.map(::PlatformValueParameter) }
|
||||
override val hasStableParameterNames: Boolean get() = descriptor.hasStableParameterNames()
|
||||
override val hasSynthesizedParameterNames: Boolean get() = descriptor.hasSynthesizedParameterNames()
|
||||
}
|
||||
|
||||
interface ValueParameter {
|
||||
@@ -63,16 +72,16 @@ data class CommonValueParameter(
|
||||
override val isCrossinline: Boolean,
|
||||
override val isNoinline: Boolean
|
||||
) : ValueParameter {
|
||||
override val annotations: Annotations get() = Annotations.EMPTY
|
||||
override val declaresDefaultValue: Boolean get() = false
|
||||
override val annotations get() = Annotations.EMPTY
|
||||
override val declaresDefaultValue get() = false
|
||||
}
|
||||
|
||||
data class PlatformValueParameter(private val descriptor: ValueParameterDescriptor) : ValueParameter {
|
||||
override val name: Name get() = descriptor.name
|
||||
override val annotations: Annotations get() = descriptor.annotations
|
||||
override val returnType: UnwrappedType get() = descriptor.returnType!!.unwrap()
|
||||
override val varargElementType: UnwrappedType? get() = descriptor.varargElementType?.unwrap()
|
||||
override val declaresDefaultValue: Boolean get() = descriptor.declaresDefaultValue()
|
||||
override val isCrossinline: Boolean get() = descriptor.isCrossinline
|
||||
override val isNoinline: Boolean get() = descriptor.isNoinline
|
||||
override val name get() = descriptor.name
|
||||
override val annotations get() = descriptor.annotations
|
||||
override val returnType by lazy(PUBLICATION) { descriptor.returnType!!.unwrap() }
|
||||
override val varargElementType by lazy(PUBLICATION) { descriptor.varargElementType?.unwrap() }
|
||||
override val declaresDefaultValue get() = descriptor.declaresDefaultValue()
|
||||
override val isCrossinline get() = descriptor.isCrossinline
|
||||
override val isNoinline get() = descriptor.isNoinline
|
||||
}
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ExtensionReceiver.Companion.toReceiver
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
|
||||
interface FunctionOrProperty : AnnotatedDeclaration, NamedDeclaration, DeclarationWithTypeParameters, MaybeVirtualCallableMember {
|
||||
val modality: Modality
|
||||
val isExternal: Boolean
|
||||
val extensionReceiver: ExtensionReceiver?
|
||||
val returnType: UnwrappedType
|
||||
val kind: CallableMemberDescriptor.Kind
|
||||
val isNonAbstractCallableMemberInInterface: Boolean
|
||||
}
|
||||
|
||||
abstract class CommonFunctionOrProperty : FunctionOrProperty {
|
||||
final override val annotations get() = Annotations.EMPTY
|
||||
final override val kind get() = CallableMemberDescriptor.Kind.DECLARATION
|
||||
final override val isVirtual get() = unsupported()
|
||||
final override val isNonAbstractCallableMemberInInterface get() = unsupported()
|
||||
}
|
||||
|
||||
abstract class TargetFunctionOrProperty<T : CallableMemberDescriptor>(protected val descriptor: T) : FunctionOrProperty {
|
||||
final override val annotations get() = descriptor.annotations
|
||||
final override val name get() = descriptor.name
|
||||
final override val modality get() = descriptor.modality
|
||||
final override val visibility get() = descriptor.visibility
|
||||
final override val isExternal get() = descriptor.isExternal
|
||||
final override val extensionReceiver by lazy(PUBLICATION) { descriptor.extensionReceiverParameter?.toReceiver() }
|
||||
final override val returnType by lazy(PUBLICATION) { descriptor.returnType!!.unwrap() }
|
||||
final override val kind get() = descriptor.kind
|
||||
final override val isVirtual get() = descriptor.isOverridable
|
||||
final override val isNonAbstractCallableMemberInInterface
|
||||
get() = modality != Modality.ABSTRACT && (descriptor.containingDeclaration as? ClassDescriptor)?.kind == ClassKind.INTERFACE
|
||||
final override val typeParameters by lazy(PUBLICATION) { descriptor.typeParameters.map(::TargetTypeParameter) }
|
||||
}
|
||||
|
||||
data class ExtensionReceiver(
|
||||
val annotations: Annotations,
|
||||
val type: UnwrappedType
|
||||
) {
|
||||
companion object {
|
||||
fun UnwrappedType.toReceiverNoAnnotations() = ExtensionReceiver(Annotations.EMPTY, this)
|
||||
fun ReceiverParameterDescriptor.toReceiver() = ExtensionReceiver(annotations, type.unwrap())
|
||||
}
|
||||
}
|
||||
+3
@@ -11,4 +11,7 @@ interface NodeVisitor<R, T> {
|
||||
fun visitPackageNode(node: PackageNode, data: T): R
|
||||
fun visitPropertyNode(node: PropertyNode, data: T): R
|
||||
fun visitFunctionNode(node: FunctionNode, data: T): R
|
||||
fun visitClassNode(node: ClassNode, data: T): R
|
||||
fun visitClassConstructorNode(node: ClassConstructorNode, data: T): R
|
||||
fun visitTypeAliasNode(node: TypeAliasNode, data: T): R
|
||||
}
|
||||
|
||||
+23
-21
@@ -12,10 +12,11 @@ import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.Getter.Companion.toGetter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.Setter.Companion.toSetter
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
|
||||
interface Property : CallableMember, Declaration {
|
||||
interface Property : FunctionOrProperty {
|
||||
val isVar: Boolean
|
||||
val lateInit: Boolean
|
||||
val isLateInit: Boolean
|
||||
val isConst: Boolean
|
||||
val isDelegate: Boolean
|
||||
val getter: Getter?
|
||||
@@ -34,28 +35,27 @@ data class CommonProperty(
|
||||
override val returnType: UnwrappedType,
|
||||
override val setter: Setter?,
|
||||
override val typeParameters: List<TypeParameter>
|
||||
) : CommonCallableMember(), Property {
|
||||
override val isVar: Boolean get() = setter != null
|
||||
override val lateInit: Boolean get() = false
|
||||
override val isConst: Boolean get() = false
|
||||
override val isDelegate: Boolean get() = false
|
||||
override val getter: Getter get() = Getter.DEFAULT_NO_ANNOTATIONS
|
||||
) : CommonFunctionOrProperty(), Property {
|
||||
override val isVar get() = setter != null
|
||||
override val isLateInit get() = false
|
||||
override val isConst get() = false
|
||||
override val isDelegate get() = false
|
||||
override val getter get() = Getter.DEFAULT_NO_ANNOTATIONS
|
||||
override val backingFieldAnnotations: Annotations? get() = null
|
||||
override val delegateFieldAnnotations: Annotations? get() = null
|
||||
override val compileTimeInitializer: ConstantValue<*>? get() = null
|
||||
}
|
||||
|
||||
class TargetProperty(descriptor: PropertyDescriptor) : TargetCallableMember<PropertyDescriptor>(descriptor), Property {
|
||||
override val isVar: Boolean get() = descriptor.isVar
|
||||
override val lateInit: Boolean get() = descriptor.isLateInit
|
||||
override val isConst: Boolean get() = descriptor.isConst
|
||||
@Suppress("DEPRECATION")
|
||||
override val isDelegate: Boolean get() = descriptor.isDelegated
|
||||
override val getter: Getter? get() = descriptor.getter?.toGetter()
|
||||
override val setter: Setter? get() = descriptor.setter?.toSetter()
|
||||
override val backingFieldAnnotations: Annotations? get() = descriptor.backingField?.annotations
|
||||
override val delegateFieldAnnotations: Annotations? get() = descriptor.delegateField?.annotations
|
||||
override val compileTimeInitializer: ConstantValue<*>? get() = descriptor.compileTimeInitializer
|
||||
class TargetProperty(descriptor: PropertyDescriptor) : TargetFunctionOrProperty<PropertyDescriptor>(descriptor), Property {
|
||||
override val isVar get() = descriptor.isVar
|
||||
override val isLateInit get() = descriptor.isLateInit
|
||||
override val isConst get() = descriptor.isConst
|
||||
override val isDelegate get() = @Suppress("DEPRECATION") descriptor.isDelegated
|
||||
override val getter by lazy(PUBLICATION) { descriptor.getter?.toGetter() }
|
||||
override val setter by lazy(PUBLICATION) { descriptor.setter?.toSetter() }
|
||||
override val backingFieldAnnotations get() = descriptor.backingField?.annotations
|
||||
override val delegateFieldAnnotations get() = descriptor.delegateField?.annotations
|
||||
override val compileTimeInitializer get() = descriptor.compileTimeInitializer
|
||||
}
|
||||
|
||||
interface PropertyAccessor {
|
||||
@@ -85,11 +85,13 @@ data class Getter(
|
||||
data class Setter(
|
||||
override val annotations: Annotations,
|
||||
val parameterAnnotations: Annotations,
|
||||
val visibility: Visibility,
|
||||
override val visibility: Visibility,
|
||||
override val isDefault: Boolean,
|
||||
override val isExternal: Boolean,
|
||||
override val isInline: Boolean
|
||||
) : PropertyAccessor {
|
||||
) : PropertyAccessor, MaybeVirtualCallableMember {
|
||||
override val isVirtual get() = false
|
||||
|
||||
companion object {
|
||||
fun createDefaultNoAnnotations(visibility: Visibility) = Setter(
|
||||
Annotations.EMPTY,
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
|
||||
interface TypeAlias : AnnotatedDeclaration, NamedDeclaration, DeclarationWithTypeParameters, DeclarationWithVisibility {
|
||||
val underlyingType: SimpleType
|
||||
val expandedType: SimpleType
|
||||
}
|
||||
|
||||
class TargetTypeAlias(private val descriptor: TypeAliasDescriptor) : TypeAlias {
|
||||
override val annotations get() = descriptor.annotations
|
||||
override val name get() = descriptor.name
|
||||
override val typeParameters by lazy(PUBLICATION) { descriptor.declaredTypeParameters.map(::TargetTypeParameter) }
|
||||
override val visibility get() = descriptor.visibility
|
||||
override val underlyingType get() = descriptor.underlyingType
|
||||
override val expandedType get() = descriptor.expandedType
|
||||
}
|
||||
+7
-10
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
|
||||
interface TypeParameter {
|
||||
val annotations: Annotations
|
||||
@@ -19,23 +20,19 @@ interface TypeParameter {
|
||||
val upperBounds: List<UnwrappedType>
|
||||
}
|
||||
|
||||
interface DeclarationWithTypeParameters : Declaration {
|
||||
val typeParameters: List<TypeParameter>
|
||||
}
|
||||
|
||||
data class CommonTypeParameter(
|
||||
override val name: Name,
|
||||
override val isReified: Boolean,
|
||||
override val variance: Variance,
|
||||
override val upperBounds: List<UnwrappedType>
|
||||
) : TypeParameter {
|
||||
override val annotations: Annotations get() = Annotations.EMPTY
|
||||
override val annotations get() = Annotations.EMPTY
|
||||
}
|
||||
|
||||
data class TargetTypeParameter(private val descriptor: TypeParameterDescriptor) : TypeParameter {
|
||||
override val annotations: Annotations get() = descriptor.annotations
|
||||
override val name: Name get() = descriptor.name
|
||||
override val isReified: Boolean get() = descriptor.isReified
|
||||
override val variance: Variance get() = descriptor.variance
|
||||
override val upperBounds: List<UnwrappedType> get() = descriptor.upperBounds.map { it.unwrap() }
|
||||
override val annotations get() = descriptor.annotations
|
||||
override val name get() = descriptor.name
|
||||
override val isReified get() = descriptor.isReified
|
||||
override val variance get() = descriptor.variance
|
||||
override val upperBounds by lazy(PUBLICATION) { descriptor.upperBounds.map { it.unwrap() } }
|
||||
}
|
||||
|
||||
+157
-41
@@ -5,77 +5,193 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroup
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.core.Commonizer
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.core.PropertyCommonizer
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.core.FunctionCommonizer
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.core.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.firstNonNull
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.RootNode.ClassifiersCacheImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.storage.NullableLazyValue
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
internal fun buildRootNode(targets: List<ConcreteTargetId>): RootNode = RootNode(
|
||||
targets.map { Root(it) },
|
||||
Root(CommonTargetId(targets.toSet()))
|
||||
internal fun buildRootNode(
|
||||
targets: List<ConcreteTargetId>
|
||||
): RootNode = RootNode(
|
||||
target = targets.map { Root(it) },
|
||||
common = LockBasedStorageManager.NO_LOCKS.createNullableLazyValue {
|
||||
Root(CommonTargetId(targets.toSet()))
|
||||
}
|
||||
)
|
||||
|
||||
internal fun buildModuleNode(modules: List<ModuleDescriptor?>): ModuleNode = buildNode(
|
||||
modules,
|
||||
{ Module(it.name) },
|
||||
{ Module(it.firstNonNull().name) },
|
||||
::ModuleNode
|
||||
internal fun buildModuleNode(
|
||||
moduleName: Name,
|
||||
modules: List<ModuleDescriptor?>
|
||||
): ModuleNode = buildNode(
|
||||
storageManager = LockBasedStorageManager.NO_LOCKS,
|
||||
descriptors = modules,
|
||||
targetDeclarationProducer = { Module(moduleName) },
|
||||
commonValueProducer = { Module(moduleName) },
|
||||
recursionMarker = null,
|
||||
nodeProducer = ::ModuleNode
|
||||
)
|
||||
|
||||
internal fun buildPackageNode(packageFqName: FqName, packageMemberScopes: List<MemberScope?>): PackageNode = buildNode(
|
||||
packageMemberScopes,
|
||||
{ Package(packageFqName) },
|
||||
{ Package(packageFqName) },
|
||||
::PackageNode
|
||||
internal fun buildPackageNode(
|
||||
packageFqName: FqName,
|
||||
packageMemberScopes: List<MemberScope?>
|
||||
): PackageNode = buildNode(
|
||||
storageManager = LockBasedStorageManager.NO_LOCKS,
|
||||
descriptors = packageMemberScopes,
|
||||
targetDeclarationProducer = { Package(packageFqName) },
|
||||
commonValueProducer = { Package(packageFqName) },
|
||||
recursionMarker = null,
|
||||
nodeProducer = ::PackageNode
|
||||
)
|
||||
|
||||
internal fun buildPropertyNode(properties: List<PropertyDescriptor?>): PropertyNode = buildNode(
|
||||
properties,
|
||||
{ TargetProperty(it) },
|
||||
{ commonize(it, PropertyCommonizer()) },
|
||||
::PropertyNode
|
||||
internal fun buildPropertyNode(
|
||||
storageManager: StorageManager,
|
||||
cache: ClassifiersCache,
|
||||
containingDeclarationCommon: NullableLazyValue<*>?,
|
||||
properties: List<PropertyDescriptor?>
|
||||
): PropertyNode = buildNode(
|
||||
storageManager = storageManager,
|
||||
descriptors = properties,
|
||||
targetDeclarationProducer = ::TargetProperty,
|
||||
commonValueProducer = { commonize(containingDeclarationCommon, it, PropertyCommonizer(cache)) },
|
||||
recursionMarker = null,
|
||||
nodeProducer = ::PropertyNode
|
||||
)
|
||||
|
||||
internal fun buildFunctionNode(functions: List<SimpleFunctionDescriptor?>): FunctionNode = buildNode(
|
||||
functions,
|
||||
{ TargetFunction(it) },
|
||||
{ commonize(it, FunctionCommonizer()) },
|
||||
::FunctionNode
|
||||
internal fun buildFunctionNode(
|
||||
storageManager: StorageManager,
|
||||
cache: ClassifiersCache,
|
||||
containingDeclarationCommon: NullableLazyValue<*>?,
|
||||
functions: List<SimpleFunctionDescriptor?>
|
||||
): FunctionNode = buildNode(
|
||||
storageManager = storageManager,
|
||||
descriptors = functions,
|
||||
targetDeclarationProducer = ::TargetFunction,
|
||||
commonValueProducer = { commonize(containingDeclarationCommon, it, FunctionCommonizer(cache)) },
|
||||
recursionMarker = null,
|
||||
nodeProducer = ::FunctionNode
|
||||
)
|
||||
|
||||
private fun <T : Any, D : Declaration, N : Node<D>> buildNode(
|
||||
descriptors: List<T?>,
|
||||
targetDeclarationProducer: (T) -> D,
|
||||
commonDeclarationProducer: (List<T?>) -> D?,
|
||||
nodeProducer: (List<D?>, D?) -> N
|
||||
internal fun buildClassNode(
|
||||
storageManager: StorageManager,
|
||||
cacheRW: ClassifiersCacheImpl,
|
||||
containingDeclarationCommon: NullableLazyValue<*>?,
|
||||
classes: List<ClassDescriptor?>
|
||||
): ClassNode {
|
||||
val fqName = classes.firstNonNull().fqNameSafe
|
||||
|
||||
return buildNode(
|
||||
storageManager = storageManager,
|
||||
descriptors = classes,
|
||||
targetDeclarationProducer = ::TargetClassDeclaration,
|
||||
commonValueProducer = { commonize(containingDeclarationCommon, it, ClassCommonizer(cacheRW)) },
|
||||
recursionMarker = ClassDeclarationRecursionMarker,
|
||||
nodeProducer = ::ClassNode
|
||||
).also { node ->
|
||||
node.fqName = fqName
|
||||
cacheRW.classes.put(fqName, node)?.let { oldNode ->
|
||||
throw IllegalStateException("Class node with FQ name $fqName has been overwritten: $oldNode")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun buildClassConstructorNode(
|
||||
storageManager: StorageManager,
|
||||
cache: ClassifiersCache,
|
||||
containingDeclarationCommon: NullableLazyValue<*>?,
|
||||
constructors: List<ClassConstructorDescriptor?>
|
||||
): ClassConstructorNode = buildNode(
|
||||
storageManager = storageManager,
|
||||
descriptors = constructors,
|
||||
targetDeclarationProducer = ::TargetClassConstructor,
|
||||
commonValueProducer = { commonize(containingDeclarationCommon, it, ClassConstructorCommonizer(cache)) },
|
||||
recursionMarker = null,
|
||||
nodeProducer = ::ClassConstructorNode
|
||||
)
|
||||
|
||||
internal fun buildTypeAliasNode(
|
||||
storageManager: StorageManager,
|
||||
cacheRW: ClassifiersCacheImpl,
|
||||
typeAliases: List<TypeAliasDescriptor?>
|
||||
): TypeAliasNode {
|
||||
val fqName = typeAliases.firstNonNull().fqNameSafe
|
||||
|
||||
return buildNode(
|
||||
storageManager = storageManager,
|
||||
descriptors = typeAliases,
|
||||
targetDeclarationProducer = ::TargetTypeAlias,
|
||||
commonValueProducer = { commonize(it, TypeAliasCommonizer(cacheRW)) },
|
||||
recursionMarker = ClassDeclarationRecursionMarker,
|
||||
nodeProducer = ::TypeAliasNode
|
||||
).also { node ->
|
||||
node.fqName = fqName
|
||||
cacheRW.typeAliases.put(fqName, node)?.let { oldNode ->
|
||||
throw IllegalStateException("Type alias node with FQ name $fqName has been overwritten: $oldNode")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <D : Any, T : Declaration, R : Declaration, N : Node<T, R>> buildNode(
|
||||
storageManager: StorageManager,
|
||||
descriptors: List<D?>,
|
||||
targetDeclarationProducer: (D) -> T,
|
||||
commonValueProducer: (List<T?>) -> R?,
|
||||
recursionMarker: R?,
|
||||
nodeProducer: (List<T?>, NullableLazyValue<R>) -> N
|
||||
): N {
|
||||
val target = CommonizedGroup<D>(descriptors.size)
|
||||
val declarationsGroup = CommonizedGroup<T>(descriptors.size)
|
||||
var canHaveCommon = descriptors.size > 1
|
||||
|
||||
descriptors.forEachIndexed { index, descriptor ->
|
||||
if (descriptor != null)
|
||||
target[index] = targetDeclarationProducer(descriptor)
|
||||
declarationsGroup[index] = targetDeclarationProducer(descriptor)
|
||||
else
|
||||
canHaveCommon = false
|
||||
}
|
||||
|
||||
val common = if (canHaveCommon) commonDeclarationProducer(descriptors) else null
|
||||
val declarations = declarationsGroup.toList()
|
||||
|
||||
return nodeProducer(target.toList(), common)
|
||||
val commonComputable: () -> R? = if (canHaveCommon) {
|
||||
{ commonValueProducer(declarations) }
|
||||
} else {
|
||||
{ null }
|
||||
}
|
||||
|
||||
val commonLazyValue = if (recursionMarker != null)
|
||||
storageManager.createRecursionTolerantNullableLazyValue(commonComputable, recursionMarker)
|
||||
else
|
||||
storageManager.createNullableLazyValue(commonComputable)
|
||||
|
||||
return nodeProducer(declarations, commonLazyValue)
|
||||
}
|
||||
|
||||
private fun <T : Any, R : Declaration> commonize(descriptors: List<T?>, commonizer: Commonizer<T, R>): R? {
|
||||
for (item in descriptors) {
|
||||
if (item == null || !commonizer.commonizeWith(item))
|
||||
internal fun <T, R> commonize(declarations: List<T?>, commonizer: Commonizer<T, R>): R? {
|
||||
for (declaration in declarations) {
|
||||
if (declaration == null || !commonizer.commonizeWith(declaration))
|
||||
return null
|
||||
}
|
||||
|
||||
return commonizer.result
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun <T, R> commonize(
|
||||
containingDeclarationCommon: NullableLazyValue<*>?,
|
||||
declarations: List<T?>,
|
||||
commonizer: Commonizer<T, R>
|
||||
): R? {
|
||||
if (containingDeclarationCommon != null && containingDeclarationCommon.invoke() == null) {
|
||||
// don't commonize declaration if it has commonizable containing declaration that has not been successfully commonized
|
||||
return null
|
||||
}
|
||||
|
||||
return commonize(declarations, commonizer)
|
||||
}
|
||||
|
||||
+63
-16
@@ -5,20 +5,27 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir
|
||||
|
||||
interface Declaration
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.storage.NullableLazyValue
|
||||
|
||||
interface Node<D : Declaration> {
|
||||
val target: List<D?>
|
||||
val common: D?
|
||||
interface Node<T : Declaration, R : Declaration> {
|
||||
val target: List<T?>
|
||||
val common: NullableLazyValue<R>
|
||||
|
||||
fun <R, T> accept(visitor: NodeVisitor<R, T>, data: T): R
|
||||
}
|
||||
|
||||
class RootNode(
|
||||
override val target: List<Root>,
|
||||
override val common: Root
|
||||
) : Node<Root> {
|
||||
override val common: NullableLazyValue<Root>
|
||||
) : Node<Root, Root> {
|
||||
class ClassifiersCacheImpl : ClassifiersCache {
|
||||
override val classes = HashMap<FqName, ClassNode>()
|
||||
override val typeAliases = HashMap<FqName, TypeAliasNode>()
|
||||
}
|
||||
|
||||
val modules: MutableList<ModuleNode> = ArrayList()
|
||||
val cache = ClassifiersCacheImpl()
|
||||
|
||||
override fun <R, T> accept(visitor: NodeVisitor<R, T>, data: T): R =
|
||||
visitor.visitRootNode(this, data)
|
||||
@@ -26,8 +33,8 @@ class RootNode(
|
||||
|
||||
class ModuleNode(
|
||||
override val target: List<Module?>,
|
||||
override val common: Module?
|
||||
) : Node<Module> {
|
||||
override val common: NullableLazyValue<Module>
|
||||
) : Node<Module, Module> {
|
||||
val packages: MutableList<PackageNode> = ArrayList()
|
||||
|
||||
override fun <R, T> accept(visitor: NodeVisitor<R, T>, data: T) =
|
||||
@@ -36,10 +43,12 @@ class ModuleNode(
|
||||
|
||||
class PackageNode(
|
||||
override val target: List<Package?>,
|
||||
override val common: Package?
|
||||
) : Node<Package> {
|
||||
override val common: NullableLazyValue<Package>
|
||||
) : Node<Package, Package> {
|
||||
val properties: MutableList<PropertyNode> = ArrayList()
|
||||
val functions: MutableList<FunctionNode> = ArrayList()
|
||||
val classes: MutableList<ClassNode> = ArrayList()
|
||||
val typeAliases: MutableList<TypeAliasNode> = ArrayList()
|
||||
|
||||
override fun <R, T> accept(visitor: NodeVisitor<R, T>, data: T) =
|
||||
visitor.visitPackageNode(this, data)
|
||||
@@ -47,22 +56,60 @@ class PackageNode(
|
||||
|
||||
class PropertyNode(
|
||||
override val target: List<Property?>,
|
||||
override val common: Property?
|
||||
) : Node<Property> {
|
||||
override val common: NullableLazyValue<Property>
|
||||
) : Node<Property, Property> {
|
||||
override fun <R, T> accept(visitor: NodeVisitor<R, T>, data: T) =
|
||||
visitor.visitPropertyNode(this, data)
|
||||
}
|
||||
|
||||
class FunctionNode(
|
||||
override val target: List<Function?>,
|
||||
override val common: Function?
|
||||
) : Node<Function> {
|
||||
override val common: NullableLazyValue<Function>
|
||||
) : Node<Function, Function> {
|
||||
override fun <R, T> accept(visitor: NodeVisitor<R, T>, data: T) =
|
||||
visitor.visitFunctionNode(this, data)
|
||||
}
|
||||
|
||||
internal val <D : Declaration> Node<D>.indexOfCommon: Int
|
||||
class ClassNode(
|
||||
override val target: List<ClassDeclaration?>,
|
||||
override val common: NullableLazyValue<ClassDeclaration>
|
||||
) : Node<ClassDeclaration, ClassDeclaration> {
|
||||
lateinit var fqName: FqName
|
||||
|
||||
val constructors: MutableList<ClassConstructorNode> = ArrayList()
|
||||
val properties: MutableList<PropertyNode> = ArrayList()
|
||||
val functions: MutableList<FunctionNode> = ArrayList()
|
||||
val classes: MutableList<ClassNode> = ArrayList()
|
||||
|
||||
override fun <R, T> accept(visitor: NodeVisitor<R, T>, data: T): R =
|
||||
visitor.visitClassNode(this, data)
|
||||
}
|
||||
|
||||
class ClassConstructorNode(
|
||||
override val target: List<ClassConstructor?>,
|
||||
override val common: NullableLazyValue<ClassConstructor>
|
||||
) : Node<ClassConstructor, ClassConstructor> {
|
||||
override fun <R, T> accept(visitor: NodeVisitor<R, T>, data: T): R =
|
||||
visitor.visitClassConstructorNode(this, data)
|
||||
}
|
||||
|
||||
class TypeAliasNode(
|
||||
override val target: List<TypeAlias?>,
|
||||
override val common: NullableLazyValue<ClassDeclaration>
|
||||
) : Node<TypeAlias, ClassDeclaration> {
|
||||
lateinit var fqName: FqName
|
||||
|
||||
override fun <R, T> accept(visitor: NodeVisitor<R, T>, data: T): R =
|
||||
visitor.visitTypeAliasNode(this, data)
|
||||
}
|
||||
|
||||
interface ClassifiersCache {
|
||||
val classes: Map<FqName, ClassNode>
|
||||
val typeAliases: Map<FqName, TypeAliasNode>
|
||||
}
|
||||
|
||||
internal inline val Node<*, *>.indexOfCommon: Int
|
||||
get() = target.size
|
||||
|
||||
internal val <D : Declaration> Node<D>.dimension: Int
|
||||
internal inline val Node<*, *>.dimension: Int
|
||||
get() = target.size + 1
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.core.Commonizer
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.fqNameWithTypeParameters
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
|
||||
internal fun MemberScope.collectMembers(vararg collectors: (DeclarationDescriptor) -> Boolean) =
|
||||
getContributedDescriptors().forEach { member ->
|
||||
collectors.any { it(member) }
|
||||
// each member must be consumed, otherwise - error
|
||||
|| throw IllegalStateException("Unhandled member declaration: $member")
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
internal inline fun <reified T : DeclarationDescriptor> Collector(
|
||||
crossinline typedCollector: (T) -> Unit
|
||||
): (DeclarationDescriptor) -> Boolean = { candidate ->
|
||||
if (candidate is T) {
|
||||
typedCollector(candidate)
|
||||
true
|
||||
} else
|
||||
false
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
internal inline fun <reified T : CallableMemberDescriptor> CallableMemberCollector(
|
||||
crossinline typedCollector: (T) -> Unit
|
||||
): (DeclarationDescriptor) -> Boolean = Collector<T> { candidate ->
|
||||
if (candidate.kind.isReal) // omit fake overrides
|
||||
typedCollector(candidate)
|
||||
}
|
||||
|
||||
/** Used for approximation of [PropertyDescriptor]s before running concrete [Commonizer]s */
|
||||
internal data class PropertyApproximationKey(
|
||||
val name: Name,
|
||||
val extensionReceiverParameter: String?
|
||||
) {
|
||||
constructor(property: PropertyDescriptor) : this(
|
||||
property.name,
|
||||
property.extensionReceiverParameter?.type?.fqNameWithTypeParameters
|
||||
)
|
||||
}
|
||||
|
||||
/** Used for approximation of [SimpleFunctionDescriptor]s before running concrete [Commonizer]s */
|
||||
internal data class FunctionApproximationKey(
|
||||
val name: Name,
|
||||
val valueParameters: List<Pair<Name, String>>,
|
||||
val extensionReceiverParameter: String?
|
||||
) {
|
||||
constructor(function: SimpleFunctionDescriptor) : this(
|
||||
function.name,
|
||||
function.valueParameters.map { it.name to it.type.fqNameWithTypeParameters },
|
||||
function.extensionReceiverParameter?.type?.fqNameWithTypeParameters
|
||||
)
|
||||
}
|
||||
|
||||
/** Used for approximation of [ConstructorDescriptor]s before running concrete [Commonizer]s */
|
||||
internal data class ConstructorApproximationKey(
|
||||
val valueParameters: List<Pair<Name, String>>
|
||||
) {
|
||||
constructor(constructor: ConstructorDescriptor) : this(
|
||||
constructor.valueParameters.map { it.name to it.type.fqNameWithTypeParameters }
|
||||
)
|
||||
}
|
||||
+11
-3
@@ -8,16 +8,24 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroupMap
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ModuleNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.RootNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildModuleNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.toList
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.ChainedMemberScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.utils.alwaysTrue
|
||||
|
||||
internal fun mergeModules(modules: List<ModuleDescriptor?>): ModuleNode {
|
||||
val node = buildModuleNode(modules)
|
||||
internal fun mergeModules(
|
||||
storageManager: StorageManager,
|
||||
cacheRW: RootNode.ClassifiersCacheImpl,
|
||||
moduleName: Name,
|
||||
modules: List<ModuleDescriptor?>
|
||||
): ModuleNode {
|
||||
val node = buildModuleNode(moduleName, modules)
|
||||
|
||||
val packageMemberScopesMap = CommonizedGroupMap<FqName, MemberScope>(modules.size)
|
||||
|
||||
@@ -28,7 +36,7 @@ internal fun mergeModules(modules: List<ModuleDescriptor?>): ModuleNode {
|
||||
}
|
||||
|
||||
for ((packageFqName, packageMemberScopesGroup) in packageMemberScopesMap) {
|
||||
node.packages += mergePackages(packageFqName, packageMemberScopesGroup.toList())
|
||||
node.packages += mergePackages(storageManager, cacheRW, packageFqName, packageMemberScopesGroup.toList())
|
||||
}
|
||||
|
||||
return node
|
||||
|
||||
+27
-53
@@ -5,82 +5,56 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroupMap
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.fqNameWithTypeParameters
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.PackageNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.RootNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildPackageNode
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.PackageNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildPackageNode
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
internal fun mergePackages(
|
||||
storageManager: StorageManager,
|
||||
cacheRW: RootNode.ClassifiersCacheImpl,
|
||||
packageFqName: FqName,
|
||||
packageMemberScopes: List<MemberScope?>
|
||||
): PackageNode {
|
||||
val node = buildPackageNode(packageFqName, packageMemberScopes)
|
||||
|
||||
val propertiesMap = CommonizedGroupMap<PropertyKey, PropertyDescriptor>(packageMemberScopes.size)
|
||||
val functionsMap = CommonizedGroupMap<FunctionKey, SimpleFunctionDescriptor>(packageMemberScopes.size)
|
||||
val propertiesMap = CommonizedGroupMap<PropertyApproximationKey, PropertyDescriptor>(packageMemberScopes.size)
|
||||
val functionsMap = CommonizedGroupMap<FunctionApproximationKey, SimpleFunctionDescriptor>(packageMemberScopes.size)
|
||||
val classesMap = CommonizedGroupMap<Name, ClassDescriptor>(packageMemberScopes.size)
|
||||
val typeAliasesMap = CommonizedGroupMap<Name, TypeAliasDescriptor>(packageMemberScopes.size)
|
||||
|
||||
packageMemberScopes.forEachIndexed { index, memberScope ->
|
||||
memberScope?.collectProperties { propertyKey, property ->
|
||||
propertiesMap[propertyKey][index] = property
|
||||
}
|
||||
memberScope?.collectFunctions { functionKey, function ->
|
||||
functionsMap[functionKey][index] = function
|
||||
}
|
||||
memberScope?.collectMembers(
|
||||
CallableMemberCollector<PropertyDescriptor> { propertiesMap[PropertyApproximationKey(it)][index] = it },
|
||||
CallableMemberCollector<SimpleFunctionDescriptor> { functionsMap[FunctionApproximationKey(it)][index] = it },
|
||||
Collector<ClassDescriptor> { classesMap[it.name][index] = it },
|
||||
Collector<TypeAliasDescriptor> { typeAliasesMap[it.name][index] = it }
|
||||
)
|
||||
}
|
||||
|
||||
for ((_, propertiesGroup) in propertiesMap) {
|
||||
node.properties += mergeProperties(propertiesGroup.toList())
|
||||
node.properties += mergeProperties(storageManager, cacheRW, null, propertiesGroup.toList())
|
||||
}
|
||||
|
||||
for ((_, functionsGroup) in functionsMap) {
|
||||
node.functions += mergeFunctions(functionsGroup.toList())
|
||||
node.functions += mergeFunctions(storageManager, cacheRW, null, functionsGroup.toList())
|
||||
}
|
||||
|
||||
// FIXME: traverse the rest - classes, typealiases
|
||||
for ((_, classesGroup) in classesMap) {
|
||||
node.classes += mergeClasses(storageManager, cacheRW, null, classesGroup.toList())
|
||||
}
|
||||
|
||||
for ((_, typeAliasesGroup) in typeAliasesMap) {
|
||||
node.typeAliases += mergeTypeAliases(storageManager, cacheRW, typeAliasesGroup.toList())
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
internal data class PropertyKey(
|
||||
val name: Name,
|
||||
val extensionReceiverParameter: String?
|
||||
) {
|
||||
constructor(property: PropertyDescriptor) : this(
|
||||
property.name,
|
||||
property.extensionReceiverParameter?.type?.fqNameWithTypeParameters
|
||||
)
|
||||
}
|
||||
|
||||
internal fun MemberScope.collectProperties(collector: (PropertyKey, PropertyDescriptor) -> Unit) {
|
||||
getContributedDescriptors(DescriptorKindFilter.VARIABLES).asSequence()
|
||||
.filterIsInstance<PropertyDescriptor>()
|
||||
.forEach { property ->
|
||||
collector(PropertyKey(property), property)
|
||||
}
|
||||
}
|
||||
|
||||
internal data class FunctionKey(
|
||||
val name: Name,
|
||||
val valueParameters: List<Pair<Name, String>>,
|
||||
val extensionReceiverParameter: String?
|
||||
) {
|
||||
constructor(function: SimpleFunctionDescriptor) : this(
|
||||
function.name,
|
||||
function.valueParameters.map { it.name to it.type.fqNameWithTypeParameters },
|
||||
function.extensionReceiverParameter?.type?.fqNameWithTypeParameters
|
||||
)
|
||||
}
|
||||
|
||||
internal fun MemberScope.collectFunctions(collector: (FunctionKey, SimpleFunctionDescriptor) -> Unit) {
|
||||
getContributedDescriptors(DescriptorKindFilter.FUNCTIONS).asSequence()
|
||||
.filterIsInstance<SimpleFunctionDescriptor>()
|
||||
.forEach { function ->
|
||||
collector(FunctionKey(function), function)
|
||||
}
|
||||
}
|
||||
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildPropertyNode
|
||||
|
||||
internal fun mergeProperties(properties: List<PropertyDescriptor?>) = buildPropertyNode(properties)
|
||||
@@ -11,8 +11,12 @@ import org.jetbrains.kotlin.descriptors.commonizer.ConcreteTargetId
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.RootNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildRootNode
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
|
||||
internal fun mergeRoots(modulesByTargets: List<Pair<ConcreteTargetId, Collection<ModuleDescriptor>>>): RootNode {
|
||||
internal fun mergeRoots(
|
||||
storageManager: StorageManager,
|
||||
modulesByTargets: List<Pair<ConcreteTargetId, Collection<ModuleDescriptor>>>
|
||||
): RootNode {
|
||||
val node = buildRootNode(modulesByTargets.map { it.first })
|
||||
|
||||
val modulesMap = CommonizedGroupMap<Name, ModuleDescriptor>(modulesByTargets.size)
|
||||
@@ -23,8 +27,8 @@ internal fun mergeRoots(modulesByTargets: List<Pair<ConcreteTargetId, Collection
|
||||
}
|
||||
}
|
||||
|
||||
for ((_, modulesGroup) in modulesMap) {
|
||||
node.modules += mergeModules(modulesGroup.toList())
|
||||
for ((moduleName, modulesGroup) in modulesMap) {
|
||||
node.modules += mergeModules(storageManager, node.cache, moduleName, modulesGroup.toList())
|
||||
}
|
||||
|
||||
return node
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
@@ -20,7 +22,7 @@ internal fun <T> Sequence<T>.toList(expectedCapacity: Int): List<T> {
|
||||
internal inline fun <reified T> Iterable<T?>.firstNonNull() = firstIsInstance<T>()
|
||||
|
||||
internal val KotlinType.fqName: FqName
|
||||
get() = constructor.declarationDescriptor!!.fqNameSafe
|
||||
get() = (constructor.declarationDescriptor ?: throw IllegalStateException("No declaration descriptor found for $constructor")).fqNameSafe
|
||||
|
||||
internal val KotlinType.fqNameWithTypeParameters: String
|
||||
get() = buildString { buildFqNameWithTypeParameters(this@fqNameWithTypeParameters) }
|
||||
@@ -48,4 +50,9 @@ private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType) {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Any?.isNull() = this == null
|
||||
internal fun Any?.isNull(): Boolean = this == null
|
||||
|
||||
private val KOTLINX_PACKAGE_NAME = Name.identifier("kotlinx")
|
||||
|
||||
internal val FqName.isUnderStandardKotlinPackages: Boolean
|
||||
get() = startsWith(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME) || startsWith(KOTLINX_PACKAGE_NAME)
|
||||
|
||||
+4
-1
@@ -1,4 +1,7 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
expect class Planet(name: String, diameter: Double) {
|
||||
val name: String
|
||||
val diameter: Double
|
||||
}
|
||||
|
||||
expect val intProperty: Int
|
||||
expect val Int.intProperty: Int
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
actual class Planet actual constructor(actual val name: String, actual val diameter: Double)
|
||||
|
||||
actual val intProperty get() = 42
|
||||
actual val Int.intProperty get() = this
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
actual class Planet actual constructor(actual val name: String, actual val diameter: Double)
|
||||
|
||||
actual val intProperty get() = 42
|
||||
actual val Int.intProperty get() = this
|
||||
|
||||
Vendored
+9
-4
@@ -1,4 +1,7 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
expect class Planet(name: String, diameter: Double) {
|
||||
val name: String
|
||||
val diameter: Double
|
||||
}
|
||||
|
||||
expect val propertyWithInferredType1: Int
|
||||
expect val propertyWithInferredType2: String
|
||||
@@ -6,7 +9,7 @@ expect val propertyWithInferredType3: String
|
||||
expect val propertyWithInferredType4: Nothing?
|
||||
expect val propertyWithInferredType5: Planet
|
||||
|
||||
typealias C = Planet
|
||||
expect class C
|
||||
|
||||
expect val property1: Int
|
||||
expect val property2: String
|
||||
@@ -20,8 +23,10 @@ expect fun function3(): Planet
|
||||
expect fun function6(): Planet
|
||||
expect fun function7(): C
|
||||
|
||||
class Box<T>(val value: T)
|
||||
class Fox
|
||||
expect class Box<T>(value: T) {
|
||||
val value: T
|
||||
}
|
||||
expect class Fox()
|
||||
|
||||
expect fun functionWithTypeParametersInReturnType1(): Array<Int>
|
||||
expect fun functionWithTypeParametersInReturnType3(): Array<String>
|
||||
|
||||
Vendored
+4
-4
@@ -1,4 +1,4 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
actual class Planet actual constructor(actual val name: String, actual val diameter: Double)
|
||||
|
||||
actual val propertyWithInferredType1 = 1
|
||||
actual val propertyWithInferredType2 = "hello"
|
||||
@@ -7,7 +7,7 @@ actual val propertyWithInferredType4 = null
|
||||
actual val propertyWithInferredType5 = Planet("Earth", 12742)
|
||||
|
||||
typealias A = Planet
|
||||
typealias C = Planet
|
||||
actual typealias C = Planet
|
||||
|
||||
actual val property1 = 1
|
||||
actual val property2 = "hello"
|
||||
@@ -37,8 +37,8 @@ fun functionWithMismatchedType3(): Int = 1
|
||||
fun functionWithMismatchedType4(): Int = 1
|
||||
fun functionWithMismatchedType5(): Int = 1
|
||||
|
||||
class Box<T>(val value: T)
|
||||
class Fox
|
||||
actual class Box<T> actual constructor(actual val value: T)
|
||||
actual class Fox actual constructor()
|
||||
|
||||
actual fun functionWithTypeParametersInReturnType1() = arrayOf(1)
|
||||
fun functionWithTypeParametersInReturnType2() = arrayOf(1)
|
||||
|
||||
Vendored
+4
-4
@@ -1,4 +1,4 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
actual class Planet actual constructor(actual val name: String, actual val diameter: Double)
|
||||
|
||||
actual val propertyWithInferredType1 get() = 1
|
||||
actual val propertyWithInferredType2 get() = "hello"
|
||||
@@ -7,7 +7,7 @@ actual val propertyWithInferredType4 get() = null
|
||||
actual val propertyWithInferredType5 get() = Planet("Earth", 12742)
|
||||
|
||||
typealias B = Planet
|
||||
typealias C = Planet
|
||||
actual typealias C = Planet
|
||||
|
||||
actual val property1 = 1
|
||||
actual val property2 = "hello"
|
||||
@@ -37,8 +37,8 @@ fun functionWithMismatchedType3(): Number = 1
|
||||
fun functionWithMismatchedType4(): Comparable<Int> = 1
|
||||
fun functionWithMismatchedType5(): String = 1.toString()
|
||||
|
||||
class Box<T>(val value: T)
|
||||
class Fox
|
||||
actual class Box<T> actual constructor(actual val value: T)
|
||||
actual class Fox actual constructor()
|
||||
|
||||
actual fun functionWithTypeParametersInReturnType1() = arrayOf(1)
|
||||
fun functionWithTypeParametersInReturnType2() = arrayOf("hello")
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
expect suspend fun suspendFunction1(): Int
|
||||
|
||||
class Qux
|
||||
expect class Qux()
|
||||
|
||||
expect operator fun Qux.get(index: Int): String
|
||||
expect fun Qux.set(index: Int, value: String)
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
actual suspend fun suspendFunction1() = 1
|
||||
suspend fun suspendFunction2() = 1
|
||||
|
||||
class Qux
|
||||
actual class Qux actual constructor()
|
||||
|
||||
actual operator fun Qux.get(index: Int) = "$index"
|
||||
actual operator fun Qux.set(index: Int, value: String) = Unit
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
actual suspend fun suspendFunction1() = 1
|
||||
fun suspendFunction2() = 1
|
||||
|
||||
class Qux
|
||||
actual class Qux actual constructor()
|
||||
|
||||
actual operator fun Qux.get(index: Int) = "$index"
|
||||
actual fun Qux.set(index: Int, value: String) = Unit
|
||||
|
||||
@@ -10,8 +10,10 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.getAbbreviation
|
||||
import java.io.File
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
@@ -90,15 +92,29 @@ private class ComparingDeclarationsVisitor(
|
||||
}
|
||||
|
||||
fun visitMemberScopes(expected: MemberScope, actual: MemberScope, context: Context) {
|
||||
fun collectProperties(memberScope: MemberScope): Map<PropertyKey, PropertyDescriptor> =
|
||||
mutableMapOf<PropertyKey, PropertyDescriptor>().also {
|
||||
memberScope.collectProperties { propertyKey, property ->
|
||||
it[propertyKey] = property
|
||||
}
|
||||
}
|
||||
val expectedProperties = mutableMapOf<PropertyApproximationKey, PropertyDescriptor>()
|
||||
val expectedFunctions = mutableMapOf<FunctionApproximationKey, SimpleFunctionDescriptor>()
|
||||
val expectedClasses = mutableMapOf<FqName, ClassDescriptor>()
|
||||
val expectedTypeAliases = mutableMapOf<FqName, TypeAliasDescriptor>()
|
||||
|
||||
val expectedProperties = collectProperties(expected)
|
||||
val actualProperties = collectProperties(actual)
|
||||
expected.collectMembers(
|
||||
CallableMemberCollector<PropertyDescriptor> { expectedProperties[PropertyApproximationKey(it)] = it },
|
||||
CallableMemberCollector<SimpleFunctionDescriptor> { expectedFunctions[FunctionApproximationKey(it)] = it },
|
||||
Collector<ClassDescriptor> { expectedClasses[it.fqNameSafe] = it },
|
||||
Collector<TypeAliasDescriptor> { expectedTypeAliases[it.fqNameSafe] = it }
|
||||
)
|
||||
|
||||
val actualProperties = mutableMapOf<PropertyApproximationKey, PropertyDescriptor>()
|
||||
val actualFunctions = mutableMapOf<FunctionApproximationKey, SimpleFunctionDescriptor>()
|
||||
val actualClasses = mutableMapOf<FqName, ClassDescriptor>()
|
||||
val actualTypeAliases = mutableMapOf<FqName, TypeAliasDescriptor>()
|
||||
|
||||
actual.collectMembers(
|
||||
CallableMemberCollector<PropertyDescriptor> { actualProperties[PropertyApproximationKey(it)] = it },
|
||||
CallableMemberCollector<SimpleFunctionDescriptor> { actualFunctions[FunctionApproximationKey(it)] = it },
|
||||
Collector<ClassDescriptor> { actualClasses[it.fqNameSafe] = it },
|
||||
Collector<TypeAliasDescriptor> { actualTypeAliases[it.fqNameSafe] = it }
|
||||
)
|
||||
|
||||
context.assertSetsEqual(expectedProperties.keys, actualProperties.keys, "sets of properties")
|
||||
|
||||
@@ -107,16 +123,6 @@ private class ComparingDeclarationsVisitor(
|
||||
expectedProperty.accept(this, context.nextLevel(actualProperty))
|
||||
}
|
||||
|
||||
fun collectFunctions(memberScope: MemberScope): Map<FunctionKey, SimpleFunctionDescriptor> =
|
||||
mutableMapOf<FunctionKey, SimpleFunctionDescriptor>().also {
|
||||
memberScope.collectFunctions { functionKey, function ->
|
||||
it[functionKey] = function
|
||||
}
|
||||
}
|
||||
|
||||
val expectedFunctions = collectFunctions(expected)
|
||||
val actualFunctions = collectFunctions(actual)
|
||||
|
||||
context.assertSetsEqual(expectedFunctions.keys, actualFunctions.keys, "sets of functions")
|
||||
|
||||
expectedFunctions.forEach { (functionKey, expectedFunction) ->
|
||||
@@ -124,9 +130,20 @@ private class ComparingDeclarationsVisitor(
|
||||
expectedFunction.accept(this, context.nextLevel(actualFunction))
|
||||
}
|
||||
|
||||
// FIXME: traverse the rest - classes, typealiases
|
||||
}
|
||||
context.assertSetsEqual(expectedClasses.keys, actualClasses.keys, "sets of classes")
|
||||
|
||||
expectedClasses.forEach { (classFqName, expectedClass) ->
|
||||
val actualClass = actualClasses.getValue(classFqName)
|
||||
expectedClass.accept(this, context.nextLevel(actualClass))
|
||||
}
|
||||
|
||||
context.assertSetsEqual(expectedTypeAliases.keys, actualTypeAliases.keys, "sets of type aliases")
|
||||
|
||||
expectedTypeAliases.forEach { (typeAliasFqName, expectedTypeAlias) ->
|
||||
val actualTypeAlias = actualTypeAliases.getValue(typeAliasFqName)
|
||||
expectedTypeAlias.accept(this, context.nextLevel(actualTypeAlias))
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitFunctionDescriptor(expected: FunctionDescriptor, context: Context) {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
@@ -146,6 +163,8 @@ private class ComparingDeclarationsVisitor(
|
||||
context.assertFieldsEqual(expected::isExternal, actual::isExternal)
|
||||
context.assertFieldsEqual(expected::isExpect, actual::isExpect)
|
||||
context.assertFieldsEqual(expected::isActual, actual::isActual)
|
||||
context.assertFieldsEqual(expected::hasStableParameterNames, actual::hasStableParameterNames)
|
||||
context.assertFieldsEqual(expected::hasSynthesizedParameterNames, actual::hasSynthesizedParameterNames)
|
||||
|
||||
visitType(expected.returnType, actual.returnType, context.nextLevel("Function type"))
|
||||
|
||||
@@ -214,15 +233,97 @@ private class ComparingDeclarationsVisitor(
|
||||
}
|
||||
|
||||
override fun visitClassDescriptor(expected: ClassDescriptor, context: Context) {
|
||||
TODO("not implemented")
|
||||
val actual = context.getActualAs<ClassDescriptor>()
|
||||
|
||||
visitAnnotations(expected.annotations, actual.annotations, context.nextLevel("Class annotations"))
|
||||
context.assertFieldsEqual(expected::getName, actual::getName)
|
||||
context.assertFieldsEqual(expected::getVisibility, actual::getVisibility)
|
||||
context.assertFieldsEqual(expected::getModality, actual::getModality)
|
||||
context.assertFieldsEqual(expected::getKind, actual::getKind)
|
||||
context.assertFieldsEqual(expected::isCompanionObject, actual::isCompanionObject)
|
||||
context.assertFieldsEqual(expected::isData, actual::isData)
|
||||
context.assertFieldsEqual(expected::isInline, actual::isInline)
|
||||
context.assertFieldsEqual(expected::isInner, actual::isInner)
|
||||
context.assertFieldsEqual(expected::isExternal, actual::isExternal)
|
||||
context.assertFieldsEqual(expected::isExpect, actual::isExpect)
|
||||
context.assertFieldsEqual(expected::isActual, actual::isActual)
|
||||
|
||||
visitTypeParameters(
|
||||
expected.declaredTypeParameters,
|
||||
actual.declaredTypeParameters,
|
||||
context.nextLevel("Class declared type parameters")
|
||||
)
|
||||
|
||||
if (expected.sealedSubclasses.isNotEmpty() || actual.sealedSubclasses.isNotEmpty()) {
|
||||
val expectedSealedSubclassesFqNames = expected.sealedSubclasses.mapTo(HashSet()) { it.fqNameSafe }
|
||||
val actualSealedSubclassesFqNames = actual.sealedSubclasses.mapTo(HashSet()) { it.fqNameSafe }
|
||||
|
||||
context.assertSetsEqual(expectedSealedSubclassesFqNames, actualSealedSubclassesFqNames, "Sealed subclasses FQ names")
|
||||
}
|
||||
|
||||
val expectedSupertypeFqNames = expected.typeConstructor.supertypes.mapTo(HashSet()) { it.fqNameWithTypeParameters }
|
||||
val actualSupertypeFqNames = actual.typeConstructor.supertypes.mapTo(HashSet()) { it.fqNameWithTypeParameters }
|
||||
|
||||
context.assertSetsEqual(expectedSupertypeFqNames, actualSupertypeFqNames, "Supertypes FQ names")
|
||||
|
||||
if (expected.constructors.isNotEmpty() || actual.constructors.isNotEmpty()) {
|
||||
val expectedConstructors = expected.constructors.associateBy { ConstructorApproximationKey(it) }
|
||||
val actualConstructors = actual.constructors.associateBy { ConstructorApproximationKey(it) }
|
||||
|
||||
context.assertSetsEqual(expectedConstructors.keys, actualConstructors.keys, "sets of class constructors")
|
||||
|
||||
for (key in expectedConstructors.keys) {
|
||||
val expectedConstructor = expectedConstructors.getValue(key)
|
||||
val actualConstructor = actualConstructors.getValue(key)
|
||||
|
||||
visitConstructorDescriptor(expectedConstructor, context.nextLevel(actualConstructor))
|
||||
}
|
||||
}
|
||||
|
||||
visitMemberScopes(
|
||||
expected.unsubstitutedMemberScope,
|
||||
actual.unsubstitutedMemberScope,
|
||||
context.nextLevel("class member scope [${expected.fqNameSafe}]")
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitConstructorDescriptor(expected: ConstructorDescriptor, context: Context) {
|
||||
TODO("not implemented")
|
||||
val actual = context.getActualAs<ConstructorDescriptor>()
|
||||
|
||||
visitAnnotations(expected.annotations, actual.annotations, context.nextLevel("Constructor annotations"))
|
||||
context.assertFieldsEqual(expected::getVisibility, actual::getVisibility)
|
||||
context.assertFieldsEqual(expected::isPrimary, actual::isPrimary)
|
||||
context.assertFieldsEqual(expected::getKind, actual::getKind)
|
||||
context.assertFieldsEqual(expected::hasStableParameterNames, actual::hasStableParameterNames)
|
||||
context.assertFieldsEqual(expected::hasSynthesizedParameterNames, actual::hasSynthesizedParameterNames)
|
||||
context.assertFieldsEqual(expected::isExpect, actual::isExpect)
|
||||
context.assertFieldsEqual(expected::isActual, actual::isActual)
|
||||
|
||||
visitValueParameterDescriptorList(
|
||||
expected.valueParameters,
|
||||
actual.valueParameters,
|
||||
context.nextLevel("Constructor value parameters")
|
||||
)
|
||||
|
||||
visitTypeParameters(expected.typeParameters, actual.typeParameters, context.nextLevel("Constructor type parameters"))
|
||||
}
|
||||
|
||||
override fun visitTypeAliasDescriptor(expected: TypeAliasDescriptor, context: Context) {
|
||||
TODO("not implemented")
|
||||
val actual = context.getActualAs<TypeAliasDescriptor>()
|
||||
|
||||
visitAnnotations(expected.annotations, actual.annotations, context.nextLevel("Type alias annotations"))
|
||||
context.assertFieldsEqual(expected::getName, actual::getName)
|
||||
context.assertFieldsEqual(expected::getVisibility, actual::getVisibility)
|
||||
context.assertFieldsEqual(expected::isActual, actual::isActual)
|
||||
|
||||
visitTypeParameters(
|
||||
expected.declaredTypeParameters,
|
||||
actual.declaredTypeParameters,
|
||||
context.nextLevel("Type alias declared type parameters")
|
||||
)
|
||||
|
||||
visitType(expected.underlyingType, actual.underlyingType, context.nextLevel("Type alias underlying type"))
|
||||
visitType(expected.expandedType, actual.expandedType, context.nextLevel("Type alias expanded type"))
|
||||
}
|
||||
|
||||
override fun visitPropertyDescriptor(expected: PropertyDescriptor, context: Context) {
|
||||
@@ -305,10 +406,10 @@ private class ComparingDeclarationsVisitor(
|
||||
|
||||
|
||||
private fun visitAnnotations(expected: Annotations?, actual: Annotations?, context: Context) {
|
||||
if (expected === actual) return
|
||||
if (expected === actual || (expected?.isEmpty() != false && actual?.isEmpty() != false)) return
|
||||
|
||||
val expectedAnnotationFqNames = (expected ?: Annotations.EMPTY).map { it.fqName }.toSet()
|
||||
val actualAnnotationFqNames = (actual ?: Annotations.EMPTY).map { it.fqName }.toSet()
|
||||
val expectedAnnotationFqNames: Set<FqName?> = expected?.mapTo(HashSet()) { it.fqName } ?: emptySet()
|
||||
val actualAnnotationFqNames: Set<FqName?> = actual?.mapTo(HashSet()) { it.fqName } ?: emptySet()
|
||||
|
||||
context.assertSetsEqual(expectedAnnotationFqNames, actualAnnotationFqNames, "annotations")
|
||||
}
|
||||
@@ -318,8 +419,8 @@ private class ComparingDeclarationsVisitor(
|
||||
|
||||
check(actual != null && expected != null)
|
||||
|
||||
val expectedUnwrapped = expected.unwrap()
|
||||
val actualUnwrapped = actual.unwrap()
|
||||
val expectedUnwrapped = expected.getAbbreviation() ?: expected.unwrap()
|
||||
val actualUnwrapped = actual.getAbbreviation() ?: actual.unwrap()
|
||||
|
||||
if (expectedUnwrapped === actualUnwrapped) return
|
||||
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@ abstract class AbstractCommonizerTest<T, R> {
|
||||
|
||||
protected open fun isEqual(a: R?, b: R?): Boolean = a == b
|
||||
|
||||
protected fun doTestSuccess(expected: R, vararg variants: T) {
|
||||
protected open fun doTestSuccess(expected: R, vararg variants: T) {
|
||||
check(variants.isNotEmpty())
|
||||
|
||||
val commonized = createCommonizer().apply {
|
||||
@@ -34,7 +34,7 @@ abstract class AbstractCommonizerTest<T, R> {
|
||||
}
|
||||
|
||||
// should fail on the last variant
|
||||
protected fun doTestFailure(vararg variants: T) {
|
||||
protected open fun doTestFailure(vararg variants: T) {
|
||||
check(variants.isNotEmpty())
|
||||
|
||||
val commonized = createCommonizer().apply {
|
||||
|
||||
+23
-24
@@ -5,60 +5,59 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.EMPTY_CLASSIFIERS_CACHE
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ExtensionReceiver
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mockClassType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mockProperty
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||
import org.junit.Test
|
||||
|
||||
@TypeRefinement
|
||||
class DefaultExtensionReceiverCommonizerTest : AbstractCommonizerTest<ReceiverParameterDescriptor?, UnwrappedType?>() {
|
||||
class DefaultExtensionReceiverCommonizerTest : AbstractCommonizerTest<ExtensionReceiver?, UnwrappedType?>() {
|
||||
|
||||
@Test
|
||||
fun nullReceiver() = doTestSuccess(
|
||||
null,
|
||||
mock().extensionReceiverParameter,
|
||||
mock().extensionReceiverParameter,
|
||||
mock().extensionReceiverParameter
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
|
||||
@Test
|
||||
fun sameReceiver() = doTestSuccess(
|
||||
mockClassType("kotlin.String").unwrap(),
|
||||
mock(receiverTypeFqName = "kotlin.String").extensionReceiverParameter,
|
||||
mock(receiverTypeFqName = "kotlin.String").extensionReceiverParameter,
|
||||
mock(receiverTypeFqName = "kotlin.String").extensionReceiverParameter
|
||||
mockExtensionReceiver("kotlin.String"),
|
||||
mockExtensionReceiver("kotlin.String"),
|
||||
mockExtensionReceiver("kotlin.String")
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun differentReceivers() = doTestFailure(
|
||||
mock(receiverTypeFqName = "kotlin.String").extensionReceiverParameter,
|
||||
mock(receiverTypeFqName = "kotlin.String").extensionReceiverParameter,
|
||||
mock(receiverTypeFqName = "kotlin.Int").extensionReceiverParameter
|
||||
mockExtensionReceiver("kotlin.String"),
|
||||
mockExtensionReceiver("kotlin.String"),
|
||||
mockExtensionReceiver("kotlin.Int")
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun nullAndNonNullReceivers1() = doTestFailure(
|
||||
mock(receiverTypeFqName = "kotlin.String").extensionReceiverParameter,
|
||||
mock(receiverTypeFqName = "kotlin.String").extensionReceiverParameter,
|
||||
mock(receiverTypeFqName = null).extensionReceiverParameter
|
||||
mockExtensionReceiver("kotlin.String"),
|
||||
mockExtensionReceiver("kotlin.String"),
|
||||
null
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun nullAndNonNullReceivers2() = doTestFailure(
|
||||
mock(receiverTypeFqName = null).extensionReceiverParameter,
|
||||
mock(receiverTypeFqName = null).extensionReceiverParameter,
|
||||
mock(receiverTypeFqName = "kotlin.String").extensionReceiverParameter
|
||||
null,
|
||||
null,
|
||||
mockExtensionReceiver("kotlin.String")
|
||||
)
|
||||
|
||||
override fun createCommonizer() = ExtensionReceiverCommonizer.default()
|
||||
override fun createCommonizer() = ExtensionReceiverCommonizer.default(EMPTY_CLASSIFIERS_CACHE)
|
||||
}
|
||||
|
||||
@TypeRefinement
|
||||
private fun mock(name: String = "myLength", receiverTypeFqName: String? = null) = mockProperty(
|
||||
name = name,
|
||||
setterVisibility = null,
|
||||
extensionReceiverType = receiverTypeFqName?.let { mockClassType(receiverTypeFqName) },
|
||||
returnType = mockClassType("kotlin.Int")
|
||||
private fun mockExtensionReceiver(typeFqName: String) = ExtensionReceiver(
|
||||
annotations = Annotations.EMPTY,
|
||||
type = mockClassType(typeFqName).unwrap()
|
||||
)
|
||||
|
||||
+91
-89
@@ -5,177 +5,179 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.TestFunctionModifiers
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.TestFunctionModifiers.Companion.areEqual
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.core.TestFunctionModifiers.Companion.areEqual
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.FunctionModifiers
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mockClassType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mockFunction
|
||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||
import org.junit.Test
|
||||
|
||||
@TypeRefinement
|
||||
class DefaultFunctionModifiersCommonizerTest : AbstractCommonizerTest<SimpleFunctionDescriptor, FunctionModifiers>() {
|
||||
class DefaultFunctionModifiersCommonizerTest : AbstractCommonizerTest<FunctionModifiers, FunctionModifiers>() {
|
||||
|
||||
@Test
|
||||
fun allDefault() = doTestSuccess(
|
||||
create(),
|
||||
create().toMockFunction(),
|
||||
create().toMockFunction(),
|
||||
create().toMockFunction()
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun allSuspend() = doTestSuccess(
|
||||
create(isSuspend = true),
|
||||
create(isSuspend = true).toMockFunction(),
|
||||
create(isSuspend = true).toMockFunction(),
|
||||
create(isSuspend = true).toMockFunction()
|
||||
mockFunctionModifiers(isSuspend = true),
|
||||
mockFunctionModifiers(isSuspend = true),
|
||||
mockFunctionModifiers(isSuspend = true),
|
||||
mockFunctionModifiers(isSuspend = true)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun suspendAndNotSuspend() = doTestFailure(
|
||||
create(isSuspend = true).toMockFunction(),
|
||||
create(isSuspend = true).toMockFunction(),
|
||||
create().toMockFunction()
|
||||
mockFunctionModifiers(isSuspend = true),
|
||||
mockFunctionModifiers(isSuspend = true),
|
||||
mockFunctionModifiers()
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun notSuspendAndSuspend() = doTestFailure(
|
||||
create().toMockFunction(),
|
||||
create().toMockFunction(),
|
||||
create(isSuspend = true).toMockFunction()
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(isSuspend = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun allOperator() = doTestSuccess(
|
||||
create(isOperator = true),
|
||||
create(isOperator = true).toMockFunction(),
|
||||
create(isOperator = true).toMockFunction(),
|
||||
create(isOperator = true).toMockFunction()
|
||||
mockFunctionModifiers(isOperator = true),
|
||||
mockFunctionModifiers(isOperator = true),
|
||||
mockFunctionModifiers(isOperator = true),
|
||||
mockFunctionModifiers(isOperator = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun notOperatorAndOperator() = doTestSuccess(
|
||||
create(),
|
||||
create().toMockFunction(),
|
||||
create(isOperator = true).toMockFunction(),
|
||||
create(isOperator = true).toMockFunction()
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(isOperator = true),
|
||||
mockFunctionModifiers(isOperator = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun operatorAndNotOperator() = doTestSuccess(
|
||||
create(),
|
||||
create(isOperator = true).toMockFunction(),
|
||||
create(isOperator = true).toMockFunction(),
|
||||
create().toMockFunction()
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(isOperator = true),
|
||||
mockFunctionModifiers(isOperator = true),
|
||||
mockFunctionModifiers()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun allInfix() = doTestSuccess(
|
||||
create(isInfix = true),
|
||||
create(isInfix = true).toMockFunction(),
|
||||
create(isInfix = true).toMockFunction(),
|
||||
create(isInfix = true).toMockFunction()
|
||||
mockFunctionModifiers(isInfix = true),
|
||||
mockFunctionModifiers(isInfix = true),
|
||||
mockFunctionModifiers(isInfix = true),
|
||||
mockFunctionModifiers(isInfix = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun notInfixAndInfix() = doTestSuccess(
|
||||
create(),
|
||||
create().toMockFunction(),
|
||||
create(isInfix = true).toMockFunction(),
|
||||
create(isInfix = true).toMockFunction()
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(isInfix = true),
|
||||
mockFunctionModifiers(isInfix = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun infixAndNotInfix() = doTestSuccess(
|
||||
create(),
|
||||
create(isInfix = true).toMockFunction(),
|
||||
create(isInfix = true).toMockFunction(),
|
||||
create().toMockFunction()
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(isInfix = true),
|
||||
mockFunctionModifiers(isInfix = true),
|
||||
mockFunctionModifiers()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun allInline() = doTestSuccess(
|
||||
create(isInline = true),
|
||||
create(isInline = true).toMockFunction(),
|
||||
create(isInline = true).toMockFunction(),
|
||||
create(isInline = true).toMockFunction()
|
||||
mockFunctionModifiers(isInline = true),
|
||||
mockFunctionModifiers(isInline = true),
|
||||
mockFunctionModifiers(isInline = true),
|
||||
mockFunctionModifiers(isInline = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun notInlineAndInline() = doTestSuccess(
|
||||
create(),
|
||||
create().toMockFunction(),
|
||||
create(isInline = true).toMockFunction(),
|
||||
create(isInline = true).toMockFunction()
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(isInline = true),
|
||||
mockFunctionModifiers(isInline = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun inlineAndNotInline() = doTestSuccess(
|
||||
create(),
|
||||
create(isInline = true).toMockFunction(),
|
||||
create(isInline = true).toMockFunction(),
|
||||
create().toMockFunction()
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(isInline = true),
|
||||
mockFunctionModifiers(isInline = true),
|
||||
mockFunctionModifiers()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun allTailrec() = doTestSuccess(
|
||||
create(isTailrec = true),
|
||||
create(isTailrec = true).toMockFunction(),
|
||||
create(isTailrec = true).toMockFunction(),
|
||||
create(isTailrec = true).toMockFunction()
|
||||
mockFunctionModifiers(isTailrec = true),
|
||||
mockFunctionModifiers(isTailrec = true),
|
||||
mockFunctionModifiers(isTailrec = true),
|
||||
mockFunctionModifiers(isTailrec = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun notTailrecAndTailrec() = doTestSuccess(
|
||||
create(),
|
||||
create().toMockFunction(),
|
||||
create(isTailrec = true).toMockFunction(),
|
||||
create(isTailrec = true).toMockFunction()
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(isTailrec = true),
|
||||
mockFunctionModifiers(isTailrec = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun tailrecAndNotTailrec() = doTestSuccess(
|
||||
create(),
|
||||
create(isTailrec = true).toMockFunction(),
|
||||
create(isTailrec = true).toMockFunction(),
|
||||
create().toMockFunction()
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(isTailrec = true),
|
||||
mockFunctionModifiers(isTailrec = true),
|
||||
mockFunctionModifiers()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun allExternal() = doTestSuccess(
|
||||
create(isExternal = true),
|
||||
create(isExternal = true).toMockFunction(),
|
||||
create(isExternal = true).toMockFunction(),
|
||||
create(isExternal = true).toMockFunction()
|
||||
mockFunctionModifiers(isExternal = true),
|
||||
mockFunctionModifiers(isExternal = true),
|
||||
mockFunctionModifiers(isExternal = true),
|
||||
mockFunctionModifiers(isExternal = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun notExternalAndExternal() = doTestSuccess(
|
||||
create(),
|
||||
create().toMockFunction(),
|
||||
create(isExternal = true).toMockFunction(),
|
||||
create(isExternal = true).toMockFunction()
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(isExternal = true),
|
||||
mockFunctionModifiers(isExternal = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun externalAndNotExternal() = doTestSuccess(
|
||||
create(),
|
||||
create(isExternal = true).toMockFunction(),
|
||||
create(isExternal = true).toMockFunction(),
|
||||
create().toMockFunction()
|
||||
mockFunctionModifiers(),
|
||||
mockFunctionModifiers(isExternal = true),
|
||||
mockFunctionModifiers(isExternal = true),
|
||||
mockFunctionModifiers()
|
||||
)
|
||||
|
||||
override fun createCommonizer() = FunctionModifiersCommonizer.default()
|
||||
override fun isEqual(a: FunctionModifiers?, b: FunctionModifiers?) = (a === b) || (a != null && b != null && areEqual(a, b))
|
||||
}
|
||||
|
||||
private typealias create = TestFunctionModifiers
|
||||
private typealias mockFunctionModifiers = TestFunctionModifiers
|
||||
|
||||
@TypeRefinement
|
||||
private fun TestFunctionModifiers.toMockFunction() = mockFunction(
|
||||
name = "myFunction",
|
||||
returnType = mockClassType("kotlin.String"),
|
||||
modifiers = this
|
||||
)
|
||||
private data class TestFunctionModifiers(
|
||||
override val isOperator: Boolean = false,
|
||||
override val isInfix: Boolean = false,
|
||||
override val isInline: Boolean = false,
|
||||
override val isTailrec: Boolean = false,
|
||||
override val isSuspend: Boolean = false,
|
||||
override val isExternal: Boolean = false
|
||||
) : FunctionModifiers {
|
||||
companion object {
|
||||
fun areEqual(a: FunctionModifiers, b: FunctionModifiers) =
|
||||
a.isOperator == b.isOperator && a.isInfix == b.isInfix && a.isInline == b.isInline
|
||||
&& a.isTailrec == b.isTailrec && a.isSuspend == b.isSuspend && a.isExternal == b.isExternal
|
||||
}
|
||||
}
|
||||
|
||||
+3
-16
@@ -5,16 +5,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.PropertySetterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities.*
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.Setter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mockClassType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mockProperty
|
||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||
import org.junit.Test
|
||||
|
||||
class DefaultPropertySetterCommonizerTest : AbstractCommonizerTest<PropertySetterDescriptor?, Setter?>() {
|
||||
class DefaultPropertySetterCommonizerTest : AbstractCommonizerTest<Setter?, Setter?>() {
|
||||
|
||||
@Test
|
||||
fun absentOnly() = super.doTestSuccess(null, null, null, null)
|
||||
@@ -61,22 +57,13 @@ class DefaultPropertySetterCommonizerTest : AbstractCommonizerTest<PropertySette
|
||||
private fun doTestSuccess(expected: Visibility?, vararg variants: Visibility?) =
|
||||
super.doTestSuccess(
|
||||
expected?.let { Setter.createDefaultNoAnnotations(expected) },
|
||||
*variants.map { it?.let(Visibility::toMockProperty) }.toTypedArray()
|
||||
*variants.map { it?.let(Setter.Companion::createDefaultNoAnnotations) }.toTypedArray()
|
||||
)
|
||||
|
||||
private fun doTestFailure(vararg variants: Visibility?) =
|
||||
super.doTestFailure(
|
||||
*variants.map { it?.let(Visibility::toMockProperty) }.toTypedArray()
|
||||
*variants.map { it?.let(Setter.Companion::createDefaultNoAnnotations) }.toTypedArray()
|
||||
)
|
||||
|
||||
override fun createCommonizer() = PropertySetterCommonizer.default()
|
||||
}
|
||||
|
||||
|
||||
@UseExperimental(TypeRefinement::class)
|
||||
private fun Visibility.toMockProperty() = mockProperty(
|
||||
name = "myProperty",
|
||||
setterVisibility = this,
|
||||
extensionReceiverType = null,
|
||||
returnType = mockClassType("kotlin.String")
|
||||
).setter!!
|
||||
|
||||
+63
-10
@@ -5,17 +5,34 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroupMap
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.RootNode.ClassifiersCacheImpl
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildClassNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.buildTypeAliasNode
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mockClassType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mockTAType
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.getAbbreviation
|
||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
// TODO: add tests for type parameters
|
||||
@TypeRefinement
|
||||
class DefaultTypeCommonizerTest : AbstractCommonizerTest<KotlinType, UnwrappedType>() {
|
||||
|
||||
private lateinit var cache: ClassifiersCacheImpl
|
||||
|
||||
@Before
|
||||
fun initialize() {
|
||||
cache = ClassifiersCacheImpl() // reset cache
|
||||
}
|
||||
|
||||
@Test
|
||||
fun classTypesInKotlinPackageWithSameName() = doTestSuccess(
|
||||
mockClassType("kotlin.collections.List").unwrap(),
|
||||
@@ -84,21 +101,18 @@ class DefaultTypeCommonizerTest : AbstractCommonizerTest<KotlinType, UnwrappedTy
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun classTypesInUserPackageWithDifferentNames1() = doTestFailure(
|
||||
mockClassType("org.sample.Foo"),
|
||||
mockClassType("org.sample.Foo"),
|
||||
mockClassType("org.fictitiousPackageName.Foo")
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun classTypesInUserPackageWithDifferentNames2() = doTestFailure(
|
||||
mockClassType("org.sample.Foo"),
|
||||
mockClassType("org.sample.Foo"),
|
||||
mockClassType("org.sample.Bar")
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun classTypesInUserPackageWithDifferentNames3() = doTestFailure(
|
||||
mockClassType("org.sample.Foo"),
|
||||
mockClassType("org.sample.Foo"),
|
||||
mockClassType("kotlin.String")
|
||||
)
|
||||
@@ -243,14 +257,12 @@ class DefaultTypeCommonizerTest : AbstractCommonizerTest<KotlinType, UnwrappedTy
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun taTypesInUserPackageWithDifferentNames() = doTestFailure(
|
||||
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo") },
|
||||
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo") },
|
||||
mockTAType("org.sample.BarAlias") { mockClassType("org.sample.Foo") }
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun taTypesInUserPackageWithDifferentClasses() = doTestFailure(
|
||||
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo") },
|
||||
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo") },
|
||||
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Bar") }
|
||||
)
|
||||
@@ -346,18 +358,59 @@ class DefaultTypeCommonizerTest : AbstractCommonizerTest<KotlinType, UnwrappedTy
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun taTypesInUserPackageWithDifferentNullability3() = doTestFailure(
|
||||
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = false) },
|
||||
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = false) },
|
||||
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = true) }
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun taTypesInUserPackageWithDifferentNullability4() = doTestFailure(
|
||||
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = true) },
|
||||
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = true) },
|
||||
mockTAType("org.sample.FooAlias") { mockClassType("org.sample.Foo", nullable = false) }
|
||||
)
|
||||
|
||||
override fun createCommonizer() = TypeCommonizer.default()
|
||||
override fun isEqual(a: UnwrappedType?, b: UnwrappedType?) = (a === b) || (a != null && b != null && areTypesEqual(a, b))
|
||||
private fun prepareCache(vararg variants: KotlinType) {
|
||||
check(variants.isNotEmpty())
|
||||
|
||||
val classesMap = CommonizedGroupMap<FqName, ClassDescriptor>(variants.size)
|
||||
val typeAliasesMap = CommonizedGroupMap<FqName, TypeAliasDescriptor>(variants.size)
|
||||
|
||||
fun recurse(type: KotlinType, index: Int) {
|
||||
@Suppress("MoveVariableDeclarationIntoWhen")
|
||||
val descriptor = (type.getAbbreviation() ?: type).constructor.declarationDescriptor
|
||||
when (descriptor) {
|
||||
is ClassDescriptor -> classesMap[descriptor.fqNameSafe][index] = descriptor
|
||||
is TypeAliasDescriptor -> {
|
||||
typeAliasesMap[descriptor.fqNameSafe][index] = descriptor
|
||||
recurse(descriptor.underlyingType, index) // expand underlying types recursively
|
||||
}
|
||||
else -> IllegalStateException("Unexpected descriptor of KotlinType: $descriptor, $type")
|
||||
}
|
||||
}
|
||||
|
||||
variants.forEachIndexed { index, type ->
|
||||
recurse(type, index)
|
||||
}
|
||||
|
||||
for ((_, classesGroup) in classesMap) {
|
||||
buildClassNode(LockBasedStorageManager.NO_LOCKS, cache, null, classesGroup.toList())
|
||||
}
|
||||
|
||||
for ((_, typeAliasesGroup) in typeAliasesMap) {
|
||||
buildTypeAliasNode(LockBasedStorageManager.NO_LOCKS, cache, typeAliasesGroup.toList())
|
||||
}
|
||||
}
|
||||
|
||||
override fun doTestSuccess(expected: UnwrappedType, vararg variants: KotlinType) {
|
||||
prepareCache(*variants)
|
||||
super.doTestSuccess(expected, *variants)
|
||||
}
|
||||
|
||||
override fun doTestFailure(vararg variants: KotlinType) {
|
||||
prepareCache(*variants)
|
||||
super.doTestFailure(*variants)
|
||||
}
|
||||
|
||||
override fun createCommonizer() = TypeCommonizer.default(cache)
|
||||
|
||||
override fun isEqual(a: UnwrappedType?, b: UnwrappedType?) = (a === b) || (a != null && b != null && areTypesEqual(cache, a, b))
|
||||
}
|
||||
|
||||
+33
-44
@@ -5,87 +5,86 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.EMPTY_CLASSIFIERS_CACHE
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CommonTypeParameter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.TypeParameter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mockClassType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mockTypeParameter
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||
import org.junit.Test
|
||||
|
||||
@TypeRefinement
|
||||
class DefaultTypeParameterCommonizerTest : AbstractCommonizerTest<TypeParameterDescriptor, TypeParameter>() {
|
||||
override fun createCommonizer() = TypeParameterCommonizer.default()
|
||||
class DefaultTypeParameterCommonizerTest : AbstractCommonizerTest<TypeParameter, TypeParameter>() {
|
||||
override fun createCommonizer() = TypeParameterCommonizer.default(EMPTY_CLASSIFIERS_CACHE)
|
||||
|
||||
@Test
|
||||
fun allAreReified() = doTestSuccess(
|
||||
create(isReified = true),
|
||||
create(isReified = true).toMockParam(),
|
||||
create(isReified = true).toMockParam(),
|
||||
create(isReified = true).toMockParam()
|
||||
mockTypeParam(isReified = true),
|
||||
mockTypeParam(isReified = true),
|
||||
mockTypeParam(isReified = true),
|
||||
mockTypeParam(isReified = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun allAreNotReified() = doTestSuccess(
|
||||
create(isReified = false),
|
||||
create(isReified = false).toMockParam(),
|
||||
create(isReified = false).toMockParam(),
|
||||
create(isReified = false).toMockParam()
|
||||
mockTypeParam(isReified = false),
|
||||
mockTypeParam(isReified = false),
|
||||
mockTypeParam(isReified = false),
|
||||
mockTypeParam(isReified = false)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun someAreReified1() = doTestFailure(
|
||||
create(isReified = true).toMockParam(),
|
||||
create(isReified = true).toMockParam(),
|
||||
create(isReified = false).toMockParam()
|
||||
mockTypeParam(isReified = true),
|
||||
mockTypeParam(isReified = true),
|
||||
mockTypeParam(isReified = false)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun someAreReified2() = doTestFailure(
|
||||
create(isReified = false).toMockParam(),
|
||||
create(isReified = false).toMockParam(),
|
||||
create(isReified = true).toMockParam()
|
||||
mockTypeParam(isReified = false),
|
||||
mockTypeParam(isReified = false),
|
||||
mockTypeParam(isReified = true)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun differentVariance1() = doTestFailure(
|
||||
create(variance = Variance.IN_VARIANCE).toMockParam(),
|
||||
create(variance = Variance.IN_VARIANCE).toMockParam(),
|
||||
create(variance = Variance.OUT_VARIANCE).toMockParam()
|
||||
mockTypeParam(variance = Variance.IN_VARIANCE),
|
||||
mockTypeParam(variance = Variance.IN_VARIANCE),
|
||||
mockTypeParam(variance = Variance.OUT_VARIANCE)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun differentVariance2() = doTestFailure(
|
||||
create(variance = Variance.OUT_VARIANCE).toMockParam(),
|
||||
create(variance = Variance.OUT_VARIANCE).toMockParam(),
|
||||
create(variance = Variance.INVARIANT).toMockParam()
|
||||
mockTypeParam(variance = Variance.OUT_VARIANCE),
|
||||
mockTypeParam(variance = Variance.OUT_VARIANCE),
|
||||
mockTypeParam(variance = Variance.INVARIANT)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun differentUpperBounds1() = doTestFailure(
|
||||
create(upperBounds = listOf("kotlin.String")).toMockParam(),
|
||||
create(upperBounds = listOf("kotlin.String")).toMockParam(),
|
||||
create(upperBounds = listOf("kotlin.Int")).toMockParam()
|
||||
mockTypeParam(upperBounds = listOf("kotlin.String")),
|
||||
mockTypeParam(upperBounds = listOf("kotlin.String")),
|
||||
mockTypeParam(upperBounds = listOf("kotlin.Int"))
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun differentUpperBounds2() = doTestFailure(
|
||||
create(upperBounds = listOf("kotlin.String", "kotlin.Int")).toMockParam(),
|
||||
create(upperBounds = listOf("kotlin.String", "kotlin.Int")).toMockParam(),
|
||||
create(upperBounds = listOf("kotlin.String")).toMockParam()
|
||||
mockTypeParam(upperBounds = listOf("kotlin.String", "kotlin.Int")),
|
||||
mockTypeParam(upperBounds = listOf("kotlin.String", "kotlin.Int")),
|
||||
mockTypeParam(upperBounds = listOf("kotlin.String"))
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun differentUpperBounds3() = doTestFailure(
|
||||
create(upperBounds = listOf("kotlin.String", "kotlin.Int")).toMockParam(),
|
||||
create(upperBounds = listOf("kotlin.String", "kotlin.Int")).toMockParam(),
|
||||
create(upperBounds = listOf("kotlin.Int", "kotlin.String")).toMockParam()
|
||||
mockTypeParam(upperBounds = listOf("kotlin.String", "kotlin.Int")),
|
||||
mockTypeParam(upperBounds = listOf("kotlin.String", "kotlin.Int")),
|
||||
mockTypeParam(upperBounds = listOf("kotlin.Int", "kotlin.String"))
|
||||
)
|
||||
|
||||
internal companion object {
|
||||
fun create(
|
||||
fun mockTypeParam(
|
||||
name: String = "T",
|
||||
isReified: Boolean = false,
|
||||
variance: Variance = Variance.INVARIANT,
|
||||
@@ -96,15 +95,5 @@ class DefaultTypeParameterCommonizerTest : AbstractCommonizerTest<TypeParameterD
|
||||
variance = variance,
|
||||
upperBounds = upperBounds.map { mockClassType(it).unwrap() }
|
||||
)
|
||||
|
||||
fun TypeParameter.toMockParam(
|
||||
index: Int = 0
|
||||
): TypeParameterDescriptor = mockTypeParameter(
|
||||
name = name.asString(),
|
||||
index = index,
|
||||
isReified = isReified,
|
||||
variance = variance,
|
||||
upperBounds = upperBounds
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+32
-36
@@ -5,13 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.EMPTY_CLASSIFIERS_CACHE
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.TypeParameter
|
||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||
import org.junit.Test
|
||||
|
||||
@TypeRefinement
|
||||
class DefaultTypeParameterListCommonizerTest : AbstractCommonizerTest<List<TypeParameterDescriptor>, List<TypeParameter>>() {
|
||||
class DefaultTypeParameterListCommonizerTest : AbstractCommonizerTest<List<TypeParameter>, List<TypeParameter>>() {
|
||||
|
||||
@Test
|
||||
fun emptyValueParameters() = doTestSuccess(
|
||||
@@ -23,108 +23,104 @@ class DefaultTypeParameterListCommonizerTest : AbstractCommonizerTest<List<TypeP
|
||||
|
||||
@Test
|
||||
fun matchedParameters() = doTestSuccess(
|
||||
create(
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"R" to "kotlin.CharSequence",
|
||||
"Q" to "org.sample.Foo?"
|
||||
),
|
||||
create(
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"R" to "kotlin.CharSequence",
|
||||
"Q" to "org.sample.Foo?"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"R" to "kotlin.CharSequence",
|
||||
"Q" to "org.sample.Foo?"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"R" to "kotlin.CharSequence",
|
||||
"Q" to "org.sample.Foo?"
|
||||
).toMockParams()
|
||||
)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun mismatchedParameterListSize1() = doTestFailure(
|
||||
create(
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"R" to "kotlin.CharSequence",
|
||||
"Q" to "org.sample.Foo?"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"R" to "kotlin.CharSequence",
|
||||
"Q" to "org.sample.Foo?"
|
||||
).toMockParams(),
|
||||
),
|
||||
emptyList()
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun mismatchedParameterListSize2() = doTestFailure(
|
||||
create(
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"R" to "kotlin.CharSequence",
|
||||
"Q" to "org.sample.Foo?"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"R" to "kotlin.CharSequence",
|
||||
"Q" to "org.sample.Foo?"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"R" to "kotlin.CharSequence"
|
||||
).toMockParams()
|
||||
)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun mismatchedParameterListSize3() = doTestFailure(
|
||||
create(
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"R" to "kotlin.CharSequence",
|
||||
"Q" to "org.sample.Foo?"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"R" to "kotlin.CharSequence",
|
||||
"Q" to "org.sample.Foo?"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"R" to "kotlin.CharSequence",
|
||||
"Q" to "org.sample.Foo?",
|
||||
"V" to "org.sample.Bar"
|
||||
).toMockParams()
|
||||
)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun mismatchedParameterNames() = doTestFailure(
|
||||
create(
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"R" to "kotlin.CharSequence"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockTypeParams(
|
||||
"T" to "kotlin.Any?",
|
||||
"Q" to "kotlin.CharSequence"
|
||||
).toMockParams()
|
||||
)
|
||||
)
|
||||
|
||||
override fun createCommonizer() = TypeParameterListCommonizer.default()
|
||||
override fun createCommonizer() = TypeParameterListCommonizer.default(EMPTY_CLASSIFIERS_CACHE)
|
||||
|
||||
private companion object {
|
||||
fun create(vararg params: Pair<String, String>): List<TypeParameter> {
|
||||
fun mockTypeParams(vararg params: Pair<String, String>): List<TypeParameter> {
|
||||
check(params.isNotEmpty())
|
||||
return params.map { (name, returnTypeFqName) ->
|
||||
DefaultTypeParameterCommonizerTest.create(
|
||||
DefaultTypeParameterCommonizerTest.mockTypeParam(
|
||||
name = name,
|
||||
upperBounds = listOf(returnTypeFqName)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun List<TypeParameter>.toMockParams() = DefaultTypeParameterCommonizerTest.run {
|
||||
mapIndexed { index, param -> param.toMockParam(index) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+105
-80
@@ -5,172 +5,197 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CommonValueParameter
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.EMPTY_CLASSIFIERS_CACHE
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.core.TestValueParameter.Companion.areEqual
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ClassifiersCache
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ValueParameter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mockClassType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mockValueParameter
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||
import org.junit.Test
|
||||
|
||||
@TypeRefinement
|
||||
class DefaultValueParameterCommonizerTest : AbstractCommonizerTest<ValueParameterDescriptor, ValueParameter>() {
|
||||
class DefaultValueParameterCommonizerTest : AbstractCommonizerTest<ValueParameter, ValueParameter>() {
|
||||
|
||||
@Test
|
||||
fun sameReturnType1() = doTestSuccess(
|
||||
create("kotlin.String"),
|
||||
create("kotlin.String").toMockParam(),
|
||||
create("kotlin.String").toMockParam(),
|
||||
create("kotlin.String").toMockParam()
|
||||
mockValueParam("kotlin.String"),
|
||||
mockValueParam("kotlin.String"),
|
||||
mockValueParam("kotlin.String"),
|
||||
mockValueParam("kotlin.String")
|
||||
)
|
||||
|
||||
@Test
|
||||
fun sameReturnType2() = doTestSuccess(
|
||||
create("org.sample.Foo"),
|
||||
create("org.sample.Foo").toMockParam(),
|
||||
create("org.sample.Foo").toMockParam(),
|
||||
create("org.sample.Foo").toMockParam()
|
||||
mockValueParam("org.sample.Foo"),
|
||||
mockValueParam("org.sample.Foo"),
|
||||
mockValueParam("org.sample.Foo"),
|
||||
mockValueParam("org.sample.Foo")
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun differentReturnTypes1() = doTestFailure(
|
||||
create("kotlin.String").toMockParam(),
|
||||
create("kotlin.String").toMockParam(),
|
||||
create("kotlin.Int").toMockParam()
|
||||
mockValueParam("kotlin.String"),
|
||||
mockValueParam("kotlin.String"),
|
||||
mockValueParam("kotlin.Int")
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun differentReturnTypes2() = doTestFailure(
|
||||
create("kotlin.String").toMockParam(),
|
||||
create("kotlin.String").toMockParam(),
|
||||
create("org.sample.Foo").toMockParam()
|
||||
mockValueParam("kotlin.String"),
|
||||
mockValueParam("kotlin.String"),
|
||||
mockValueParam("org.sample.Foo")
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun differentReturnTypes3() = doTestFailure(
|
||||
create("org.sample.Foo").toMockParam(),
|
||||
create("org.sample.Foo").toMockParam(),
|
||||
create("org.sample.Bar").toMockParam()
|
||||
mockValueParam("org.sample.Foo"),
|
||||
mockValueParam("org.sample.Foo"),
|
||||
mockValueParam("org.sample.Bar")
|
||||
)
|
||||
|
||||
@Test
|
||||
fun allHaveVararg1() = doTestSuccess(
|
||||
create("kotlin.String", hasVarargElementType = true),
|
||||
create("kotlin.String", hasVarargElementType = true).toMockParam(),
|
||||
create("kotlin.String", hasVarargElementType = true).toMockParam(),
|
||||
create("kotlin.String", hasVarargElementType = true).toMockParam()
|
||||
mockValueParam("kotlin.String", hasVarargElementType = true),
|
||||
mockValueParam("kotlin.String", hasVarargElementType = true),
|
||||
mockValueParam("kotlin.String", hasVarargElementType = true),
|
||||
mockValueParam("kotlin.String", hasVarargElementType = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun allHaveVararg2() = doTestSuccess(
|
||||
create("org.sample.Foo", hasVarargElementType = true),
|
||||
create("org.sample.Foo", hasVarargElementType = true).toMockParam(),
|
||||
create("org.sample.Foo", hasVarargElementType = true).toMockParam(),
|
||||
create("org.sample.Foo", hasVarargElementType = true).toMockParam()
|
||||
mockValueParam("org.sample.Foo", hasVarargElementType = true),
|
||||
mockValueParam("org.sample.Foo", hasVarargElementType = true),
|
||||
mockValueParam("org.sample.Foo", hasVarargElementType = true),
|
||||
mockValueParam("org.sample.Foo", hasVarargElementType = true)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun someDoesNotHaveVararg1() = doTestFailure(
|
||||
create("kotlin.String", hasVarargElementType = true).toMockParam(),
|
||||
create("kotlin.String", hasVarargElementType = true).toMockParam(),
|
||||
create("kotlin.String", hasVarargElementType = false).toMockParam()
|
||||
mockValueParam("kotlin.String", hasVarargElementType = true),
|
||||
mockValueParam("kotlin.String", hasVarargElementType = true),
|
||||
mockValueParam("kotlin.String", hasVarargElementType = false)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun someDoesNotHaveVararg2() = doTestFailure(
|
||||
create("org.sample.Foo", hasVarargElementType = false).toMockParam(),
|
||||
create("org.sample.Foo", hasVarargElementType = false).toMockParam(),
|
||||
create("org.sample.Foo", hasVarargElementType = true).toMockParam()
|
||||
mockValueParam("org.sample.Foo", hasVarargElementType = false),
|
||||
mockValueParam("org.sample.Foo", hasVarargElementType = false),
|
||||
mockValueParam("org.sample.Foo", hasVarargElementType = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun allHaveCrossinline() = doTestSuccess(
|
||||
create("kotlin.String", isCrossinline = true),
|
||||
create("kotlin.String", isCrossinline = true).toMockParam(),
|
||||
create("kotlin.String", isCrossinline = true).toMockParam(),
|
||||
create("kotlin.String", isCrossinline = true).toMockParam()
|
||||
mockValueParam("kotlin.String", isCrossinline = true),
|
||||
mockValueParam("kotlin.String", isCrossinline = true),
|
||||
mockValueParam("kotlin.String", isCrossinline = true),
|
||||
mockValueParam("kotlin.String", isCrossinline = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun someHaveCrossinline1() = doTestSuccess(
|
||||
create("kotlin.String", isCrossinline = false),
|
||||
create("kotlin.String", isCrossinline = true).toMockParam(),
|
||||
create("kotlin.String", isCrossinline = true).toMockParam(),
|
||||
create("kotlin.String", isCrossinline = false).toMockParam()
|
||||
mockValueParam("kotlin.String", isCrossinline = false),
|
||||
mockValueParam("kotlin.String", isCrossinline = true),
|
||||
mockValueParam("kotlin.String", isCrossinline = true),
|
||||
mockValueParam("kotlin.String", isCrossinline = false)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun someHaveCrossinline2() = doTestSuccess(
|
||||
create("kotlin.String", isCrossinline = false),
|
||||
create("kotlin.String", isCrossinline = false).toMockParam(),
|
||||
create("kotlin.String", isCrossinline = true).toMockParam(),
|
||||
create("kotlin.String", isCrossinline = true).toMockParam()
|
||||
mockValueParam("kotlin.String", isCrossinline = false),
|
||||
mockValueParam("kotlin.String", isCrossinline = false),
|
||||
mockValueParam("kotlin.String", isCrossinline = true),
|
||||
mockValueParam("kotlin.String", isCrossinline = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun allHaveNoinline() = doTestSuccess(
|
||||
create("kotlin.String", isNoinline = true),
|
||||
create("kotlin.String", isNoinline = true).toMockParam(),
|
||||
create("kotlin.String", isNoinline = true).toMockParam(),
|
||||
create("kotlin.String", isNoinline = true).toMockParam()
|
||||
mockValueParam("kotlin.String", isNoinline = true),
|
||||
mockValueParam("kotlin.String", isNoinline = true),
|
||||
mockValueParam("kotlin.String", isNoinline = true),
|
||||
mockValueParam("kotlin.String", isNoinline = true)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun someHaveNoinline1() = doTestSuccess(
|
||||
create("kotlin.String", isNoinline = false),
|
||||
create("kotlin.String", isNoinline = true).toMockParam(),
|
||||
create("kotlin.String", isNoinline = true).toMockParam(),
|
||||
create("kotlin.String", isNoinline = false).toMockParam()
|
||||
mockValueParam("kotlin.String", isNoinline = false),
|
||||
mockValueParam("kotlin.String", isNoinline = true),
|
||||
mockValueParam("kotlin.String", isNoinline = true),
|
||||
mockValueParam("kotlin.String", isNoinline = false)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun someHaveNoinline2() = doTestSuccess(
|
||||
create("kotlin.String", isNoinline = false),
|
||||
create("kotlin.String", isNoinline = false).toMockParam(),
|
||||
create("kotlin.String", isNoinline = true).toMockParam(),
|
||||
create("kotlin.String", isNoinline = true).toMockParam()
|
||||
mockValueParam("kotlin.String", isNoinline = false),
|
||||
mockValueParam("kotlin.String", isNoinline = false),
|
||||
mockValueParam("kotlin.String", isNoinline = true),
|
||||
mockValueParam("kotlin.String", isNoinline = true)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun anyDeclaresDefaultValue() = doTestFailure(
|
||||
create("kotlin.String").toMockParam(declaresDefaultValue = false),
|
||||
create("kotlin.String").toMockParam(declaresDefaultValue = false),
|
||||
create("kotlin.String").toMockParam(declaresDefaultValue = true)
|
||||
mockValueParam("kotlin.String", declaresDefaultValue = false),
|
||||
mockValueParam("kotlin.String", declaresDefaultValue = false),
|
||||
mockValueParam("kotlin.String", declaresDefaultValue = true)
|
||||
)
|
||||
|
||||
override fun createCommonizer() = ValueParameterCommonizer.default()
|
||||
override fun createCommonizer() = ValueParameterCommonizer.default(EMPTY_CLASSIFIERS_CACHE)
|
||||
|
||||
override fun isEqual(a: ValueParameter?, b: ValueParameter?) =
|
||||
(a === b) || (a != null && b != null && areEqual(EMPTY_CLASSIFIERS_CACHE, a, b))
|
||||
|
||||
internal companion object {
|
||||
fun create(
|
||||
fun mockValueParam(
|
||||
returnTypeFqName: String,
|
||||
name: String = "myParameter",
|
||||
hasVarargElementType: Boolean = false,
|
||||
isCrossinline: Boolean = false,
|
||||
isNoinline: Boolean = false
|
||||
isNoinline: Boolean = false,
|
||||
declaresDefaultValue: Boolean = false
|
||||
): ValueParameter {
|
||||
val returnType = mockClassType(returnTypeFqName).unwrap()
|
||||
|
||||
return CommonValueParameter(
|
||||
return TestValueParameter(
|
||||
name = Name.identifier(name),
|
||||
annotations = Annotations.EMPTY,
|
||||
returnType = returnType,
|
||||
varargElementType = returnType.takeIf { hasVarargElementType }, // the vararg type itself does not matter here, only it's presence matters
|
||||
isCrossinline = isCrossinline,
|
||||
isNoinline = isNoinline
|
||||
isNoinline = isNoinline,
|
||||
declaresDefaultValue = declaresDefaultValue
|
||||
)
|
||||
}
|
||||
|
||||
fun ValueParameter.toMockParam(
|
||||
index: Int = 0,
|
||||
declaresDefaultValue: Boolean = false
|
||||
): ValueParameterDescriptor = mockValueParameter(
|
||||
name = name.asString(),
|
||||
index = index,
|
||||
returnType = returnType,
|
||||
varargElementType = varargElementType,
|
||||
declaresDefaultValue = declaresDefaultValue,
|
||||
isCrossinline = isCrossinline,
|
||||
isNoinline = isNoinline
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal data class TestValueParameter(
|
||||
override val name: Name,
|
||||
override val annotations: Annotations,
|
||||
override val returnType: UnwrappedType,
|
||||
override val varargElementType: UnwrappedType?,
|
||||
override val declaresDefaultValue: Boolean,
|
||||
override val isCrossinline: Boolean,
|
||||
override val isNoinline: Boolean
|
||||
) : ValueParameter {
|
||||
companion object {
|
||||
fun areEqual(cache: ClassifiersCache, a: ValueParameter, b: ValueParameter): Boolean {
|
||||
if (a.name != b.name
|
||||
|| !areTypesEqual(cache, a.returnType, b.returnType)
|
||||
|| a.declaresDefaultValue != b.declaresDefaultValue
|
||||
|| a.isCrossinline != b.isCrossinline
|
||||
|| a.isNoinline != b.isNoinline
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
val aVarargElementType = a.varargElementType
|
||||
val bVarargElementType = b.varargElementType
|
||||
|
||||
return (aVarargElementType === bVarargElementType)
|
||||
|| (aVarargElementType != null && bVarargElementType != null
|
||||
&& areTypesEqual(cache, aVarargElementType, bVarargElementType))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+65
-54
@@ -5,13 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.EMPTY_CLASSIFIERS_CACHE
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.core.TestValueParameter.Companion.areEqual
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ValueParameter
|
||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||
import org.junit.Test
|
||||
|
||||
@TypeRefinement
|
||||
class DefaultValueParameterListCommonizerTest : AbstractCommonizerTest<List<ValueParameterDescriptor>, List<ValueParameter>>() {
|
||||
class DefaultValueParameterListCommonizerTest : AbstractCommonizerTest<List<ValueParameter>, List<ValueParameter>>() {
|
||||
|
||||
@Test
|
||||
fun emptyValueParameters() = doTestSuccess(
|
||||
@@ -23,163 +24,173 @@ class DefaultValueParameterListCommonizerTest : AbstractCommonizerTest<List<Valu
|
||||
|
||||
@Test
|
||||
fun matchedParameters() = doTestSuccess(
|
||||
create(
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
),
|
||||
create(
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams()
|
||||
)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun mismatchedParameterListSize1() = doTestFailure(
|
||||
create(
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
),
|
||||
emptyList()
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun mismatchedParameterListSize2() = doTestFailure(
|
||||
create(
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int"
|
||||
).toMockParams()
|
||||
)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun mismatchedParameterListSize3() = doTestFailure(
|
||||
create(
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo",
|
||||
"d" to "org.sample.Bar"
|
||||
).toMockParams()
|
||||
)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun mismatchedParameterNames1() = doTestFailure(
|
||||
create(
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a1" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams()
|
||||
)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun mismatchedParameterNames2() = doTestFailure(
|
||||
create(
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c1" to "org.sample.Foo"
|
||||
).toMockParams()
|
||||
)
|
||||
)
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun mismatchedParameterTypes() = doTestFailure(
|
||||
create(
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.String",
|
||||
"b" to "kotlin.Int",
|
||||
"c" to "org.sample.Foo"
|
||||
).toMockParams(),
|
||||
create(
|
||||
),
|
||||
mockValueParams(
|
||||
"a" to "kotlin.Int",
|
||||
"b" to "kotlin.String",
|
||||
"c" to "org.sample.Bar"
|
||||
).toMockParams()
|
||||
)
|
||||
)
|
||||
|
||||
override fun createCommonizer() = ValueParameterListCommonizer.default()
|
||||
override fun createCommonizer() = ValueParameterListCommonizer.default(EMPTY_CLASSIFIERS_CACHE)
|
||||
|
||||
override fun isEqual(a: List<ValueParameter>?, b: List<ValueParameter>?): Boolean {
|
||||
if (a === b)
|
||||
return true
|
||||
else if (a == null || b == null || a.size != b.size)
|
||||
return false
|
||||
|
||||
for (i in 0 until a.size) {
|
||||
if (!areEqual(EMPTY_CLASSIFIERS_CACHE, a[i], b[i]))
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private companion object {
|
||||
fun create(vararg params: Pair<String, String>): List<ValueParameter> {
|
||||
fun mockValueParams(vararg params: Pair<String, String>): List<ValueParameter> {
|
||||
check(params.isNotEmpty())
|
||||
return params.map { (name, returnTypeFqName) ->
|
||||
DefaultValueParameterCommonizerTest.create(
|
||||
DefaultValueParameterCommonizerTest.mockValueParam(
|
||||
name = name,
|
||||
returnTypeFqName = returnTypeFqName
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun List<ValueParameter>.toMockParams() = DefaultValueParameterCommonizerTest.run {
|
||||
mapIndexed { index, param -> param.toMockParam(index) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-10
@@ -7,36 +7,41 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities.*
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.DeclarationWithVisibility
|
||||
import org.junit.Test
|
||||
|
||||
class EqualizingVisibilityCommonizerTest : AbstractCommonizerTest<Visibility, Visibility>() {
|
||||
class EqualizingVisibilityCommonizerTest : AbstractCommonizerTest<DeclarationWithVisibility, Visibility>() {
|
||||
|
||||
@Test
|
||||
fun publicOnly() = doTestSuccess(PUBLIC, PUBLIC, PUBLIC, PUBLIC)
|
||||
fun publicOnly() = doTestSuccess(PUBLIC, PUBLIC.toMock(), PUBLIC.toMock(), PUBLIC.toMock())
|
||||
|
||||
@Test
|
||||
fun protectedOnly() = doTestSuccess(PROTECTED, PROTECTED, PROTECTED, PROTECTED)
|
||||
fun protectedOnly() = doTestSuccess(PROTECTED, PROTECTED.toMock(), PROTECTED.toMock(), PROTECTED.toMock())
|
||||
|
||||
@Test
|
||||
fun internalOnly() = doTestSuccess(INTERNAL, INTERNAL, INTERNAL, INTERNAL)
|
||||
fun internalOnly() = doTestSuccess(INTERNAL, INTERNAL.toMock(), INTERNAL.toMock(), INTERNAL.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun privateOnly() = doTestFailure(PRIVATE)
|
||||
fun privateOnly() = doTestFailure(PRIVATE.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun publicAndProtected() = doTestFailure(PROTECTED, PROTECTED, PROTECTED, PUBLIC)
|
||||
fun publicAndProtected() = doTestFailure(PROTECTED.toMock(), PROTECTED.toMock(), PUBLIC.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun publicAndInternal() = doTestFailure(INTERNAL, INTERNAL, INTERNAL, PUBLIC)
|
||||
fun publicAndInternal() = doTestFailure(INTERNAL.toMock(), INTERNAL.toMock(), PUBLIC.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun protectedAndInternal() = doTestFailure(PROTECTED, PROTECTED, PROTECTED, INTERNAL)
|
||||
fun protectedAndInternal() = doTestFailure(PROTECTED.toMock(), PROTECTED.toMock(), INTERNAL.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun publicAndPrivate() = doTestFailure(PUBLIC, PUBLIC, PRIVATE)
|
||||
fun publicAndPrivate() = doTestFailure(PUBLIC.toMock(), PUBLIC.toMock(), PRIVATE.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun somethingUnexpected() = doTestFailure(PUBLIC, LOCAL)
|
||||
fun somethingUnexpected() = doTestFailure(PUBLIC.toMock(), LOCAL.toMock())
|
||||
|
||||
override fun createCommonizer() = VisibilityCommonizer.equalizing()
|
||||
}
|
||||
|
||||
private fun Visibility.toMock() = object : DeclarationWithVisibility {
|
||||
override val visibility: Visibility = this@toMock
|
||||
}
|
||||
|
||||
+75
-17
@@ -5,38 +5,96 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities.*
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.DeclarationWithVisibility
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.MaybeVirtualCallableMember
|
||||
import org.junit.Test
|
||||
|
||||
class LoweringVisibilityCommonizerTest : AbstractCommonizerTest<Visibility, Visibility>() {
|
||||
abstract class LoweringVisibilityCommonizerTest(
|
||||
private val allowPrivate: Boolean,
|
||||
private val areMembersVirtual: Boolean
|
||||
) : AbstractCommonizerTest<DeclarationWithVisibility, Visibility>() {
|
||||
|
||||
@Test
|
||||
fun publicOnly() = doTestSuccess(PUBLIC, PUBLIC, PUBLIC, PUBLIC)
|
||||
fun publicOnly() = doTestSuccess(PUBLIC, PUBLIC.toMock(), PUBLIC.toMock(), PUBLIC.toMock())
|
||||
|
||||
@Test
|
||||
fun protectedOnly() = doTestSuccess(PROTECTED, PROTECTED, PROTECTED, PROTECTED)
|
||||
fun protectedOnly() = doTestSuccess(PROTECTED, PROTECTED.toMock(), PROTECTED.toMock(), PROTECTED.toMock())
|
||||
|
||||
@Test
|
||||
fun internalOnly() = doTestSuccess(INTERNAL, INTERNAL, INTERNAL, INTERNAL)
|
||||
fun internalOnly() = doTestSuccess(INTERNAL, INTERNAL.toMock(), INTERNAL.toMock(), INTERNAL.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun privateOnly() = doTestFailure(PRIVATE)
|
||||
fun somethingUnexpected() = doTestFailure(PUBLIC.toMock(), LOCAL.toMock())
|
||||
|
||||
@Test
|
||||
fun publicAndProtected() = doTestSuccess(PROTECTED, PUBLIC, PROTECTED, PUBLIC)
|
||||
final override fun createCommonizer() = VisibilityCommonizer.lowering(allowPrivate = allowPrivate)
|
||||
|
||||
@Test
|
||||
fun publicAndInternal() = doTestSuccess(INTERNAL, PUBLIC, INTERNAL, PUBLIC)
|
||||
protected fun Visibility.toMock() = object : MaybeVirtualCallableMember {
|
||||
override val visibility: Visibility = this@toMock
|
||||
override val isVirtual: Boolean = !isPrivate(visibility) && areMembersVirtual
|
||||
}
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun protectedAndInternal() = doTestFailure(PUBLIC, INTERNAL, PROTECTED)
|
||||
class PrivateMembers : LoweringVisibilityCommonizerTest(true, false) {
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun publicAndPrivate() = doTestFailure(PUBLIC, INTERNAL, PRIVATE)
|
||||
@Test
|
||||
fun publicAndProtected() = doTestSuccess(PROTECTED, PUBLIC.toMock(), PROTECTED.toMock(), PUBLIC.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun somethingUnexpected() = doTestFailure(PUBLIC, LOCAL)
|
||||
@Test
|
||||
fun publicAndInternal() = doTestSuccess(INTERNAL, PUBLIC.toMock(), INTERNAL.toMock(), PUBLIC.toMock())
|
||||
|
||||
override fun createCommonizer() = VisibilityCommonizer.lowering()
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun publicAndInternalAndProtected() = doTestFailure(PUBLIC.toMock(), INTERNAL.toMock(), PROTECTED.toMock())
|
||||
|
||||
@Test
|
||||
fun publicAndInternalAndPrivate() = doTestSuccess(PRIVATE, PUBLIC.toMock(), INTERNAL.toMock(), PRIVATE.toMock())
|
||||
|
||||
@Test
|
||||
fun privateOnly() = doTestSuccess(PRIVATE, PRIVATE.toMock(), PRIVATE.toMock(), PRIVATE.toMock())
|
||||
}
|
||||
|
||||
class NonVirtualMembers : LoweringVisibilityCommonizerTest(false, false) {
|
||||
|
||||
@Test
|
||||
fun publicAndProtected() = doTestSuccess(PROTECTED, PUBLIC.toMock(), PROTECTED.toMock(), PUBLIC.toMock())
|
||||
|
||||
@Test
|
||||
fun publicAndInternal() = doTestSuccess(INTERNAL, PUBLIC.toMock(), INTERNAL.toMock(), PUBLIC.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun publicAndInternalAndProtected() = doTestFailure(PUBLIC.toMock(), INTERNAL.toMock(), PROTECTED.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun publicAndInternalAndPrivate() = doTestFailure(PUBLIC.toMock(), INTERNAL.toMock(), PRIVATE.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun privateOnly() = doTestFailure(PRIVATE.toMock())
|
||||
}
|
||||
|
||||
class VirtualMembers : LoweringVisibilityCommonizerTest(false, true) {
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun publicAndProtected1() = doTestFailure(PUBLIC.toMock(), PROTECTED.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun publicAndProtected2() = doTestFailure(PUBLIC.toMock(), PUBLIC.toMock(), PROTECTED.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun publicAndInternal1() = doTestFailure(PUBLIC.toMock(), INTERNAL.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun publicAndInternal2() = doTestFailure(PUBLIC.toMock(), PUBLIC.toMock(), INTERNAL.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun protectedAndInternal1() = doTestFailure(PROTECTED.toMock(), INTERNAL.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun protectedAndInternal2() = doTestFailure(PROTECTED.toMock(), PROTECTED.toMock(), INTERNAL.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun publicAndPrivate() = doTestFailure(PUBLIC.toMock(), PRIVATE.toMock())
|
||||
|
||||
@Test(expected = IllegalCommonizerStateException::class)
|
||||
fun privateOnly() = doTestFailure(PRIVATE.toMock())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,12 @@ package org.jetbrains.kotlin.descriptors.commonizer
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.builder.buildDispatchReceiver
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.FunctionModifiers
|
||||
import org.jetbrains.kotlin.descriptors.impl.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.AbstractTypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorBase
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.parentOrNull
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
@@ -105,186 +104,13 @@ internal fun mockTAType(
|
||||
override val constructors: Collection<TypeAliasConstructorDescriptor> = emptyList()
|
||||
override fun substitute(substitutor: TypeSubstitutor) = this
|
||||
override val expandedType by lazy { rightHandSideType }
|
||||
}.apply {
|
||||
initialize(emptyList())
|
||||
}
|
||||
|
||||
(rightHandSideType.getAbbreviatedType()?.expandedType ?: rightHandSideType).withAbbreviation(typeAliasDescriptor.defaultType)
|
||||
}
|
||||
|
||||
internal fun mockProperty(
|
||||
name: String,
|
||||
setterVisibility: Visibility?,
|
||||
extensionReceiverType: KotlinType?,
|
||||
returnType: KotlinType
|
||||
): PropertyDescriptor {
|
||||
val propertyName = Name.identifier(name)
|
||||
|
||||
val propertyDescriptor = PropertyDescriptorImpl.create(
|
||||
/*containingDeclaration =*/ fakeContainingDeclaration(),
|
||||
/*annotations =*/ Annotations.EMPTY,
|
||||
/*modality =*/ Modality.FINAL,
|
||||
/*visibility =*/ Visibilities.PUBLIC,
|
||||
/*isVar =*/ setterVisibility != null,
|
||||
/*name =*/ propertyName,
|
||||
/*kind =*/ CallableMemberDescriptor.Kind.DECLARATION,
|
||||
/*source =*/ SourceElement.NO_SOURCE,
|
||||
/*lateInit =*/ false,
|
||||
/*isConst =*/ false,
|
||||
/*isExpect =*/ false,
|
||||
/*isActual =*/ false,
|
||||
/*isExternal =*/ false,
|
||||
/*isDelegated =*/ false
|
||||
)
|
||||
|
||||
val extensionReceiverDescriptor = DescriptorFactory.createExtensionReceiverParameterForCallable(
|
||||
/*owner =*/ propertyDescriptor,
|
||||
/*receiverParameterType =*/ extensionReceiverType,
|
||||
/*annotations =*/ Annotations.EMPTY
|
||||
)
|
||||
|
||||
val dispatchReceiverDescriptor = buildDispatchReceiver(propertyDescriptor)
|
||||
|
||||
propertyDescriptor.setType(
|
||||
/*outType =*/ returnType,
|
||||
/*typeParameters =*/ emptyList(),
|
||||
/*dispatchReceiverParameter =*/ dispatchReceiverDescriptor,
|
||||
/*extensionReceiverParameter =*/ extensionReceiverDescriptor
|
||||
)
|
||||
|
||||
val getter = DescriptorFactory.createDefaultGetter(
|
||||
/*propertyDescriptor =*/ propertyDescriptor,
|
||||
/*annotations =*/ Annotations.EMPTY
|
||||
).apply {
|
||||
initialize(null) // use return type from the property descriptor
|
||||
}
|
||||
|
||||
val setter = setterVisibility?.let {
|
||||
DescriptorFactory.createSetter(
|
||||
/*propertyDescriptor =*/ propertyDescriptor,
|
||||
/*annotations =*/ Annotations.EMPTY,
|
||||
/*parameterAnnotations =*/ Annotations.EMPTY,
|
||||
/*isDefault =*/ false,
|
||||
/*isExternal =*/ false,
|
||||
/*isInline =*/ false,
|
||||
/*visibility =*/ setterVisibility,
|
||||
/*sourceElement =*/ SourceElement.NO_SOURCE
|
||||
)
|
||||
}
|
||||
|
||||
propertyDescriptor.initialize(getter, setter)
|
||||
|
||||
return propertyDescriptor
|
||||
}
|
||||
|
||||
internal data class TestFunctionModifiers(
|
||||
override val isOperator: Boolean = false,
|
||||
override val isInfix: Boolean = false,
|
||||
override val isInline: Boolean = false,
|
||||
override val isTailrec: Boolean = false,
|
||||
override val isSuspend: Boolean = false,
|
||||
override val isExternal: Boolean = false
|
||||
) : FunctionModifiers {
|
||||
companion object {
|
||||
fun areEqual(a: FunctionModifiers, b: FunctionModifiers) =
|
||||
a.isOperator == b.isOperator && a.isInfix == b.isInfix && a.isInline == b.isInline
|
||||
&& a.isTailrec == b.isTailrec && a.isSuspend == b.isSuspend && a.isExternal == b.isExternal
|
||||
}
|
||||
}
|
||||
|
||||
internal fun mockFunction(
|
||||
name: String,
|
||||
returnType: KotlinType,
|
||||
modifiers: FunctionModifiers
|
||||
): SimpleFunctionDescriptor {
|
||||
val functionName = Name.identifier(name)
|
||||
|
||||
val functionDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
/*containingDeclaration =*/ fakeContainingDeclaration(),
|
||||
/*annotations =*/ Annotations.EMPTY,
|
||||
/*name =*/ functionName,
|
||||
/*kind =*/ CallableMemberDescriptor.Kind.DECLARATION,
|
||||
/*source =*/ SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
functionDescriptor.isOperator = modifiers.isOperator
|
||||
functionDescriptor.isInfix = modifiers.isInfix
|
||||
functionDescriptor.isInline = modifiers.isInline
|
||||
functionDescriptor.isTailrec = modifiers.isTailrec
|
||||
functionDescriptor.isSuspend = modifiers.isSuspend
|
||||
functionDescriptor.isExternal = modifiers.isExternal
|
||||
|
||||
val dispatchReceiverDescriptor = buildDispatchReceiver(functionDescriptor)
|
||||
|
||||
functionDescriptor.initialize(
|
||||
/*extensionReceiverParameter =*/ null,
|
||||
/*dispatchReceiverDescriptor =*/ dispatchReceiverDescriptor,
|
||||
/*typeParameters =*/ emptyList(),
|
||||
/*unsubstitutedValueParameters =*/ emptyList(),
|
||||
/*returnType =*/ returnType,
|
||||
/*modality =*/ Modality.FINAL,
|
||||
/*visibility =*/ Visibilities.PUBLIC
|
||||
)
|
||||
|
||||
return functionDescriptor
|
||||
}
|
||||
|
||||
internal fun mockValueParameter(
|
||||
containingDeclaration: CallableDescriptor? = null,
|
||||
name: String,
|
||||
index: Int,
|
||||
returnType: KotlinType,
|
||||
varargElementType: KotlinType?,
|
||||
declaresDefaultValue: Boolean,
|
||||
isCrossinline: Boolean,
|
||||
isNoinline: Boolean
|
||||
): ValueParameterDescriptor {
|
||||
check(index >= 0)
|
||||
|
||||
val effectiveContainingDeclaration = containingDeclaration
|
||||
?: /* use fake function if no real containing declaration specified */ mockFunction(
|
||||
"fakeFunction",
|
||||
returnType,
|
||||
TestFunctionModifiers()
|
||||
)
|
||||
|
||||
return ValueParameterDescriptorImpl(
|
||||
containingDeclaration = effectiveContainingDeclaration,
|
||||
original = null,
|
||||
index = index,
|
||||
annotations = Annotations.EMPTY,
|
||||
name = Name.identifier(name),
|
||||
outType = returnType,
|
||||
declaresDefaultValue = declaresDefaultValue,
|
||||
isCrossinline = isCrossinline,
|
||||
isNoinline = isNoinline,
|
||||
varargElementType = varargElementType,
|
||||
source = SourceElement.NO_SOURCE
|
||||
)
|
||||
}
|
||||
|
||||
internal fun mockTypeParameter(
|
||||
containingDeclaration: CallableDescriptor? = null,
|
||||
name: String,
|
||||
index: Int,
|
||||
isReified: Boolean,
|
||||
variance: Variance,
|
||||
upperBounds: List<KotlinType>
|
||||
): TypeParameterDescriptor {
|
||||
check(index >= 0)
|
||||
|
||||
return TypeParameterDescriptorImpl.createForFurtherModification(
|
||||
containingDeclaration ?: fakeContainingDeclaration(),
|
||||
Annotations.EMPTY,
|
||||
isReified,
|
||||
variance,
|
||||
Name.identifier(name),
|
||||
index,
|
||||
SourceElement.NO_SOURCE
|
||||
).apply {
|
||||
upperBounds.forEach(this::addUpperBound)
|
||||
setInitialized()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createPackageFragmentForClassifier(classifierFqName: FqName): PackageFragmentDescriptor =
|
||||
object : PackageFragmentDescriptor {
|
||||
private val module: ModuleDescriptor by lazy { mockEmptyModule("<module4_${classifierFqName.shortName()}_x${Random.nextInt()}>") }
|
||||
@@ -310,8 +136,7 @@ private fun createSimpleType(typeConstructor: TypeConstructor, nullable: Boolean
|
||||
refinedTypeFactory = { null }
|
||||
)
|
||||
|
||||
private fun fakeContainingDeclaration() =
|
||||
object : DeclarationDescriptorImpl(Annotations.EMPTY, Name.special("<fake containing declaration>")) {
|
||||
override fun getContainingDeclaration() = error("not supported")
|
||||
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>?, data: D) = error("not supported")
|
||||
}
|
||||
internal val EMPTY_CLASSIFIERS_CACHE = object : ClassifiersCache {
|
||||
override val classes: Map<FqName, ClassNode> get() = emptyMap()
|
||||
override val typeAliases: Map<FqName, TypeAliasNode> get() = emptyMap()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user