[Commonizer] Property descriptor tests
This commit is contained in:
+2
-2
@@ -62,8 +62,8 @@ private fun Property.buildDescriptor(
|
||||
|
||||
val extensionReceiverDescriptor = DescriptorFactory.createExtensionReceiverParameterForCallable(
|
||||
propertyDescriptor,
|
||||
extensionReceiverType,
|
||||
Annotations.EMPTY
|
||||
extensionReceiver?.type,
|
||||
extensionReceiver?.annotations ?: Annotations.EMPTY
|
||||
)
|
||||
|
||||
val dispatchReceiverDescriptor = DescriptorUtils.getDispatchReceiverParameterIfNeeded(containingDeclaration)
|
||||
|
||||
+2
-1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ir.CommonProperty
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ir.ExtensionReceiver
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ir.Property
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@@ -36,7 +37,7 @@ class PropertyCommonizer : Commonizer<PropertyDescriptor, Property> {
|
||||
modality = modality.result,
|
||||
type = returnType.result,
|
||||
setter = setter.result,
|
||||
extensionReceiverType = extensionReceiver.result
|
||||
extensionReceiver = extensionReceiver.result?.let { ExtensionReceiver.createNoAnnotations(it) }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ private class DefaultPropertySetterCommonizer : PropertySetterCommonizer {
|
||||
state = when (state) {
|
||||
State.ERROR -> State.ERROR
|
||||
State.EMPTY -> next?.let {
|
||||
setterVisibility = VisibilityCommonizer.lowering()
|
||||
setterVisibility = VisibilityCommonizer.equalizing()
|
||||
doCommonizeWith(next)
|
||||
} ?: State.WITHOUT_SETTER
|
||||
State.WITH_SETTER -> next?.let(::doCommonizeWith) ?: State.ERROR
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
|
||||
data class ExtensionReceiver(
|
||||
val annotations: Annotations,
|
||||
val type: UnwrappedType
|
||||
) {
|
||||
companion object {
|
||||
fun createNoAnnotations(type: UnwrappedType) = ExtensionReceiver(Annotations.EMPTY, type)
|
||||
|
||||
fun ReceiverParameterDescriptor.toReceiver() = ExtensionReceiver(annotations, type.unwrap())
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ir.Getter.Companion.toGetter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ir.Setter.Companion.toSetter
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.ir.ExtensionReceiver.Companion.toReceiver
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
|
||||
interface Property : Declaration {
|
||||
@@ -27,7 +28,7 @@ interface Property : Declaration {
|
||||
val isDelegate: Boolean
|
||||
val getter: Getter?
|
||||
val setter: Setter?
|
||||
val extensionReceiverType: UnwrappedType?
|
||||
val extensionReceiver: ExtensionReceiver?
|
||||
val backingFieldAnnotations: Annotations? // null assumes no backing field
|
||||
val delegateFieldAnnotations: Annotations? // null assumes no backing field
|
||||
val compileTimeInitializer: ConstantValue<*>?
|
||||
@@ -39,7 +40,7 @@ data class CommonProperty(
|
||||
override val modality: Modality,
|
||||
override val type: UnwrappedType,
|
||||
override val setter: Setter?,
|
||||
override val extensionReceiverType: UnwrappedType?
|
||||
override val extensionReceiver: ExtensionReceiver?
|
||||
) : Property {
|
||||
override val annotations get() = Annotations.EMPTY
|
||||
override val isVar: Boolean get() = setter != null
|
||||
@@ -69,7 +70,7 @@ data class TargetProperty(private val descriptor: PropertyDescriptor) : Property
|
||||
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 extensionReceiverType: UnwrappedType? get() = descriptor.extensionReceiverParameter?.type?.unwrap()
|
||||
override val extensionReceiver: ExtensionReceiver? get() = descriptor.extensionReceiverParameter?.toReceiver()
|
||||
override val backingFieldAnnotations: Annotations? get() = descriptor.backingField?.annotations
|
||||
override val delegateFieldAnnotations: Annotations? get() = descriptor.delegateField?.annotations
|
||||
override val compileTimeInitializer: ConstantValue<*>? get() = descriptor.compileTimeInitializer
|
||||
@@ -112,7 +113,7 @@ data class Setter(
|
||||
Annotations.EMPTY,
|
||||
Annotations.EMPTY,
|
||||
visibility,
|
||||
isDefault = true,
|
||||
isDefault = visibility == Visibilities.PUBLIC,
|
||||
isExternal = false,
|
||||
isInline = false
|
||||
)
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ internal fun mergeModules(modules: List<ModuleDescriptor?>): ModuleNode {
|
||||
}
|
||||
|
||||
// collects member scopes for every non-empty package provided by this module
|
||||
private fun ModuleDescriptor.collectNonEmptyPackageMemberScopes(collector: (FqName, MemberScope) -> Unit) {
|
||||
internal fun ModuleDescriptor.collectNonEmptyPackageMemberScopes(collector: (FqName, MemberScope) -> Unit) {
|
||||
// we don's need to process fragments from other modules which are the dependencies of this module, so
|
||||
// let's use the appropriate package fragment provider
|
||||
val packageFragmentProvider = (this as ModuleDescriptorImpl).packageFragmentProviderForModuleContentWithoutDependencies
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ internal fun mergePackages(
|
||||
return node
|
||||
}
|
||||
|
||||
private fun MemberScope.collectProperties(collector: (PropertyKey, PropertyDescriptor) -> Unit) {
|
||||
internal fun MemberScope.collectProperties(collector: (PropertyKey, PropertyDescriptor) -> Unit) {
|
||||
getContributedDescriptors(DescriptorKindFilter.VARIABLES).asSequence()
|
||||
.filterIsInstance<PropertyDescriptor>()
|
||||
.forEach { property ->
|
||||
@@ -46,7 +46,7 @@ private fun MemberScope.collectProperties(collector: (PropertyKey, PropertyDescr
|
||||
}
|
||||
}
|
||||
|
||||
private data class PropertyKey(
|
||||
internal data class PropertyKey(
|
||||
val name: Name,
|
||||
val extensionReceiverParameterFqName: FqName?
|
||||
) {
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer
|
||||
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.isCommon
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||
|
||||
internal fun <T> Sequence<T>.toList(expectedCapacity: Int): List<T> {
|
||||
@@ -16,6 +14,3 @@ internal fun <T> Sequence<T>.toList(expectedCapacity: Int): List<T> {
|
||||
}
|
||||
|
||||
internal inline fun <reified T> Iterable<T?>.firstNonNull() = firstIsInstance<T>()
|
||||
|
||||
internal fun List<TargetPlatform>.asCommonPlatform() =
|
||||
TargetPlatform(flatMap(TargetPlatform::componentPlatforms).toSet()).also { check(it.isCommon()) }
|
||||
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
expect var propertyWithoutBackingField: Double
|
||||
|
||||
expect val propertyWithBackingField: Double
|
||||
|
||||
expect val propertyWithDelegateField: Int
|
||||
|
||||
expect val String.propertyWithExtensionReceiver: Int
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import kotlin.annotation.AnnotationTarget.*
|
||||
|
||||
@Target(PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER, FIELD, VALUE_PARAMETER)
|
||||
@Repeatable
|
||||
annotation class Foo(val text: String)
|
||||
|
||||
@property:Foo("property")
|
||||
@get:Foo("getter")
|
||||
@set:Foo("setter")
|
||||
@setparam:Foo("parameter")
|
||||
actual var propertyWithoutBackingField
|
||||
get() = 3.14
|
||||
set(value) = Unit
|
||||
|
||||
@field:Foo("field")
|
||||
actual val propertyWithBackingField = 3.14
|
||||
|
||||
@delegate:Foo("field")
|
||||
actual val propertyWithDelegateField: Int by lazy { 42 }
|
||||
|
||||
actual val @receiver:Foo("receiver") String.propertyWithExtensionReceiver: Int
|
||||
get() = length
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import kotlin.annotation.AnnotationTarget.*
|
||||
|
||||
@Target(PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER, FIELD, VALUE_PARAMETER)
|
||||
@Repeatable
|
||||
annotation class Bar(val text: String)
|
||||
|
||||
@Bar("property")
|
||||
actual var propertyWithoutBackingField
|
||||
@Bar("getter") get() = 3.14
|
||||
@Bar("setter") set(@Bar("parameter") value) = Unit
|
||||
|
||||
@field:Bar("field")
|
||||
actual val propertyWithBackingField = 3.14
|
||||
|
||||
@delegate:Bar("field")
|
||||
actual val propertyWithDelegateField: Int by lazy { 42 }
|
||||
|
||||
actual val @receiver:Bar("receiver") String.propertyWithExtensionReceiver: Int
|
||||
get() = length
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import kotlin.annotation.AnnotationTarget.*
|
||||
|
||||
@Target(PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER, FIELD, VALUE_PARAMETER)
|
||||
@Repeatable
|
||||
annotation class Foo(val text: String)
|
||||
|
||||
@Foo("property")
|
||||
var propertyWithoutBackingField
|
||||
@Foo("getter") get() = 3.14
|
||||
@Foo("setter") set(@Foo("parameter") value) = Unit
|
||||
|
||||
@field:Foo("field")
|
||||
val propertyWithBackingField = 3.14
|
||||
|
||||
@delegate:Foo("field")
|
||||
val propertyWithDelegateField: Int by lazy { 42 }
|
||||
|
||||
val @receiver:Foo("receiver") String.propertyWithExtensionReceiver: Int
|
||||
get() = length
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import kotlin.annotation.AnnotationTarget.*
|
||||
|
||||
@Target(PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER, FIELD, VALUE_PARAMETER)
|
||||
@Repeatable
|
||||
annotation class Bar(val text: String)
|
||||
|
||||
@Bar("property")
|
||||
var propertyWithoutBackingField
|
||||
@Bar("getter") get() = 3.14
|
||||
@Bar("setter") set(@Bar("parameter") value) = Unit
|
||||
|
||||
@field:Bar("field")
|
||||
val propertyWithBackingField = 3.14
|
||||
|
||||
@delegate:Bar("field")
|
||||
val propertyWithDelegateField: Int by lazy { 42 }
|
||||
|
||||
val @receiver:Bar("receiver") String.propertyWithExtensionReceiver: Int
|
||||
get() = length
|
||||
konan/commonizer/testData/propertyCommonization/extensionReceivers/commonized/common/package_root.kt
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
|
||||
expect val intProperty: Int
|
||||
expect val Int.intProperty: Int
|
||||
expect val Short.intProperty: Int
|
||||
expect val Long.intProperty: Int
|
||||
expect val String.intProperty: Int
|
||||
expect val Planet.intProperty: Int
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
|
||||
actual val intProperty get() = 42
|
||||
actual val Int.intProperty get() = this
|
||||
actual val Short.intProperty get() = toInt()
|
||||
actual val Long.intProperty get() = toInt()
|
||||
actual val String.intProperty get() = length
|
||||
actual val Planet.intProperty get() = diameter.toInt()
|
||||
|
||||
val String.mismatchedProperty1 get() = 42
|
||||
val mismatchedProperty2 get() = 42
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
|
||||
actual val intProperty get() = 42
|
||||
actual val Int.intProperty get() = this
|
||||
actual val Short.intProperty get() = toInt()
|
||||
actual val Long.intProperty get() = toInt()
|
||||
actual val String.intProperty get() = length
|
||||
actual val Planet.intProperty get() = diameter.toInt()
|
||||
|
||||
val mismatchedProperty1 get() = 42
|
||||
val Double.mismatchedProperty2 get() = 42
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
|
||||
val intProperty get() = 42
|
||||
val Int.intProperty get() = this
|
||||
val Short.intProperty get() = toInt()
|
||||
val Long.intProperty get() = toInt()
|
||||
val String.intProperty get() = length
|
||||
val Planet.intProperty get() = diameter.toInt()
|
||||
|
||||
val String.mismatchedProperty1 get() = 42
|
||||
val mismatchedProperty2 get() = 42
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
|
||||
val intProperty get() = 42
|
||||
val Int.intProperty get() = this
|
||||
val Short.intProperty get() = toInt()
|
||||
val Long.intProperty get() = toInt()
|
||||
val String.intProperty get() = length
|
||||
val Planet.intProperty get() = diameter.toInt()
|
||||
|
||||
val mismatchedProperty1 get() = 42
|
||||
val Double.mismatchedProperty2 get() = 42
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
package org.sample.one
|
||||
|
||||
val firstOrgSampleOne = 1
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
package org.sample.three
|
||||
|
||||
val firstOrgSampleThree = 1
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
package org.sample.two
|
||||
|
||||
val firstOrgSampleTwo = 1
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
// root package
|
||||
|
||||
val firstRoot = 1
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
package org.sample.one
|
||||
|
||||
val secondOrgSampleOne = 1
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
package org.sample.two
|
||||
|
||||
val secondOrgSampleTwo = 1
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
// root package
|
||||
|
||||
val secondRoot = 1
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
package org.sample.three
|
||||
|
||||
val thirdOrgSampleThree = 1
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
package org.sample.two
|
||||
|
||||
val thirdOrgSampleTwo = 1
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
// root package
|
||||
|
||||
val thirdRoot = 1
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample.two
|
||||
|
||||
expect val qux: Int
|
||||
konan/commonizer/testData/propertyCommonization/mismatchedPackages/commonized/common/package_root.kt
Vendored
+1
@@ -0,0 +1 @@
|
||||
expect val foo: Int
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample
|
||||
|
||||
val bar = 1
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample.one
|
||||
|
||||
val baz = 1
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample.two
|
||||
|
||||
actual val qux = 1
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
actual val foo = 1
|
||||
|
||||
val jsSpecificProperty = 42
|
||||
val jsAndJvmSpecificProperty = 42 * 2
|
||||
val jsAndNativeSpecificProperty = 42 * 3
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample
|
||||
|
||||
val bar = 1
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample.two
|
||||
|
||||
actual val qux = 1
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
actual val foo = 1
|
||||
|
||||
val jvmSpecificProperty = 42
|
||||
val jsAndJvmSpecificProperty = 42 * 2
|
||||
val jvmAndNativeSpecificProperty = 42 * 4
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample.one
|
||||
|
||||
val baz = 1
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample.two
|
||||
|
||||
actual val qux = 1
|
||||
konan/commonizer/testData/propertyCommonization/mismatchedPackages/commonized/native/package_root.kt
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
actual val foo = 1
|
||||
|
||||
val nativeSpecificProperty = 42
|
||||
val jsAndNativeSpecificProperty = 42 * 3
|
||||
val jvmAndNativeSpecificProperty = 42 * 4
|
||||
konan/commonizer/testData/propertyCommonization/mismatchedPackages/original/js/package_org_sample.kt
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample
|
||||
|
||||
val bar = 1
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample.one
|
||||
|
||||
val baz = 1
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample.two
|
||||
|
||||
val qux = 1
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
val foo = 1
|
||||
|
||||
val jsSpecificProperty = 42
|
||||
val jsAndJvmSpecificProperty = 42 * 2
|
||||
val jsAndNativeSpecificProperty = 42 * 3
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample
|
||||
|
||||
val bar = 1
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample.two
|
||||
|
||||
val qux = 1
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
val foo = 1
|
||||
|
||||
val jvmSpecificProperty = 42
|
||||
val jsAndJvmSpecificProperty = 42 * 2
|
||||
val jvmAndNativeSpecificProperty = 42 * 4
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample.one
|
||||
|
||||
val baz = 1
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package org.sample.two
|
||||
|
||||
val qux = 1
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
val foo = 1
|
||||
|
||||
val nativeSpecificProperty = 42
|
||||
val jsAndNativeSpecificProperty = 42 * 3
|
||||
val jvmAndNativeSpecificProperty = 42 * 4
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
|
||||
expect val propertyWithInferredType1: Int
|
||||
expect val propertyWithInferredType2: String
|
||||
expect val propertyWithInferredType3: String
|
||||
expect val propertyWithInferredType4: Nothing?
|
||||
expect val propertyWithInferredType5: Planet
|
||||
|
||||
typealias C = Planet
|
||||
|
||||
expect val property1: Int
|
||||
expect val property2: String
|
||||
expect val property3: Planet
|
||||
expect val property6: Planet
|
||||
expect val property7: C
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
|
||||
actual val propertyWithInferredType1 = 1
|
||||
actual val propertyWithInferredType2 = "hello"
|
||||
actual val propertyWithInferredType3 = 42.toString()
|
||||
actual val propertyWithInferredType4 = null
|
||||
actual val propertyWithInferredType5 = Planet("Earth", 12742)
|
||||
|
||||
typealias A = Planet
|
||||
typealias C = Planet
|
||||
|
||||
actual val property1 = 1
|
||||
actual val property2 = "hello"
|
||||
actual val property3 = Planet("Earth", 12742)
|
||||
val property4 = A("Earth", 12742)
|
||||
val property5 = A("Earth", 12742)
|
||||
actual val property6 = Planet("Earth", 12742)
|
||||
actual val property7 = C("Earth", 12742)
|
||||
|
||||
val propertyWithMismatchedType1: Int = 1
|
||||
val propertyWithMismatchedType2: Int = 1
|
||||
val propertyWithMismatchedType3: Int = 1
|
||||
val propertyWithMismatchedType4: Int = 1
|
||||
val propertyWithMismatchedType5: Int = 1
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
|
||||
actual val propertyWithInferredType1 get() = 1
|
||||
actual val propertyWithInferredType2 get() = "hello"
|
||||
actual val propertyWithInferredType3 get() = 42.toString()
|
||||
actual val propertyWithInferredType4 get() = null
|
||||
actual val propertyWithInferredType5 get() = Planet("Earth", 12742)
|
||||
|
||||
typealias B = Planet
|
||||
typealias C = Planet
|
||||
|
||||
actual val property1 = 1
|
||||
actual val property2 = "hello"
|
||||
actual val property3 = Planet("Earth", 12742)
|
||||
val property4: B = Planet("Earth", 12742)
|
||||
val property5: Planet = A("Earth", 12742)
|
||||
actual val property6: Planet = A("Earth", 12742)
|
||||
actual val property7: C = Planet("Earth", 12742)
|
||||
|
||||
val propertyWithMismatchedType1: Long = 1
|
||||
val propertyWithMismatchedType2: Short = 1
|
||||
val propertyWithMismatchedType3: Number = 1
|
||||
val propertyWithMismatchedType4: Comparable<Int> = 1
|
||||
val propertyWithMismatchedType5: String = 1.toString()
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
|
||||
val propertyWithInferredType1 = 1
|
||||
val propertyWithInferredType2 = "hello"
|
||||
val propertyWithInferredType3 = 42.toString()
|
||||
val propertyWithInferredType4 = null
|
||||
val propertyWithInferredType5 = Planet("Earth", 12742)
|
||||
|
||||
typealias A = Planet
|
||||
typealias C = Planet
|
||||
|
||||
val property1 = 1 // with inferred type
|
||||
val property2 = "hello" // with inferred type
|
||||
val property3 = Planet("Earth", 12742) // with inferred type
|
||||
val property4 = A("Earth", 12742) // with inferred type
|
||||
val property5 = A("Earth", 12742) // with inferred type
|
||||
val property6 = Planet("Earth", 12742) // with inferred type
|
||||
val property7 = C("Earth", 12742) // with inferred type
|
||||
|
||||
val propertyWithMismatchedType1: Int = 1
|
||||
val propertyWithMismatchedType2: Int = 1
|
||||
val propertyWithMismatchedType3: Int = 1
|
||||
val propertyWithMismatchedType4: Int = 1
|
||||
val propertyWithMismatchedType5: Int = 1
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
class Planet(val name: String, val diameter: Double)
|
||||
|
||||
val propertyWithInferredType1 get() = 1
|
||||
val propertyWithInferredType2 get() = "hello"
|
||||
val propertyWithInferredType3 get() = 42.toString()
|
||||
val propertyWithInferredType4 get() = null
|
||||
val propertyWithInferredType5 get() = Planet("Earth", 12742)
|
||||
|
||||
typealias B = Planet
|
||||
typealias C = Planet
|
||||
|
||||
val property1: Int = 1 // with explicit type
|
||||
val property2: String = "hello" // with explicit type
|
||||
val property3: Planet = Planet("Earth", 12742) // with explicit type
|
||||
val property4: B = Planet("Earth", 12742) // with explicit type
|
||||
val property5: Planet = A("Earth", 12742) // with explicit type
|
||||
val property6: Planet = A("Earth", 12742) // with explicit type
|
||||
val property7: C = Planet("Earth", 12742) // with explicit type
|
||||
|
||||
val propertyWithMismatchedType1: Long = 1
|
||||
val propertyWithMismatchedType2: Short = 1
|
||||
val propertyWithMismatchedType3: Number = 1
|
||||
val propertyWithMismatchedType4: Comparable<Int> = 1
|
||||
val propertyWithMismatchedType5: String = 1.toString()
|
||||
@@ -1,21 +0,0 @@
|
||||
// root package
|
||||
|
||||
val foo = 1
|
||||
|
||||
val bar = 42
|
||||
val String.bar get() = this
|
||||
val Int.bar get() = this
|
||||
|
||||
var baz = "baz"
|
||||
var bazWithSetter = "baz"
|
||||
set
|
||||
var bazWithCustomSetter = "baz"
|
||||
set(value) {
|
||||
field = value.toLowerCase()
|
||||
}
|
||||
var bazWithSetterWithInternalVisibility = "baz"
|
||||
internal set
|
||||
var bazWithCustomSetterWithInternalVisibility = "baz"
|
||||
internal set(value) {
|
||||
field = value.toLowerCase()
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// root package
|
||||
|
||||
val foo = 1
|
||||
|
||||
val bar = 42
|
||||
val String.bar get() = this
|
||||
val Int.bar get() = this
|
||||
|
||||
var baz = "baz"
|
||||
var bazWithSetter = "baz"
|
||||
set
|
||||
var bazWithCustomSetter = "baz"
|
||||
set(value) {
|
||||
field = value.toLowerCase()
|
||||
}
|
||||
var bazWithSetterWithInternalVisibility = "baz"
|
||||
internal set
|
||||
var bazWithCustomSetterWithInternalVisibility = "baz"
|
||||
internal set(value) {
|
||||
field = value.toLowerCase()
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
expect var defaultSetter1: Int
|
||||
expect var defaultSetter2: Int
|
||||
expect var defaultSetter3: Int
|
||||
|
||||
expect var setterWithoutBackingField1: Int
|
||||
expect var setterWithoutBackingField2: Int
|
||||
|
||||
expect var setterWithDelegation1: Int
|
||||
expect var setterWithDelegation2: Int
|
||||
|
||||
expect var defaultSetteCustomVisibility1: Int
|
||||
expect var defaultSetteCustomVisibility3 = 42
|
||||
internal set
|
||||
|
||||
expect val propertyWithoutSetter: Int
|
||||
expect var propertyWithSetter: Int
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
actual var defaultSetter1 = 42
|
||||
actual var defaultSetter2 = 42
|
||||
set
|
||||
actual var defaultSetter3 = 42
|
||||
set
|
||||
|
||||
actual var setterWithoutBackingField1
|
||||
get() = 42
|
||||
set(value) = Unit
|
||||
actual var setterWithoutBackingField2
|
||||
get() = 42
|
||||
set(value) = Unit
|
||||
|
||||
actual var setterWithDelegation1: Int by mutableMapOf("setterWithDelegation1" to 42)
|
||||
actual var setterWithDelegation2: Int by mutableMapOf("setterWithDelegation2" to 42)
|
||||
|
||||
actual var defaultSetteCustomVisibility1 = 42
|
||||
public set
|
||||
var defaultSetteCustomVisibility2 = 42
|
||||
internal set
|
||||
actual var defaultSetteCustomVisibility3 = 42
|
||||
internal set
|
||||
var defaultSetteCustomVisibility4 = 42
|
||||
private set
|
||||
var defaultSetteCustomVisibility5 = 42
|
||||
private set
|
||||
|
||||
actual val propertyWithoutSetter = 42
|
||||
var propertyMaybeSetter = 42
|
||||
actual var propertyWithSetter = 42
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
actual var defaultSetter1 = 42
|
||||
actual var defaultSetter2 = 42
|
||||
actual var defaultSetter3 = 42
|
||||
set
|
||||
|
||||
actual var setterWithoutBackingField1
|
||||
get() = 42
|
||||
set(value) = Unit
|
||||
actual var setterWithoutBackingField2 = 42
|
||||
|
||||
actual var setterWithDelegation1: Int by mutableMapOf("setterWithDelegation1" to 42)
|
||||
actual var setterWithDelegation2 = 42
|
||||
|
||||
actual var defaultSetteCustomVisibility1 = 42
|
||||
public set
|
||||
var defaultSetteCustomVisibility2 = 42
|
||||
public set
|
||||
actual var defaultSetteCustomVisibility3 = 42
|
||||
internal set
|
||||
var defaultSetteCustomVisibility4 = 42
|
||||
internal set
|
||||
var defaultSetteCustomVisibility5 = 42
|
||||
private set
|
||||
|
||||
actual val propertyWithoutSetter = 42
|
||||
val propertyMaybeSetter = 42
|
||||
actual var propertyWithSetter = 42
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
var defaultSetter1 = 42
|
||||
var defaultSetter2 = 42
|
||||
set
|
||||
var defaultSetter3 = 42
|
||||
set
|
||||
|
||||
var setterWithoutBackingField1
|
||||
get() = 42
|
||||
set(value) = Unit
|
||||
var setterWithoutBackingField2
|
||||
get() = 42
|
||||
set(value) = Unit
|
||||
|
||||
var setterWithDelegation1: Int by mutableMapOf("setterWithDelegation1" to 42)
|
||||
var setterWithDelegation2: Int by mutableMapOf("setterWithDelegation2" to 42)
|
||||
|
||||
var defaultSetteCustomVisibility1 = 42
|
||||
public set
|
||||
var defaultSetteCustomVisibility2 = 42
|
||||
internal set
|
||||
var defaultSetteCustomVisibility3 = 42
|
||||
internal set
|
||||
var defaultSetteCustomVisibility4 = 42
|
||||
private set
|
||||
var defaultSetteCustomVisibility5 = 42
|
||||
private set
|
||||
|
||||
val propertyWithoutSetter = 42
|
||||
var propertyMaybeSetter = 42
|
||||
var propertyWithSetter = 42
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
var defaultSetter1 = 42
|
||||
var defaultSetter2 = 42 // intentionally commented setter declaration
|
||||
// set
|
||||
var defaultSetter3 = 42
|
||||
set
|
||||
|
||||
var setterWithoutBackingField1
|
||||
get() = 42
|
||||
set(value) = Unit
|
||||
var setterWithoutBackingField2 = 42 // intentionally left as with backing field
|
||||
|
||||
var setterWithDelegation1: Int by mutableMapOf("setterWithDelegation1" to 42)
|
||||
var setterWithDelegation2 = 42 // intentionally left without delegation
|
||||
|
||||
var defaultSetteCustomVisibility1 = 42
|
||||
public set
|
||||
var defaultSetteCustomVisibility2 = 42
|
||||
// internal set
|
||||
public set // intentionally used public visibility
|
||||
var defaultSetteCustomVisibility3 = 42
|
||||
internal set
|
||||
var defaultSetteCustomVisibility4 = 42
|
||||
// private set
|
||||
internal set // intentionally used internal visibility
|
||||
var defaultSetteCustomVisibility5 = 42
|
||||
private set
|
||||
|
||||
val propertyWithoutSetter = 42
|
||||
//var propertyMaybeSetter = 42
|
||||
val propertyMaybeSetter = 42 // fixed to be a property without setter
|
||||
var propertyWithSetter = 42
|
||||
konan/commonizer/testData/propertyCommonization/specificProperties/commonized/common/package_root.kt
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
expect val delegatedProperty1: Int
|
||||
expect val delegatedProperty2: Int
|
||||
expect val delegatedProperty3: Int
|
||||
expect val delegatedProperty4: Int
|
||||
|
||||
expect val inlineProperty1: Int
|
||||
expect val inlineProperty2: Int
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
const val constProperty1 = 42
|
||||
const val constProperty2 = 42
|
||||
|
||||
actual val delegatedProperty1: Int by lazy { 42 }
|
||||
actual val delegatedProperty2: Int by lazy { 42 }
|
||||
actual val delegatedProperty3: Int by mapOf("delegatedProperty3" to 42)
|
||||
actual val delegatedProperty4: Int by mapOf("delegatedProperty4" to 42)
|
||||
|
||||
lateinit var lateinitProperty1: String
|
||||
lateinit var lateinitProperty2: String
|
||||
|
||||
actual inline val inlineProperty1 get() = 42
|
||||
actual inline val inlineProperty2 get() = 42
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
const val constProperty1 = 42
|
||||
val constProperty2 = 42 // intentionally left as non-const
|
||||
|
||||
actual val delegatedProperty1: Int by lazy { 42 }
|
||||
actual val delegatedProperty2 = 42 // intentionally left as non-delegated
|
||||
actual val delegatedProperty3: Int by mapOf("delegatedProperty3" to 42)
|
||||
actual val delegatedProperty4 = 42 // intentionally left as non-delegated
|
||||
|
||||
lateinit var lateinitProperty1: String
|
||||
var lateinitProperty2 = "hello" // intentionally left as non-lateinit
|
||||
|
||||
actual inline val inlineProperty1 get() = 42
|
||||
actual val inlineProperty2 = 42 // intentionally left as non-inline
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
const val constProperty1 = 42
|
||||
const val constProperty2 = 42
|
||||
|
||||
val delegatedProperty1: Int by lazy { 42 }
|
||||
val delegatedProperty2: Int by lazy { 42 }
|
||||
val delegatedProperty3: Int by mapOf("delegatedProperty3" to 42)
|
||||
val delegatedProperty4: Int by mapOf("delegatedProperty4" to 42)
|
||||
|
||||
lateinit var lateinitProperty1: String
|
||||
lateinit var lateinitProperty2: String
|
||||
|
||||
inline val inlineProperty1 get() = 42
|
||||
inline val inlineProperty2 get() = 42
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
const val constProperty1 = 42
|
||||
val constProperty2 = 42 // intentionally left as non-const
|
||||
|
||||
val delegatedProperty1: Int by lazy { 42 }
|
||||
val delegatedProperty2 = 42 // intentionally left as non-delegated
|
||||
val delegatedProperty3: Int by mapOf("delegatedProperty3" to 42)
|
||||
val delegatedProperty4 = 42 // intentionally left as non-delegated
|
||||
|
||||
lateinit var lateinitProperty1: String
|
||||
var lateinitProperty2 = "hello" // intentionally left as non-lateinit
|
||||
|
||||
inline val inlineProperty1 get() = 42
|
||||
val inlineProperty2 = 42 // intentionally left as non-inline
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
expect public val publicProperty: Int
|
||||
expect internal val internalProperty: Int
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
actual public val publicProperty = 1
|
||||
actual internal val internalProperty = 1
|
||||
private val privateProperty = 1
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
actual public val publicProperty = 1
|
||||
actual internal val internalProperty = 1
|
||||
private val privateProperty = 1
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
public val publicProperty = 1
|
||||
internal val internalProperty = 1
|
||||
private val privateProperty = 1
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
public val publicProperty = 1
|
||||
internal val internalProperty = 1
|
||||
private val privateProperty = 1
|
||||
+61
-18
@@ -17,7 +17,9 @@ import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils.*
|
||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
||||
import java.io.File
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
|
||||
companion object {
|
||||
@@ -25,17 +27,17 @@ abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
|
||||
System.setProperty("java.awt.headless", "true")
|
||||
}
|
||||
|
||||
fun List<ModuleDescriptor>.eachModuleAsTarget() = CommonizationParameters().also {
|
||||
forEachIndexed { index, module ->
|
||||
it.addTarget("target_$index", listOf(module))
|
||||
fun Collection<ModuleDescriptor>.eachModuleAsTarget() = mapIndexed { index, moduleDescriptor ->
|
||||
"target_$index" to moduleDescriptor
|
||||
}.toMap().toCommonizationParameters()
|
||||
|
||||
fun Map<String, ModuleDescriptor>.toCommonizationParameters() = CommonizationParameters().also {
|
||||
forEach { (targetName, moduleDescriptor) ->
|
||||
it.addTarget(targetName, listOf(moduleDescriptor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun assertIsDirectory(file: File) {
|
||||
assertTrue("Not a directory: $file", file.isDirectory)
|
||||
}
|
||||
|
||||
protected fun createEnvironment(bareModuleName: String): KotlinCoreEnvironment {
|
||||
check(Name.isValidIdentifier(bareModuleName))
|
||||
val configuration = newConfiguration()
|
||||
@@ -65,31 +67,46 @@ abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
|
||||
.also(::assertIsDirectory)
|
||||
}
|
||||
|
||||
protected val sourceModuleRoots: List<File>
|
||||
protected val sourceModuleRoots: Pair<Set<File>, Set<File>>
|
||||
get() {
|
||||
val testDataDir = testDataDir
|
||||
val roots = testDataDir.listFiles()?.toList()
|
||||
|
||||
if (roots.isNullOrEmpty())
|
||||
error("No source module roots found in $testDataDir")
|
||||
val originalRoots = testDataDir
|
||||
.resolve("original")
|
||||
.also(::assertIsDirectory)
|
||||
.listFiles()
|
||||
?.toSet()
|
||||
?.also { it.forEach(::assertIsDirectory) }
|
||||
|
||||
roots.forEach(::assertIsDirectory)
|
||||
val commonizedRoots = testDataDir
|
||||
.resolve("commonized")
|
||||
.also(::assertIsDirectory)
|
||||
.listFiles()
|
||||
?.toSet()
|
||||
?.also { it.forEach(::assertIsDirectory) }
|
||||
|
||||
return roots
|
||||
check(
|
||||
!originalRoots.isNullOrEmpty() && !commonizedRoots.isNullOrEmpty()
|
||||
&& (originalRoots.map { it.name } + "common").toSet() == commonizedRoots.map { it.name }.toSet()
|
||||
) {
|
||||
"Source module misconfiguration in $testDataDir"
|
||||
}
|
||||
|
||||
return originalRoots to commonizedRoots
|
||||
}
|
||||
|
||||
protected val sourceModuleDescriptors: List<ModuleDescriptor>
|
||||
protected val sourceModuleDescriptors: Pair<Map<String, ModuleDescriptor>, Map<String, ModuleDescriptor>>
|
||||
get() {
|
||||
return sourceModuleRoots.map { root ->
|
||||
val environment = createEnvironment(root.parentFile.name)
|
||||
fun analyzeTarget(targetRoot: File): Pair<String, ModuleDescriptor> {
|
||||
val environment = createEnvironment(targetRoot.parentFile.parentFile.name)
|
||||
val psiFactory = KtPsiFactory(environment.project)
|
||||
|
||||
val psiFiles = root.walkTopDown()
|
||||
val psiFiles = targetRoot.walkTopDown()
|
||||
.filter { it.isFile }
|
||||
.map { psiFactory.createFile(it.name, doLoadFile(it)) }
|
||||
.toList()
|
||||
|
||||
CommonResolverForModuleFactory.analyzeFiles(
|
||||
val moduleDescriptor = CommonResolverForModuleFactory.analyzeFiles(
|
||||
files = psiFiles,
|
||||
moduleName = environment.moduleName,
|
||||
dependOnBuiltIns = true,
|
||||
@@ -97,6 +114,32 @@ abstract class AbstractCommonizationFromSourcesTest : KtUsefulTestCase() {
|
||||
) { content ->
|
||||
environment.createPackagePartProvider(content.moduleContentScope)
|
||||
}.moduleDescriptor
|
||||
|
||||
return targetRoot.name to moduleDescriptor
|
||||
}
|
||||
|
||||
return sourceModuleRoots.first.map(::analyzeTarget).toMap() to sourceModuleRoots.second.map(::analyzeTarget).toMap()
|
||||
}
|
||||
|
||||
protected fun doTestSuccessfulCommonization() {
|
||||
val (originalModules, commonizedModules) = sourceModuleDescriptors
|
||||
|
||||
val result = runCommonization(originalModules.toCommonizationParameters())
|
||||
assertCommonizationPerformed(result)
|
||||
|
||||
val commonModuleAsExpected = commonizedModules.getValue("common")
|
||||
val commonModuleByCommonizer = result.commonModules.single()
|
||||
|
||||
assertModulesAreEqual(commonModuleAsExpected, commonModuleByCommonizer, "\"common\" target")
|
||||
|
||||
val concreteTargetNames = commonizedModules.keys - "common"
|
||||
assertEquals(concreteTargetNames, result.modulesByTargets.keys)
|
||||
|
||||
for (targetName in concreteTargetNames) {
|
||||
val targetModuleAsExpected = commonizedModules.getValue(targetName)
|
||||
val targetModuleByCommonizer = result.modulesByTargets.getValue(targetName).single()
|
||||
|
||||
assertModulesAreEqual(targetModuleAsExpected, targetModuleByCommonizer, "\"$targetName\" target")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -9,7 +9,9 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Test
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.AbstractCommonizationFromSourcesTest.Companion.eachModuleAsTarget
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
class BasicCommonizerFacadeTest {
|
||||
|
||||
@Test
|
||||
@@ -41,8 +43,7 @@ class BasicCommonizerFacadeTest {
|
||||
|
||||
val result = runCommonization(modules.eachModuleAsTarget())
|
||||
|
||||
assertTrue(result is CommonizationPerformed)
|
||||
require(result is CommonizationPerformed) // to enforce Kotlin contracts
|
||||
assertCommonizationPerformed(result)
|
||||
|
||||
assertSingleModuleForTarget("<foo>", result.commonModules)
|
||||
|
||||
|
||||
+18
-10
@@ -5,18 +5,26 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer
|
||||
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
class PropertyCommonizationFromSourcesTest : AbstractCommonizationFromSourcesTest() {
|
||||
fun testMatchingPackages() {
|
||||
val modules = sourceModuleDescriptors
|
||||
val result = runCommonization(modules.eachModuleAsTarget())
|
||||
|
||||
println(result)
|
||||
fun testMismatchedPackages() = doTestSuccessfulCommonization()
|
||||
|
||||
// TODO: implement
|
||||
}
|
||||
fun testReturnTypes() = doTestSuccessfulCommonization()
|
||||
|
||||
fun testVisibility() = doTestSuccessfulCommonization()
|
||||
|
||||
fun testSpecificProperties() = doTestSuccessfulCommonization()
|
||||
|
||||
fun testExtensionReceivers() = doTestSuccessfulCommonization()
|
||||
|
||||
fun testSetters() = doTestSuccessfulCommonization()
|
||||
|
||||
fun testAnnotations() = doTestSuccessfulCommonization()
|
||||
|
||||
// TODO: test modality (possible only inside classes)
|
||||
// TODO: test virtual val visibility commonization (possible only inside classes)
|
||||
|
||||
fun testSample() {
|
||||
val modules = sourceModuleDescriptors
|
||||
runCommonization(modules.eachModuleAsTarget())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import junit.framework.TestCase.fail
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.PropertyKey
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.collectNonEmptyPackageMemberScopes
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.collectProperties
|
||||
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 java.io.File
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.reflect.KCallable
|
||||
|
||||
fun assertIsDirectory(file: File) {
|
||||
if (!file.isDirectory)
|
||||
fail("Not a directory: $file")
|
||||
}
|
||||
|
||||
@ExperimentalContracts
|
||||
fun assertCommonizationPerformed(result: CommonizationResult) {
|
||||
contract {
|
||||
returns() implies (result is CommonizationPerformed)
|
||||
}
|
||||
|
||||
if (result !is CommonizationPerformed)
|
||||
fail("$result is not instance of ${CommonizationPerformed::class}")
|
||||
}
|
||||
|
||||
@ExperimentalContracts
|
||||
fun assertModulesAreEqual(expected: ModuleDescriptor, actual: ModuleDescriptor, designatorMessage: String) {
|
||||
val visitor = ComparingDeclarationsVisitor(designatorMessage)
|
||||
val context = visitor.Context(actual)
|
||||
|
||||
expected.accept(visitor, context)
|
||||
}
|
||||
|
||||
@ExperimentalContracts
|
||||
private class ComparingDeclarationsVisitor(
|
||||
val designatorMessage: String
|
||||
) : DeclarationDescriptorVisitor<Unit, ComparingDeclarationsVisitor.Context> {
|
||||
|
||||
inner class Context private constructor(
|
||||
private val actual: DeclarationDescriptor?,
|
||||
private val path: List<String>
|
||||
) {
|
||||
constructor(actual: DeclarationDescriptor?) : this(actual, listOf(actual.toString()))
|
||||
|
||||
fun nextLevel(nextActual: DeclarationDescriptor?) = Context(nextActual, path + nextActual.toString())
|
||||
|
||||
fun nextLevel(customPathElement: String) = Context(actual, path + customPathElement)
|
||||
|
||||
inline fun <reified T> getActualAs() = actual as T
|
||||
|
||||
override fun toString() =
|
||||
"""
|
||||
|Context: ${this@ComparingDeclarationsVisitor.designatorMessage}
|
||||
|Path: ${path.joinToString(separator = " ->\n\t")}"
|
||||
""".trimMargin()
|
||||
}
|
||||
|
||||
override fun visitModuleDeclaration(expected: ModuleDescriptor, context: Context) {
|
||||
val actual = context.getActualAs<ModuleDescriptor>()
|
||||
|
||||
context.assertEquals(expected.name, actual.name, "module names")
|
||||
|
||||
fun collectPackageMemberScopes(module: ModuleDescriptor): Map<FqName, MemberScope> = mutableMapOf<FqName, MemberScope>().also {
|
||||
module.collectNonEmptyPackageMemberScopes { packageFqName, memberScope ->
|
||||
if (memberScope.getContributedDescriptors().isNotEmpty())
|
||||
it[packageFqName] = memberScope
|
||||
}
|
||||
}
|
||||
|
||||
val expectedPackageMemberScopes = collectPackageMemberScopes(expected)
|
||||
val actualPackageMemberScopes = collectPackageMemberScopes(actual)
|
||||
|
||||
context.assertEquals(expectedPackageMemberScopes.keys, actualPackageMemberScopes.keys, "sets of packages")
|
||||
|
||||
for (packageFqName in expectedPackageMemberScopes.keys) {
|
||||
val expectedMemberScope = expectedPackageMemberScopes.getValue(packageFqName)
|
||||
val actualMemberScope = actualPackageMemberScopes.getValue(packageFqName)
|
||||
|
||||
visitMemberScopes(expectedMemberScope, actualMemberScope, context.nextLevel("package member scope [$packageFqName]"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitPackageViewDescriptor(expected: PackageViewDescriptor, context: Context) =
|
||||
fail("Comparison of package views not supported")
|
||||
|
||||
override fun visitPackageFragmentDescriptor(expected: PackageFragmentDescriptor, context: Context) =
|
||||
fail("Comparison of package fragments not supported")
|
||||
|
||||
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 = collectProperties(expected)
|
||||
val actualProperties = collectProperties(actual)
|
||||
|
||||
context.assertEquals(expectedProperties.keys, actualProperties.keys, "sets of properties")
|
||||
|
||||
expectedProperties.forEach { (propertyKey, expectedProperty) ->
|
||||
val actualProperty = actualProperties.getValue(propertyKey)
|
||||
expectedProperty.accept(this, context.nextLevel(actualProperty))
|
||||
}
|
||||
|
||||
// FIXME: traverse the rest - functions, classes, typealiases
|
||||
}
|
||||
|
||||
override fun visitVariableDescriptor(expected: VariableDescriptor, context: Context) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun visitFunctionDescriptor(expected: FunctionDescriptor, context: Context) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun visitTypeParameterDescriptor(expected: TypeParameterDescriptor, context: Context) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun visitClassDescriptor(expected: ClassDescriptor, context: Context) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun visitTypeAliasDescriptor(expected: TypeAliasDescriptor, context: Context) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun visitConstructorDescriptor(expected: ConstructorDescriptor, context: Context) {
|
||||
TODO("not implemented")
|
||||
}
|
||||
|
||||
override fun visitPropertyDescriptor(expected: PropertyDescriptor, context: Context) {
|
||||
val actual = context.getActualAs<PropertyDescriptor>()
|
||||
|
||||
visitAnnotations(expected.annotations, actual.annotations, context.nextLevel("Property annotations"))
|
||||
context.assertFieldsEqual(expected::getName, actual::getName)
|
||||
context.assertFieldsEqual(expected::getVisibility, actual::getVisibility)
|
||||
context.assertFieldsEqual(expected::getModality, actual::getModality)
|
||||
context.assertFieldsEqual(expected::isVar, actual::isVar)
|
||||
context.assertFieldsEqual(expected::getKind, actual::getKind)
|
||||
context.assertFieldsEqual(expected::isLateInit, actual::isLateInit)
|
||||
context.assertFieldsEqual(expected::isConst, actual::isConst)
|
||||
context.assertFieldsEqual(expected::isExternal, actual::isExternal)
|
||||
context.assertFieldsEqual(expected::isExpect, actual::isExpect)
|
||||
context.assertFieldsEqual(expected::isActual, actual::isActual)
|
||||
context.assertFieldsEqual(expected::isDelegated, actual::isDelegated)
|
||||
visitAnnotations(
|
||||
expected.delegateField?.annotations,
|
||||
actual.delegateField?.annotations,
|
||||
context.nextLevel("Property delegate field annotations")
|
||||
)
|
||||
visitAnnotations(
|
||||
expected.backingField?.annotations,
|
||||
actual.backingField?.annotations,
|
||||
context.nextLevel("Property backing field annotations")
|
||||
)
|
||||
context.assertEquals(expected.compileTimeInitializer != null, actual.compileTimeInitializer != null, "compile-time initializers")
|
||||
visitType(expected.type, actual.type, context.nextLevel("Property type"))
|
||||
|
||||
visitPropertyGetterDescriptor(expected.getter, context.nextLevel(actual.getter))
|
||||
visitPropertySetterDescriptor(expected.setter, context.nextLevel(actual.setter))
|
||||
|
||||
visitReceiverParameterDescriptor(expected.extensionReceiverParameter, context.nextLevel(actual.extensionReceiverParameter))
|
||||
visitReceiverParameterDescriptor(expected.dispatchReceiverParameter, context.nextLevel(actual.dispatchReceiverParameter))
|
||||
}
|
||||
|
||||
override fun visitValueParameterDescriptor(expected: ValueParameterDescriptor, context: Context) {
|
||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
override fun visitPropertyGetterDescriptor(expected: PropertyGetterDescriptor?, context: Context) {
|
||||
val actual = context.getActualAs<PropertyGetterDescriptor?>()
|
||||
if (expected === actual) return
|
||||
|
||||
check(actual != null && expected != null)
|
||||
|
||||
visitAnnotations(expected.annotations, actual.annotations, context.nextLevel("Property getter annotations"))
|
||||
context.assertFieldsEqual(expected::isDefault, actual::isDefault)
|
||||
context.assertFieldsEqual(expected::isExternal, actual::isExternal)
|
||||
context.assertFieldsEqual(expected::isInline, actual::isInline)
|
||||
}
|
||||
|
||||
override fun visitPropertySetterDescriptor(expected: PropertySetterDescriptor?, context: Context) {
|
||||
val actual = context.getActualAs<PropertySetterDescriptor?>()
|
||||
if (expected === actual) return
|
||||
|
||||
check(actual != null && expected != null)
|
||||
|
||||
visitAnnotations(expected.annotations, actual.annotations, context.nextLevel("Property setter annotations"))
|
||||
context.assertFieldsEqual(expected::isDefault, actual::isDefault)
|
||||
context.assertFieldsEqual(expected::isExternal, actual::isExternal)
|
||||
context.assertFieldsEqual(expected::isInline, actual::isInline)
|
||||
context.assertFieldsEqual(expected::getVisibility, actual::getVisibility)
|
||||
visitAnnotations(
|
||||
expected.valueParameters.single().annotations,
|
||||
actual.valueParameters.single().annotations,
|
||||
context.nextLevel("Property setter value parameter annotations")
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitReceiverParameterDescriptor(expected: ReceiverParameterDescriptor?, context: Context) {
|
||||
val actual = context.getActualAs<ReceiverParameterDescriptor?>()
|
||||
if (expected === actual) return
|
||||
|
||||
check(actual != null && expected != null)
|
||||
|
||||
visitType(expected.type, actual.type, context.nextLevel("Receiver parameter type"))
|
||||
visitAnnotations(expected.annotations, actual.annotations, context.nextLevel("Receiver parameter annotations"))
|
||||
}
|
||||
|
||||
override fun visitScriptDescriptor(expected: ScriptDescriptor, context: Context) =
|
||||
fail("Comparison of script descriptors not supported")
|
||||
|
||||
private fun visitAnnotations(expected: Annotations?, actual: Annotations?, context: Context) {
|
||||
if (expected === actual) return
|
||||
|
||||
val expectedAnnotationFqNames = (expected ?: Annotations.EMPTY).map { it.fqName }.toSet()
|
||||
val actualAnnotationFqNames = (actual ?: Annotations.EMPTY).map { it.fqName }.toSet()
|
||||
|
||||
context.assertEquals(expectedAnnotationFqNames, actualAnnotationFqNames, "annotations")
|
||||
}
|
||||
|
||||
private fun visitType(expected: KotlinType, actual: KotlinType, context: Context) {
|
||||
if (expected === actual) return
|
||||
|
||||
val expectedUnwrapped = expected.unwrap()
|
||||
val actualUnwrapped = actual.unwrap()
|
||||
|
||||
if (expectedUnwrapped === actualUnwrapped) return
|
||||
|
||||
val expectedFqName = expectedUnwrapped.constructor.declarationDescriptor!!.fqNameSafe
|
||||
val actualFqName = actualUnwrapped.constructor.declarationDescriptor!!.fqNameSafe
|
||||
|
||||
context.assertEquals(expectedFqName, actualFqName, "type FQN")
|
||||
}
|
||||
|
||||
private fun <T> Context.assertEquals(expected: T?, actual: T?, subject: String) {
|
||||
if (expected != actual)
|
||||
fail(
|
||||
buildString {
|
||||
append("Comparing $subject:\n")
|
||||
append("$expected is not equal to $actual\n")
|
||||
append(this@assertEquals.toString())
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun <T> Context.assertFieldsEqual(expected: KCallable<T>, actual: KCallable<T>) {
|
||||
val expectedValue = expected.call()
|
||||
val actualValue = actual.call()
|
||||
|
||||
assertEquals(expectedValue, actualValue, "fields \"$expected\"")
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -43,17 +43,17 @@ class DefaultPropertySetterCommonizerTest : AbstractCommonizerTest<PropertySette
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun privateOnly() = doTestFailure(PRIVATE)
|
||||
|
||||
@Test
|
||||
fun publicAndProtected() = doTestSuccess(PROTECTED, PUBLIC, PROTECTED, PUBLIC)
|
||||
|
||||
@Test
|
||||
fun publicAndInternal() = doTestSuccess(INTERNAL, PUBLIC, INTERNAL, PUBLIC)
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun publicAndProtected() = doTestFailure(PUBLIC, PUBLIC, PROTECTED)
|
||||
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun protectedAndInternal() = doTestFailure(PUBLIC, INTERNAL, PROTECTED)
|
||||
fun publicAndInternal() = doTestFailure(PUBLIC, PUBLIC, INTERNAL)
|
||||
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun publicAndPrivate() = doTestFailure(PUBLIC, INTERNAL, PRIVATE)
|
||||
fun protectedAndInternal() = doTestFailure(PROTECTED, PROTECTED, INTERNAL)
|
||||
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun publicAndPrivate() = doTestFailure(PUBLIC, PUBLIC, PRIVATE)
|
||||
|
||||
@Test(expected = IllegalStateException::class)
|
||||
fun somethingUnexpected() = doTestFailure(PUBLIC, LOCAL)
|
||||
|
||||
Reference in New Issue
Block a user