[Commonizer] Limited annotation commonization (@Deprecated for functions)
^KMM-238 ^KMM-53
This commit is contained in:
+7
-20
@@ -10,22 +10,16 @@ import org.jetbrains.kotlin.descriptors.ClassKind.ANNOTATION_CLASS
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CirAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.concat
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.constants.AnnotationValue
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.storage.getValue
|
||||
|
||||
class CommonizedAnnotationDescriptor(
|
||||
private val targetComponents: TargetDeclarationsBuilderComponents,
|
||||
override val fqName: FqName,
|
||||
rawValueArguments: Map<Name, ConstantValue<*>>
|
||||
targetComponents: TargetDeclarationsBuilderComponents,
|
||||
cirAnnotation: CirAnnotation
|
||||
) : AnnotationDescriptor {
|
||||
constructor(targetComponents: TargetDeclarationsBuilderComponents, cirAnnotation: CirAnnotation) : this(
|
||||
targetComponents,
|
||||
cirAnnotation.fqName,
|
||||
cirAnnotation.allValueArguments
|
||||
)
|
||||
override val fqName: FqName = cirAnnotation.fqName
|
||||
|
||||
override val type by targetComponents.storageManager.createLazyValue {
|
||||
val annotationClass = findClassOrTypeAlias(targetComponents, fqName)
|
||||
@@ -36,17 +30,10 @@ class CommonizedAnnotationDescriptor(
|
||||
}
|
||||
|
||||
override val allValueArguments by targetComponents.storageManager.createLazyValue {
|
||||
rawValueArguments.mapValues { (_, value) -> substituteValueArgument(value) }
|
||||
cirAnnotation.constantValueArguments concat cirAnnotation.annotationValueArguments.mapValues { (_, nestedCirAnnotation) ->
|
||||
AnnotationValue(CommonizedAnnotationDescriptor(targetComponents, nestedCirAnnotation))
|
||||
}
|
||||
}
|
||||
|
||||
override val source: SourceElement get() = SourceElement.NO_SOURCE
|
||||
|
||||
private fun substituteValueArgument(value: ConstantValue<*>) =
|
||||
(value as? AnnotationValue)?.value?.let { nestedAnnotationDescriptor ->
|
||||
// re-build annotation descriptors
|
||||
val fqName = nestedAnnotationDescriptor.fqName
|
||||
?: error("Annotation with no FQ name: ${nestedAnnotationDescriptor::class.java}, $nestedAnnotationDescriptor")
|
||||
|
||||
AnnotationValue(CommonizedAnnotationDescriptor(targetComponents, fqName, nestedAnnotationDescriptor.allValueArguments))
|
||||
} ?: value // keep other values as they are platform agnostic
|
||||
}
|
||||
|
||||
+1
-4
@@ -120,11 +120,8 @@ internal fun CirSimpleType.buildType(
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: commonize annotations, KT-34234
|
||||
val typeAnnotations = if (!targetComponents.isCommon) annotations.buildDescriptors(targetComponents) else Annotations.EMPTY
|
||||
|
||||
val simpleType = simpleType(
|
||||
annotations = typeAnnotations,
|
||||
annotations = annotations.buildDescriptors(targetComponents),
|
||||
constructor = classifier.typeConstructor,
|
||||
arguments = arguments.map { it.buildArgument(targetComponents, typeParameterResolver) },
|
||||
nullable = isMarkedNullable,
|
||||
|
||||
+3
-1
@@ -13,7 +13,9 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CirFunctionOrPr
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.isNonAbstractMemberInInterface
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class AbstractFunctionOrPropertyCommonizer<T : CirFunctionOrProperty>(cache: CirClassifiersCache) : AbstractStandardCommonizer<T, T>() {
|
||||
abstract class AbstractFunctionOrPropertyCommonizer<T : CirFunctionOrProperty>(
|
||||
cache: CirClassifiersCache
|
||||
) : AbstractStandardCommonizer<T, T>() {
|
||||
protected lateinit var name: Name
|
||||
protected val modality = ModalityCommonizer.default()
|
||||
protected val visibility = VisibilityCommonizer.lowering()
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ abstract class AbstractNullableCommonizer<T : Any, R : Any, WT, WR>(
|
||||
|
||||
final override fun commonizeWith(next: T?): Boolean {
|
||||
state = when (state) {
|
||||
State.ERROR -> State.ERROR
|
||||
State.ERROR -> return false
|
||||
State.EMPTY -> next?.let {
|
||||
wrapped = wrappedCommonizerFactory()
|
||||
doCommonizeWith(next)
|
||||
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.CirAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.DEPRECATED_ANNOTATION_FQN
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||
|
||||
/**
|
||||
* This is limited implementation of annotations commonizer. It helps to commonize only [kotlin.Deprecated] annotations.
|
||||
*/
|
||||
class AnnotationsCommonizer : AbstractStandardCommonizer<List<CirAnnotation>, List<CirAnnotation>>() {
|
||||
private var deprecatedAnnotationCommonizer: DeprecatedAnnotationCommonizer? = null
|
||||
|
||||
override fun commonizationResult(): List<CirAnnotation> {
|
||||
val deprecatedAnnotation = deprecatedAnnotationCommonizer?.result ?: return emptyList()
|
||||
return listOf(deprecatedAnnotation)
|
||||
}
|
||||
|
||||
override fun initialize(first: List<CirAnnotation>) = Unit
|
||||
|
||||
override fun doCommonizeWith(next: List<CirAnnotation>): Boolean {
|
||||
val nextDeprecatedAnnotation = next.firstOrNull { it.fqName == DEPRECATED_ANNOTATION_FQN } ?: return true
|
||||
val deprecatedAnnotationCommonizer = deprecatedAnnotationCommonizer ?: DeprecatedAnnotationCommonizer()
|
||||
return deprecatedAnnotationCommonizer.commonizeWith(nextDeprecatedAnnotation)
|
||||
}
|
||||
}
|
||||
|
||||
private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnnotation> {
|
||||
private var level: DeprecationLevel? = null // null level means that state is empty
|
||||
private var message: String? = null // null -> message is not equal
|
||||
private var replaceWithExpression: String? = null // null -> replaceWith is not equal
|
||||
private var replaceWithImports: List<String>? = null
|
||||
|
||||
override val result: CirAnnotation
|
||||
get() {
|
||||
if (level == null) throw IllegalCommonizerStateException()
|
||||
|
||||
return CirAnnotation.create(
|
||||
fqName = DEPRECATED_ANNOTATION_FQN,
|
||||
constantValueArguments = mapOf<Name, ConstantValue<*>>(
|
||||
PROPERTY_NAME_LEVEL to level!!.toDeprecationLevelValue(),
|
||||
PROPERTY_NAME_MESSAGE to message.toDeprecationMessageValue()
|
||||
),
|
||||
annotationValueArguments = mapOf(
|
||||
PROPERTY_NAME_REPLACE_WITH to replaceWithExpression.toReplaceWithValue(replaceWithImports)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun commonizeWith(next: CirAnnotation): Boolean {
|
||||
val nextLevel: DeprecationLevel = next.getDeprecationLevel() ?: DeprecationLevel.HIDDEN
|
||||
val nextMessage: String? = next.getDeprecationMessage()
|
||||
val nextReplaceWith: CirAnnotation? = next.getReplaceWith()
|
||||
val nextReplaceWithExpression: String? = nextReplaceWith?.getReplaceWithExpression()
|
||||
val nextReplaceWithImports: List<String>? = nextReplaceWith?.getReplaceWithImports()
|
||||
|
||||
return if (level != null) {
|
||||
doCommonizeWith(nextLevel, nextMessage, nextReplaceWithExpression, nextReplaceWithImports)
|
||||
} else {
|
||||
// empty, just fill in
|
||||
initialize(nextLevel, nextMessage, nextReplaceWithExpression, nextReplaceWithImports)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
private fun initialize(
|
||||
nextLevel: DeprecationLevel,
|
||||
nextMessage: String?,
|
||||
nextReplaceWithExpression: String?,
|
||||
nextReplaceWithImports: List<String>?
|
||||
) {
|
||||
level = nextLevel
|
||||
message = nextMessage
|
||||
|
||||
if (nextReplaceWithExpression != null && nextReplaceWithImports != null) {
|
||||
replaceWithExpression = nextReplaceWithExpression
|
||||
replaceWithImports = nextReplaceWithImports
|
||||
}
|
||||
}
|
||||
|
||||
private fun doCommonizeWith(
|
||||
nextLevel: DeprecationLevel,
|
||||
nextMessage: String?,
|
||||
nextReplaceWithExpression: String?,
|
||||
nextReplaceWithImports: List<String>?
|
||||
): Boolean {
|
||||
if (nextLevel.ordinal > level!!.ordinal)
|
||||
level = nextLevel
|
||||
|
||||
if (nextMessage != message)
|
||||
message = null
|
||||
|
||||
if (nextReplaceWithExpression != replaceWithExpression || nextReplaceWithImports != replaceWithImports) {
|
||||
replaceWithExpression = null
|
||||
replaceWithImports = null
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
companion object {
|
||||
private val PROPERTY_NAME_MESSAGE = Name.identifier(Deprecated::message.name)
|
||||
private val PROPERTY_NAME_REPLACE_WITH = Name.identifier(Deprecated::replaceWith.name)
|
||||
private val PROPERTY_NAME_LEVEL = Name.identifier(Deprecated::level.name)
|
||||
|
||||
private val PROPERTY_NAME_EXPRESSION = Name.identifier(ReplaceWith::expression.name)
|
||||
private val PROPERTY_NAME_IMPORTS = Name.identifier(ReplaceWith::imports.name)
|
||||
|
||||
// Optimization: Keep most frequently used message constants.
|
||||
private val FREQUENTLY_USED_MESSAGE_VALUES: Map<String, StringValue> = listOf(
|
||||
"Use constructor instead",
|
||||
"Use factory method instead"
|
||||
).associateWith { StringValue(it) }
|
||||
|
||||
private val FALLBACK_MESSAGE_VALUE = StringValue("See actual declarations for concrete deprecation messages")
|
||||
|
||||
private val DEPRECATION_LEVEL_FQN = FqName(DeprecationLevel::class.java.name)
|
||||
private val DEPRECATION_LEVEL_CLASS_ID = ClassId.topLevel(DEPRECATION_LEVEL_FQN)
|
||||
|
||||
// Optimization: Keep DeprecationLevel enum constants.
|
||||
private val DEPRECATION_LEVEL_ENUM_ENTRY_VALUES: Map<String, EnumValue> = DeprecationLevel.values().associate {
|
||||
it.name to EnumValue(DEPRECATION_LEVEL_CLASS_ID, Name.identifier(it.name))
|
||||
}
|
||||
|
||||
private val REPLACE_WITH_FQN = FqName(ReplaceWith::class.java.name)
|
||||
|
||||
// Optimization: Keep empty ReplaceWith instance of CirAnnotation.
|
||||
private val EMPTY_REPLACE_WITH_CIR_ANNOTATION = createReplaceWithAnnotation("", emptyList())
|
||||
|
||||
private fun CirAnnotation.getDeprecationMessage(): String? = constantValueArguments.getString(PROPERTY_NAME_MESSAGE)
|
||||
|
||||
private fun String?.toDeprecationMessageValue(): StringValue =
|
||||
if (this == null)
|
||||
FALLBACK_MESSAGE_VALUE
|
||||
else
|
||||
FREQUENTLY_USED_MESSAGE_VALUES[this] ?: StringValue(this)
|
||||
|
||||
private fun CirAnnotation.getDeprecationLevel(): DeprecationLevel? {
|
||||
val enumEntryName = constantValueArguments.getEnumEntryName(PROPERTY_NAME_LEVEL) ?: return null
|
||||
return DeprecationLevel.values().firstOrNull { it.name == enumEntryName }
|
||||
}
|
||||
|
||||
private fun DeprecationLevel.toDeprecationLevelValue(): EnumValue =
|
||||
DEPRECATION_LEVEL_ENUM_ENTRY_VALUES.getValue(name)
|
||||
|
||||
private fun CirAnnotation.getReplaceWith(): CirAnnotation? =
|
||||
annotationValueArguments.getAnnotation(PROPERTY_NAME_REPLACE_WITH)
|
||||
|
||||
private fun CirAnnotation.getReplaceWithExpression(): String? =
|
||||
constantValueArguments.getString(PROPERTY_NAME_EXPRESSION)
|
||||
|
||||
private fun CirAnnotation.getReplaceWithImports(): List<String>? =
|
||||
constantValueArguments.getStringArray(PROPERTY_NAME_IMPORTS)
|
||||
|
||||
private fun String?.toReplaceWithValue(imports: List<String>?): CirAnnotation =
|
||||
if (this == null || imports == null)
|
||||
EMPTY_REPLACE_WITH_CIR_ANNOTATION
|
||||
else
|
||||
createReplaceWithAnnotation(this, imports)
|
||||
|
||||
private inline fun Map<Name, ConstantValue<*>>.getString(name: Name): String? =
|
||||
(this[name] as? StringValue)?.value
|
||||
|
||||
private inline fun Map<Name, ConstantValue<*>>.getEnumEntryName(name: Name): String? =
|
||||
(this[name] as? EnumValue)?.enumEntryName?.asString()
|
||||
|
||||
private inline fun Map<Name, CirAnnotation>.getAnnotation(name: Name): CirAnnotation? =
|
||||
this[name]
|
||||
|
||||
private inline fun Map<Name, ConstantValue<*>>.getStringArray(name: Name): List<String>? {
|
||||
val elements: List<ConstantValue<*>> = (this[name] as? ArrayValue)?.value ?: return null
|
||||
if (elements.isEmpty()) return emptyList()
|
||||
|
||||
val result = mutableListOf<String>()
|
||||
for (element in elements) {
|
||||
if (element is StringValue) {
|
||||
result += element.value
|
||||
} else
|
||||
return null
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private inline fun createReplaceWithAnnotation(expression: String, imports: List<String>): CirAnnotation =
|
||||
CirAnnotation.create(
|
||||
fqName = REPLACE_WITH_FQN,
|
||||
constantValueArguments = mapOf(
|
||||
PROPERTY_NAME_EXPRESSION to StringValue(expression),
|
||||
PROPERTY_NAME_IMPORTS to ArrayValue(
|
||||
value = imports.map { StringValue(it) },
|
||||
computeType = { it.builtIns.getArrayElementType(it.builtIns.stringType) }
|
||||
)
|
||||
),
|
||||
annotationValueArguments = emptyMap()
|
||||
)
|
||||
}
|
||||
}
|
||||
+8
-6
@@ -26,13 +26,15 @@ abstract class AbstractStandardCommonizer<T, R> : Commonizer<T, R> {
|
||||
}
|
||||
|
||||
final override fun commonizeWith(next: T): Boolean {
|
||||
if (state == State.ERROR)
|
||||
return false
|
||||
val result = when (state) {
|
||||
State.ERROR -> return false
|
||||
State.EMPTY -> {
|
||||
initialize(next)
|
||||
doCommonizeWith(next)
|
||||
}
|
||||
State.IN_PROGRESS -> doCommonizeWith(next)
|
||||
}
|
||||
|
||||
if (state == State.EMPTY)
|
||||
initialize(next)
|
||||
|
||||
val result = doCommonizeWith(next)
|
||||
state = if (!result) State.ERROR else State.IN_PROGRESS
|
||||
|
||||
return result
|
||||
|
||||
+3
@@ -10,12 +10,14 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CirCommonFuncti
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CirFunction
|
||||
|
||||
class FunctionCommonizer(cache: CirClassifiersCache) : AbstractFunctionOrPropertyCommonizer<CirFunction>(cache) {
|
||||
private val annotations = AnnotationsCommonizer()
|
||||
private val modifiers = FunctionModifiersCommonizer.default()
|
||||
private val valueParameters = ValueParameterListCommonizer.default(cache)
|
||||
private var hasStableParameterNames = true
|
||||
private var hasSynthesizedParameterNames = false
|
||||
|
||||
override fun commonizationResult() = CirCommonFunction(
|
||||
annotations = annotations.result,
|
||||
name = name,
|
||||
modality = modality.result,
|
||||
visibility = visibility.result,
|
||||
@@ -31,6 +33,7 @@ class FunctionCommonizer(cache: CirClassifiersCache) : AbstractFunctionOrPropert
|
||||
|
||||
override fun doCommonizeWith(next: CirFunction): Boolean {
|
||||
val result = super.doCommonizeWith(next)
|
||||
&& annotations.commonizeWith(next.annotations)
|
||||
&& modifiers.commonizeWith(next)
|
||||
&& valueParameters.commonizeWith(next.valueParameters)
|
||||
|
||||
|
||||
+59
-20
@@ -13,24 +13,17 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.constants.*
|
||||
|
||||
class CirAnnotation private constructor(original: AnnotationDescriptor) {
|
||||
val fqName: FqName = original.fqName?.intern() ?: error("Annotation with no FQ name: ${original::class.java}, $original")
|
||||
val allValueArguments: Map<Name, ConstantValue<*>> = original.allValueArguments.mapKeys { it.key.intern() }
|
||||
|
||||
init {
|
||||
allValueArguments.forEach { (name, constantValue) ->
|
||||
checkConstantSupportedInCommonization(
|
||||
constantValue = constantValue,
|
||||
constantName = name,
|
||||
owner = original
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class CirAnnotation private constructor(
|
||||
val fqName: FqName,
|
||||
val constantValueArguments: Map<Name, ConstantValue<*>>,
|
||||
val annotationValueArguments: Map<Name, CirAnnotation>
|
||||
) {
|
||||
// See also org.jetbrains.kotlin.types.KotlinType.cachedHashCode
|
||||
private var cachedHashCode = 0
|
||||
|
||||
private fun computeHashCode() = hashCode(fqName).appendHashCode(allValueArguments)
|
||||
private fun computeHashCode() = hashCode(fqName)
|
||||
.appendHashCode(constantValueArguments)
|
||||
.appendHashCode(annotationValueArguments)
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var currentHashCode = cachedHashCode
|
||||
@@ -41,15 +34,61 @@ class CirAnnotation private constructor(original: AnnotationDescriptor) {
|
||||
return currentHashCode
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = when {
|
||||
other === this -> true
|
||||
other is CirAnnotation -> fqName == other.fqName && allValueArguments == other.allValueArguments
|
||||
else -> false
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other === this) return true
|
||||
|
||||
return other is CirAnnotation
|
||||
&& fqName == other.fqName
|
||||
&& constantValueArguments == other.constantValueArguments
|
||||
&& annotationValueArguments == other.annotationValueArguments
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val interner = Interner<CirAnnotation>()
|
||||
|
||||
fun create(original: AnnotationDescriptor): CirAnnotation = interner.intern(CirAnnotation(original))
|
||||
fun create(original: AnnotationDescriptor): CirAnnotation {
|
||||
val fqName: FqName = original.fqName?.intern() ?: error("Annotation with no FQ name: ${original::class.java}, $original")
|
||||
|
||||
val allValueArguments: Map<Name, ConstantValue<*>> = original.allValueArguments
|
||||
if (allValueArguments.isEmpty())
|
||||
return create(fqName = fqName, constantValueArguments = emptyMap(), annotationValueArguments = emptyMap())
|
||||
|
||||
val constantValueArguments: MutableMap<Name, ConstantValue<*>> = HashMap()
|
||||
val annotationValueArguments: MutableMap<Name, CirAnnotation> = HashMap()
|
||||
|
||||
allValueArguments.forEach { (name, constantValue) ->
|
||||
checkConstantSupportedInCommonization(
|
||||
constantValue = constantValue,
|
||||
constantName = name,
|
||||
owner = original,
|
||||
allowAnnotationValues = true
|
||||
)
|
||||
|
||||
if (constantValue is AnnotationValue)
|
||||
annotationValueArguments[name.intern()] = create(original = constantValue.value)
|
||||
else
|
||||
constantValueArguments[name.intern()] = constantValue
|
||||
}
|
||||
|
||||
return create(
|
||||
fqName = fqName,
|
||||
constantValueArguments = constantValueArguments,
|
||||
annotationValueArguments = annotationValueArguments
|
||||
)
|
||||
}
|
||||
|
||||
fun create(
|
||||
fqName: FqName,
|
||||
constantValueArguments: Map<Name, ConstantValue<*>>,
|
||||
annotationValueArguments: Map<Name, CirAnnotation>
|
||||
): CirAnnotation {
|
||||
return interner.intern(
|
||||
CirAnnotation(
|
||||
fqName = fqName,
|
||||
constantValueArguments = constantValueArguments,
|
||||
annotationValueArguments = annotationValueArguments
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -40,7 +40,7 @@ data class CirCommonClass(
|
||||
override val isInline: Boolean,
|
||||
override val isInner: Boolean
|
||||
) : CirClass {
|
||||
override val annotations: List<CirAnnotation> get() = emptyList() // TODO: commonize annotations, KT-34234
|
||||
override val annotations: List<CirAnnotation> get() = emptyList()
|
||||
override val isData get() = false
|
||||
override val isExternal get() = false
|
||||
override var companion: FqName? = null
|
||||
@@ -56,7 +56,7 @@ data class CirCommonClassConstructor(
|
||||
override val hasStableParameterNames: Boolean,
|
||||
override val hasSynthesizedParameterNames: Boolean
|
||||
) : CirClassConstructor {
|
||||
override val annotations: List<CirAnnotation> get() = emptyList() // TODO: commonize annotations, KT-34234
|
||||
override val annotations: List<CirAnnotation> get() = emptyList()
|
||||
override val containingClassKind get() = unsupported()
|
||||
override val containingClassModality get() = unsupported()
|
||||
override val containingClassIsData get() = unsupported()
|
||||
|
||||
+1
@@ -30,6 +30,7 @@ interface CirCallableMemberWithParameters {
|
||||
interface CirFunction : CirFunctionOrProperty, CirFunctionModifiers, CirCallableMemberWithParameters
|
||||
|
||||
data class CirCommonFunction(
|
||||
override val annotations: List<CirAnnotation>,
|
||||
override val name: Name,
|
||||
override val modality: Modality,
|
||||
override val visibility: Visibility,
|
||||
|
||||
+8
-4
@@ -9,7 +9,8 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CirExtensionReceiver.Companion.toReceiver
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.utils.intern
|
||||
|
||||
interface CirFunctionOrProperty : CirAnnotatedDeclaration, CirNamedDeclaration, CirDeclarationWithTypeParameters, CirDeclarationWithVisibility, CirDeclarationWithModality, CirMaybeCallableMemberOfClass {
|
||||
interface CirFunctionOrProperty : CirAnnotatedDeclaration, CirNamedDeclaration, CirDeclarationWithTypeParameters,
|
||||
CirDeclarationWithVisibility, CirDeclarationWithModality, CirMaybeCallableMemberOfClass {
|
||||
val isExternal: Boolean
|
||||
val extensionReceiver: CirExtensionReceiver?
|
||||
val returnType: CirType
|
||||
@@ -17,7 +18,6 @@ interface CirFunctionOrProperty : CirAnnotatedDeclaration, CirNamedDeclaration,
|
||||
}
|
||||
|
||||
abstract class CirCommonFunctionOrProperty : CirFunctionOrProperty {
|
||||
final override val annotations: List<CirAnnotation> get() = emptyList() // TODO: commonize annotations, KT-34234
|
||||
final override val containingClassKind: ClassKind? get() = unsupported()
|
||||
final override val containingClassModality: Modality? get() = unsupported()
|
||||
final override val containingClassIsData: Boolean? get() = unsupported()
|
||||
@@ -50,8 +50,12 @@ data class CirExtensionReceiver(
|
||||
val type: CirType
|
||||
) {
|
||||
companion object {
|
||||
fun CirType.toReceiverNoAnnotations() = CirExtensionReceiver( /* TODO: commonize annotations, KT-34234 */ emptyList(), this)
|
||||
fun ReceiverParameterDescriptor.toReceiver() = CirExtensionReceiver(annotations.map(CirAnnotation.Companion::create), CirType.create(type))
|
||||
fun CirType.toReceiverNoAnnotations() = CirExtensionReceiver(annotations = emptyList(), type = this)
|
||||
|
||||
fun ReceiverParameterDescriptor.toReceiver() = CirExtensionReceiver(
|
||||
annotations = annotations.map(CirAnnotation.Companion::create),
|
||||
type = CirType.create(type)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -36,6 +36,7 @@ data class CirCommonProperty(
|
||||
override val setter: CirSetter?,
|
||||
override val typeParameters: List<CirTypeParameter>
|
||||
) : CirCommonFunctionOrProperty(), CirProperty {
|
||||
override val annotations: List<CirAnnotation> get() = emptyList()
|
||||
override val isVar get() = setter != null
|
||||
override val isLateInit get() = false
|
||||
override val isConst get() = false
|
||||
|
||||
@@ -7,11 +7,8 @@ package org.jetbrains.kotlin.descriptors.commonizer.utils
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.types.getAbbreviation
|
||||
|
||||
private val DEPRECATED_ANNOTATION_FQN = FqName(Deprecated::class.java.name)
|
||||
|
||||
internal fun SimpleFunctionDescriptor.isKniBridgeFunction() =
|
||||
name.asString().startsWith("kniBridge")
|
||||
|
||||
|
||||
+14
-4
@@ -12,11 +12,13 @@ internal fun checkConstantSupportedInCommonization(
|
||||
constantValue: ConstantValue<*>,
|
||||
constantName: Name? = null,
|
||||
owner: Any,
|
||||
allowAnnotationValues: Boolean = false,
|
||||
onError: (String) -> Nothing = ::error
|
||||
) {
|
||||
checkConstantSupportedInCommonization(
|
||||
constantValue = constantValue,
|
||||
location = { "${owner::class.java}, $owner" + constantName?.asString()?.let { "[$it]" } },
|
||||
allowAnnotationValues = allowAnnotationValues,
|
||||
onError = onError
|
||||
)
|
||||
}
|
||||
@@ -24,6 +26,7 @@ internal fun checkConstantSupportedInCommonization(
|
||||
private fun checkConstantSupportedInCommonization(
|
||||
constantValue: ConstantValue<*>,
|
||||
location: () -> String,
|
||||
allowAnnotationValues: Boolean,
|
||||
onError: (String) -> Nothing
|
||||
) {
|
||||
@Suppress("TrailingComma")
|
||||
@@ -36,21 +39,28 @@ private fun checkConstantSupportedInCommonization(
|
||||
is DoubleValue,
|
||||
is FloatValue,
|
||||
is EnumValue -> {
|
||||
// OK
|
||||
return // OK
|
||||
}
|
||||
is AnnotationValue -> {
|
||||
if (constantValue.value.fqName?.isUnderStandardKotlinPackages != true)
|
||||
onError("Only ${constantValue::class.java} const values from Kotlin standard packages are supported, $constantValue at ${location()}")
|
||||
if (allowAnnotationValues) {
|
||||
if (constantValue.value.fqName?.isUnderStandardKotlinPackages != true)
|
||||
onError("Only ${constantValue::class.java} const values from Kotlin standard packages are supported, $constantValue at ${location()}")
|
||||
return // OK
|
||||
} // else fail (see below)
|
||||
}
|
||||
is ArrayValue -> {
|
||||
constantValue.value.forEachIndexed { index, innerConstantValue ->
|
||||
checkConstantSupportedInCommonization(
|
||||
constantValue = innerConstantValue,
|
||||
location = { "${location()}[$index]" },
|
||||
allowAnnotationValues = allowAnnotationValues,
|
||||
onError = onError
|
||||
)
|
||||
}
|
||||
return // OK
|
||||
}
|
||||
else -> onError("Unsupported const value type: ${constantValue::class.java}, $constantValue at ${location()}")
|
||||
}
|
||||
|
||||
onError("Unsupported const value type: ${constantValue::class.java}, $constantValue at ${location()}")
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.serialization.konan.impl.ForwardDeclarationsFqNames
|
||||
|
||||
internal val DEPRECATED_ANNOTATION_FQN: FqName = FqName(Deprecated::class.java.name)
|
||||
|
||||
private val STANDARD_KOTLIN_PACKAGE_PREFIXES = listOf(
|
||||
KotlinBuiltIns.BUILT_INS_PACKAGE_NAME.asString(),
|
||||
"kotlinx"
|
||||
|
||||
@@ -13,6 +13,16 @@ internal fun <T> Sequence<T>.toList(expectedCapacity: Int): List<T> {
|
||||
return result
|
||||
}
|
||||
|
||||
internal infix fun <K, V> Map<K, V>.concat(other: Map<K, V>): Map<K, V> =
|
||||
when {
|
||||
isEmpty() -> other
|
||||
other.isEmpty() -> this
|
||||
else -> HashMap<K, V>(size + other.size, 1F).apply {
|
||||
putAll(this@concat)
|
||||
putAll(other)
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun <reified T> Iterable<T?>.firstNonNull() = firstIsInstance<T>()
|
||||
|
||||
internal fun Any?.isNull(): Boolean = this == null
|
||||
|
||||
Reference in New Issue
Block a user