[Commonizer] Limited annotation commonization. Tests
^KMM-238 ^KMM-53
This commit is contained in:
+44
-36
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors.commonizer.core
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.core.AnnotationsCommonizer.Companion.FALLBACK_MESSAGE
|
||||
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
|
||||
@@ -14,6 +15,7 @@ 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
|
||||
import kotlin.DeprecationLevel.WARNING
|
||||
|
||||
/**
|
||||
* This is limited implementation of annotations commonizer. It helps to commonize only [kotlin.Deprecated] annotations.
|
||||
@@ -30,39 +32,55 @@ class AnnotationsCommonizer : AbstractStandardCommonizer<List<CirAnnotation>, Li
|
||||
|
||||
override fun doCommonizeWith(next: List<CirAnnotation>): Boolean {
|
||||
val nextDeprecatedAnnotation = next.firstOrNull { it.fqName == DEPRECATED_ANNOTATION_FQN } ?: return true
|
||||
val deprecatedAnnotationCommonizer = deprecatedAnnotationCommonizer ?: DeprecatedAnnotationCommonizer()
|
||||
val deprecatedAnnotationCommonizer = deprecatedAnnotationCommonizer
|
||||
?: DeprecatedAnnotationCommonizer().also { this.deprecatedAnnotationCommonizer = it }
|
||||
return deprecatedAnnotationCommonizer.commonizeWith(nextDeprecatedAnnotation)
|
||||
}
|
||||
|
||||
companion object {
|
||||
internal const val FALLBACK_MESSAGE = "See concrete deprecation messages in actual declarations"
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
private lateinit var replaceWithExpression: String
|
||||
private lateinit var replaceWithImports: List<String>
|
||||
|
||||
override val result: CirAnnotation
|
||||
get() {
|
||||
if (level == null) throw IllegalCommonizerStateException()
|
||||
val level: DeprecationLevel = level ?: throw IllegalCommonizerStateException()
|
||||
val messageValue: StringValue = message.toDeprecationMessageValue()
|
||||
|
||||
val constantValueArguments: Map<Name, ConstantValue<*>> = if (level == WARNING) {
|
||||
// don't populate with the default level value
|
||||
mapOf(PROPERTY_NAME_MESSAGE to messageValue)
|
||||
} else
|
||||
hashMapOf(
|
||||
PROPERTY_NAME_MESSAGE to messageValue,
|
||||
PROPERTY_NAME_LEVEL to level.toDeprecationLevelValue()
|
||||
)
|
||||
|
||||
val annotationValueArguments: Map<Name, CirAnnotation> = if (replaceWithExpression.isEmpty() && replaceWithImports.isEmpty()) {
|
||||
// don't populate with empty (default) ReplaceWith
|
||||
emptyMap()
|
||||
} else
|
||||
mapOf(PROPERTY_NAME_REPLACE_WITH to replaceWithExpression.toReplaceWithValue(replaceWithImports))
|
||||
|
||||
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)
|
||||
)
|
||||
constantValueArguments = constantValueArguments,
|
||||
annotationValueArguments = annotationValueArguments
|
||||
)
|
||||
}
|
||||
|
||||
override fun commonizeWith(next: CirAnnotation): Boolean {
|
||||
val nextLevel: DeprecationLevel = next.getDeprecationLevel() ?: DeprecationLevel.HIDDEN
|
||||
val nextMessage: String? = next.getDeprecationMessage()
|
||||
val nextLevel: DeprecationLevel = next.getDeprecationLevel() ?: WARNING
|
||||
val nextMessage: String = next.getDeprecationMessage().orEmpty()
|
||||
val nextReplaceWith: CirAnnotation? = next.getReplaceWith()
|
||||
val nextReplaceWithExpression: String? = nextReplaceWith?.getReplaceWithExpression()
|
||||
val nextReplaceWithImports: List<String>? = nextReplaceWith?.getReplaceWithImports()
|
||||
val nextReplaceWithExpression: String = nextReplaceWith?.getReplaceWithExpression().orEmpty()
|
||||
val nextReplaceWithImports: List<String> = nextReplaceWith?.getReplaceWithImports().orEmpty()
|
||||
|
||||
return if (level != null) {
|
||||
doCommonizeWith(nextLevel, nextMessage, nextReplaceWithExpression, nextReplaceWithImports)
|
||||
@@ -76,23 +94,20 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno
|
||||
private fun initialize(
|
||||
nextLevel: DeprecationLevel,
|
||||
nextMessage: String?,
|
||||
nextReplaceWithExpression: String?,
|
||||
nextReplaceWithImports: List<String>?
|
||||
nextReplaceWithExpression: String,
|
||||
nextReplaceWithImports: List<String>
|
||||
) {
|
||||
level = nextLevel
|
||||
message = nextMessage
|
||||
|
||||
if (nextReplaceWithExpression != null && nextReplaceWithImports != null) {
|
||||
replaceWithExpression = nextReplaceWithExpression
|
||||
replaceWithImports = nextReplaceWithImports
|
||||
}
|
||||
replaceWithExpression = nextReplaceWithExpression
|
||||
replaceWithImports = nextReplaceWithImports
|
||||
}
|
||||
|
||||
private fun doCommonizeWith(
|
||||
nextLevel: DeprecationLevel,
|
||||
nextMessage: String?,
|
||||
nextReplaceWithExpression: String?,
|
||||
nextReplaceWithImports: List<String>?
|
||||
nextReplaceWithExpression: String,
|
||||
nextReplaceWithImports: List<String>
|
||||
): Boolean {
|
||||
if (nextLevel.ordinal > level!!.ordinal)
|
||||
level = nextLevel
|
||||
@@ -101,8 +116,8 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno
|
||||
message = null
|
||||
|
||||
if (nextReplaceWithExpression != replaceWithExpression || nextReplaceWithImports != replaceWithImports) {
|
||||
replaceWithExpression = null
|
||||
replaceWithImports = null
|
||||
replaceWithExpression = ""
|
||||
replaceWithImports = emptyList()
|
||||
}
|
||||
|
||||
return true
|
||||
@@ -122,8 +137,7 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno
|
||||
"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 FALLBACK_MESSAGE_VALUE = StringValue(FALLBACK_MESSAGE)
|
||||
|
||||
private val DEPRECATION_LEVEL_FQN = FqName(DeprecationLevel::class.java.name)
|
||||
private val DEPRECATION_LEVEL_CLASS_ID = ClassId.topLevel(DEPRECATION_LEVEL_FQN)
|
||||
@@ -135,9 +149,6 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno
|
||||
|
||||
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 =
|
||||
@@ -163,11 +174,8 @@ private class DeprecatedAnnotationCommonizer : Commonizer<CirAnnotation, CirAnno
|
||||
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 fun String.toReplaceWithValue(imports: List<String>): CirAnnotation =
|
||||
createReplaceWithAnnotation(this, imports)
|
||||
|
||||
private inline fun Map<Name, ConstantValue<*>>.getString(name: Name): String? =
|
||||
(this[name] as? StringValue)?.value
|
||||
|
||||
Vendored
+45
@@ -0,0 +1,45 @@
|
||||
expect class Holder() {
|
||||
@Deprecated("This function is deprecated")
|
||||
expect fun deprecatedFunction1()
|
||||
|
||||
@Deprecated("See concrete deprecation messages in actual declarations")
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation1()
|
||||
@Deprecated("This function is deprecated")
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation2()
|
||||
@Deprecated("This function is deprecated")
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation3()
|
||||
@Deprecated("This function is deprecated", level = DeprecationLevel.ERROR)
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation4()
|
||||
@Deprecated("This function is deprecated")
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation5()
|
||||
@Deprecated("This function is deprecated")
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation6()
|
||||
@Deprecated("This function is deprecated")
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation7()
|
||||
@Deprecated("This function is deprecated")
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation8()
|
||||
@Deprecated("This function is deprecated")
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation9()
|
||||
@Deprecated("This function is deprecated")
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation10()
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()"))
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation11()
|
||||
@Deprecated("This function is deprecated")
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation12()
|
||||
@Deprecated("This function is deprecated")
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation13()
|
||||
@Deprecated("This function is deprecated")
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation14()
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = arrayOf("org.sample.foo")))
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation15()
|
||||
@Deprecated("This function is deprecated")
|
||||
expect fun deprecatedFunctionWithCustomizedAnnotation16()
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()", imports = arrayOf("org.sample.foo")))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation17() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunctionWithCustomizedAnnotation18() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunctionWithCustomizedAnnotation19() {}
|
||||
|
||||
expect fun nonDeprecatedFunction1()
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
actual class Holder actual constructor() {
|
||||
@Deprecated("This function is deprecated")
|
||||
actual fun deprecatedFunction1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction2() {}
|
||||
|
||||
@Deprecated("This function is deprecated")
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation2() {}
|
||||
@Deprecated("This function is deprecated", level = DeprecationLevel.WARNING)
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation3() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation4() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation5() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith(""))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation6() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation7() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith(""))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation8() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = emptyArray()))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation9() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation10() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()"))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation11() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("bar()"))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation12() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation13() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith(""))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation14() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = arrayOf("org.sample.foo")))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation15() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = arrayOf("org.sample.bar")))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation16() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()", imports = arrayOf("org.sample.foo")))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation17() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()", imports = arrayOf("org.sample.bar")))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation18() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("bar()", imports = arrayOf("org.sample.foo")))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation19() {}
|
||||
|
||||
actual fun nonDeprecatedFunction1() {}
|
||||
fun nonDeprecatedFunction2() {}
|
||||
}
|
||||
Vendored
+48
@@ -0,0 +1,48 @@
|
||||
actual class Holder actual constructor() {
|
||||
@Deprecated("This function is deprecated")
|
||||
actual fun deprecatedFunction1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction3() {}
|
||||
|
||||
@Deprecated("This function is deprecated as well")
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation1() {}
|
||||
@Deprecated("This function is deprecated", level = DeprecationLevel.WARNING)
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation2() {}
|
||||
@Deprecated("This function is deprecated", level = DeprecationLevel.WARNING)
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation3() {}
|
||||
@Deprecated("This function is deprecated", level = DeprecationLevel.ERROR)
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation4() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith(""))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation5() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith(""))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation6() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = emptyArray()))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation7() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = emptyArray()))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation8() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = emptyArray()))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation9() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()"))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation10() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()"))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation11() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()"))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation12() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = arrayOf("org.sample.foo")))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation13() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = arrayOf("org.sample.foo")))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation14() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = arrayOf("org.sample.foo")))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation15() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = arrayOf("org.sample.foo")))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation16() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()", imports = arrayOf("org.sample.foo")))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation17() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()", imports = arrayOf("org.sample.foo")))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation18() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()", imports = arrayOf("org.sample.foo")))
|
||||
actual fun deprecatedFunctionWithCustomizedAnnotation19() {}
|
||||
|
||||
actual fun nonDeprecatedFunction1() {}
|
||||
fun nonDeprecatedFunction3() {}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction2() {}
|
||||
|
||||
class Holder {
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction2() {}
|
||||
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunctionWithCustomizedAnnotation1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunctionWithCustomizedAnnotation2() {}
|
||||
@Deprecated("This function is deprecated", level = DeprecationLevel.WARNING)
|
||||
fun deprecatedFunctionWithCustomizedAnnotation3() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunctionWithCustomizedAnnotation4() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunctionWithCustomizedAnnotation5() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith(""))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation6() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunctionWithCustomizedAnnotation7() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith(""))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation8() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = emptyArray()))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation9() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunctionWithCustomizedAnnotation10() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()"))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation11() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("bar()"))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation12() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunctionWithCustomizedAnnotation13() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith(""))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation14() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = arrayOf("org.sample.foo")))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation15() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = arrayOf("org.sample.bar")))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation16() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()", imports = arrayOf("org.sample.foo")))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation17() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()", imports = arrayOf("org.sample.bar")))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation18() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("bar()", imports = arrayOf("org.sample.foo")))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation19() {}
|
||||
|
||||
fun nonDeprecatedFunction1() {}
|
||||
fun nonDeprecatedFunction2() {}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction3() {}
|
||||
|
||||
class Holder {
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction3() {}
|
||||
|
||||
@Deprecated("This function is deprecated as well")
|
||||
fun deprecatedFunctionWithCustomizedAnnotation1() {}
|
||||
@Deprecated("This function is deprecated", level = DeprecationLevel.WARNING)
|
||||
fun deprecatedFunctionWithCustomizedAnnotation2() {}
|
||||
@Deprecated("This function is deprecated", level = DeprecationLevel.WARNING)
|
||||
fun deprecatedFunctionWithCustomizedAnnotation3() {}
|
||||
@Deprecated("This function is deprecated", level = DeprecationLevel.ERROR)
|
||||
fun deprecatedFunctionWithCustomizedAnnotation4() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith(""))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation5() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith(""))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation6() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = emptyArray()))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation7() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = emptyArray()))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation8() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = emptyArray()))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation9() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()"))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation10() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()"))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation11() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()"))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation12() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = arrayOf("org.sample.foo")))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation13() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = arrayOf("org.sample.foo")))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation14() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = arrayOf("org.sample.foo")))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation15() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("", imports = arrayOf("org.sample.foo")))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation16() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()", imports = arrayOf("org.sample.foo")))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation17() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()", imports = arrayOf("org.sample.foo")))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation18() {}
|
||||
@Deprecated("This function is deprecated", replaceWith = ReplaceWith("foo()", imports = arrayOf("org.sample.foo")))
|
||||
fun deprecatedFunctionWithCustomizedAnnotation19() {}
|
||||
|
||||
fun nonDeprecatedFunction1() {}
|
||||
fun nonDeprecatedFunction3() {}
|
||||
}
|
||||
Vendored
-5
@@ -16,8 +16,3 @@ expect fun externalFunction2()
|
||||
|
||||
expect inline fun inlineFunction1() {}
|
||||
expect fun inlineFunction2() {}
|
||||
|
||||
expect class Holder() {
|
||||
expect fun deprecatedFunction1()
|
||||
expect fun nonDeprecatedFunction1()
|
||||
}
|
||||
|
||||
-10
@@ -17,13 +17,3 @@ actual external fun externalFunction2()
|
||||
|
||||
actual inline fun inlineFunction1() {}
|
||||
actual inline fun inlineFunction2() {}
|
||||
|
||||
actual class Holder actual constructor() {
|
||||
@Deprecated("This function is deprecated")
|
||||
actual fun deprecatedFunction1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction2() {}
|
||||
|
||||
actual fun nonDeprecatedFunction1() {}
|
||||
fun nonDeprecatedFunction2() {}
|
||||
}
|
||||
|
||||
-10
@@ -17,13 +17,3 @@ actual fun externalFunction2() {}
|
||||
|
||||
actual inline fun inlineFunction1() {}
|
||||
actual fun inlineFunction2() {}
|
||||
|
||||
actual class Holder actual constructor() {
|
||||
@Deprecated("This function is deprecated")
|
||||
actual fun deprecatedFunction1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction3() {}
|
||||
|
||||
actual fun nonDeprecatedFunction1() {}
|
||||
fun nonDeprecatedFunction3() {}
|
||||
}
|
||||
|
||||
-15
@@ -17,18 +17,3 @@ external fun externalFunction2()
|
||||
|
||||
inline fun inlineFunction1() {}
|
||||
inline fun inlineFunction2() {}
|
||||
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction2() {}
|
||||
|
||||
class Holder {
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction2() {}
|
||||
|
||||
fun nonDeprecatedFunction1() {}
|
||||
fun nonDeprecatedFunction2() {}
|
||||
}
|
||||
|
||||
-15
@@ -17,18 +17,3 @@ fun externalFunction2() {}
|
||||
|
||||
inline fun inlineFunction1() {}
|
||||
fun inlineFunction2() {}
|
||||
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction3() {}
|
||||
|
||||
class Holder {
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction1() {}
|
||||
@Deprecated("This function is deprecated")
|
||||
fun deprecatedFunction3() {}
|
||||
|
||||
fun nonDeprecatedFunction1() {}
|
||||
fun nonDeprecatedFunction3() {}
|
||||
}
|
||||
|
||||
+2
@@ -12,5 +12,7 @@ class FunctionCommonizationFromSourcesTest : AbstractCommonizationFromSourcesTes
|
||||
|
||||
fun testValueParameters() = doTestSuccessfulCommonization()
|
||||
|
||||
fun testAnnotations() = doTestSuccessfulCommonization()
|
||||
|
||||
fun testSpecifics() = doTestSuccessfulCommonization()
|
||||
}
|
||||
|
||||
+330
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* 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.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
|
||||
import org.junit.Test
|
||||
import kotlin.DeprecationLevel.*
|
||||
|
||||
class AnnotationsCommonizerTest : AbstractCommonizerTest<List<CirAnnotation>, List<CirAnnotation>>() {
|
||||
|
||||
@Test
|
||||
fun noAnnotations() = doTestSuccess(
|
||||
expected = emptyList(),
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
emptyList()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun noRelevantAnnotations1() = doTestSuccess(
|
||||
expected = emptyList(),
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
listOf(mockAnnotation("org.sample.Foo"))
|
||||
)
|
||||
|
||||
@Test
|
||||
fun noRelevantAnnotations2() = doTestSuccess(
|
||||
expected = emptyList(),
|
||||
listOf(mockAnnotation("org.sample.Foo")),
|
||||
emptyList(),
|
||||
emptyList()
|
||||
)
|
||||
|
||||
@Test
|
||||
fun noRelevantAnnotations3() = doTestSuccess(
|
||||
expected = emptyList(),
|
||||
listOf(mockAnnotation("org.sample.Foo")),
|
||||
listOf(mockAnnotation("org.sample.Foo")),
|
||||
listOf(mockAnnotation("org.sample.Foo"))
|
||||
)
|
||||
|
||||
@Test
|
||||
fun noRelevantAnnotations4() = doTestSuccess(
|
||||
expected = emptyList(),
|
||||
listOf(mockAnnotation("org.sample.Foo")),
|
||||
listOf(mockAnnotation("org.sample.Bar")),
|
||||
listOf(mockAnnotation("org.sample.Baz"))
|
||||
)
|
||||
|
||||
@Test
|
||||
fun noRelevantAnnotations5() = doTestSuccess(
|
||||
expected = emptyList(),
|
||||
listOf(mockAnnotation("kotlin.PublishedApi")),
|
||||
listOf(mockAnnotation("kotlin.PublishedApi")),
|
||||
listOf(mockAnnotation("kotlin.PublishedApi"))
|
||||
)
|
||||
|
||||
@Test
|
||||
fun sameMessages() = doTestSuccess(
|
||||
expected = listOf(mockDeprecated(message = "please don't use it because ...")),
|
||||
listOf(mockDeprecated(message = "please don't use it because ...")),
|
||||
listOf(mockDeprecated(message = "please don't use it because ...")),
|
||||
listOf(mockDeprecated(message = "please don't use it because ..."))
|
||||
)
|
||||
|
||||
@Test
|
||||
fun differentMessages() = doTestSuccess(
|
||||
expected = listOf(mockDeprecated(message = AnnotationsCommonizer.FALLBACK_MESSAGE)),
|
||||
listOf(mockDeprecated(message = "please don't use it because ...")),
|
||||
listOf(mockDeprecated(message = "it should not be used due to ...")),
|
||||
listOf(mockDeprecated(message = "please don't use it because ..."))
|
||||
)
|
||||
|
||||
@Test
|
||||
fun sameLevels1() = doTestSuccess(
|
||||
expected = listOf(mockDeprecated(level = WARNING)),
|
||||
listOf(mockDeprecated(level = WARNING)),
|
||||
listOf(mockDeprecated(level = WARNING)),
|
||||
listOf(mockDeprecated(level = WARNING))
|
||||
)
|
||||
|
||||
@Test
|
||||
fun sameLevels2() = doTestSuccess(
|
||||
expected = listOf(mockDeprecated(level = ERROR)),
|
||||
listOf(mockDeprecated(level = ERROR)),
|
||||
listOf(mockDeprecated(level = ERROR)),
|
||||
listOf(mockDeprecated(level = ERROR))
|
||||
)
|
||||
|
||||
@Test
|
||||
fun sameLevels3() = doTestSuccess(
|
||||
expected = listOf(mockDeprecated(level = HIDDEN)),
|
||||
listOf(mockDeprecated(level = HIDDEN)),
|
||||
listOf(mockDeprecated(level = HIDDEN)),
|
||||
listOf(mockDeprecated(level = HIDDEN))
|
||||
)
|
||||
|
||||
@Test
|
||||
fun differentLevels1() = doTestSuccess(
|
||||
expected = listOf(mockDeprecated(level = ERROR)),
|
||||
listOf(mockDeprecated(level = WARNING)),
|
||||
listOf(mockDeprecated(level = ERROR)),
|
||||
listOf(mockDeprecated(level = WARNING))
|
||||
)
|
||||
|
||||
@Test
|
||||
fun differentLevels2() = doTestSuccess(
|
||||
expected = listOf(mockDeprecated(level = HIDDEN)),
|
||||
listOf(mockDeprecated(level = WARNING)),
|
||||
listOf(mockDeprecated(level = HIDDEN)),
|
||||
listOf(mockDeprecated(level = WARNING))
|
||||
)
|
||||
|
||||
@Test
|
||||
fun differentLevels3() = doTestSuccess(
|
||||
expected = listOf(mockDeprecated(level = HIDDEN)),
|
||||
listOf(mockDeprecated(level = ERROR)),
|
||||
listOf(mockDeprecated(level = HIDDEN)),
|
||||
listOf(mockDeprecated(level = ERROR))
|
||||
)
|
||||
|
||||
@Test
|
||||
fun differentLevels4() = doTestSuccess(
|
||||
expected = listOf(mockDeprecated(level = HIDDEN)),
|
||||
listOf(mockDeprecated(level = ERROR)),
|
||||
listOf(mockDeprecated(level = HIDDEN)),
|
||||
listOf(mockDeprecated(level = WARNING))
|
||||
)
|
||||
|
||||
@Test
|
||||
fun sameReplaceWith1() = doTestSuccess(
|
||||
expected = listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = emptyArray()
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = emptyArray()
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = emptyArray()
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = emptyArray()
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun sameReplaceWith2() = doTestSuccess(
|
||||
expected = listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = arrayOf("org.sample.Foo")
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = arrayOf("org.sample.Foo")
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = arrayOf("org.sample.Foo")
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = arrayOf("org.sample.Foo")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun sameReplaceWith3() = doTestSuccess(
|
||||
expected = listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = arrayOf("org.sample.Foo", "org.sample.foo.*")
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = arrayOf("org.sample.Foo", "org.sample.foo.*")
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = arrayOf("org.sample.Foo", "org.sample.foo.*")
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = arrayOf("org.sample.Foo", "org.sample.foo.*")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun differentReplaceWith1() = doTestSuccess(
|
||||
expected = listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "",
|
||||
replaceWithImports = emptyArray()
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = arrayOf("org.sample.Foo", "org.sample.foo.*")
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Bar",
|
||||
replaceWithImports = arrayOf("org.sample.Foo", "org.sample.foo.*")
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = arrayOf("org.sample.Foo", "org.sample.foo.*")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun differentReplaceWith2() = doTestSuccess(
|
||||
expected = listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "",
|
||||
replaceWithImports = emptyArray()
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = arrayOf("org.sample.Foo", "org.sample.foo.*")
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = arrayOf("org.sample.Foo")
|
||||
)
|
||||
),
|
||||
listOf(
|
||||
mockDeprecated(
|
||||
replaceWithExpression = "org.sample.Foo",
|
||||
replaceWithImports = arrayOf("org.sample.Foo", "org.sample.foo.*")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
override fun createCommonizer() = AnnotationsCommonizer()
|
||||
|
||||
override fun isEqual(a: List<CirAnnotation>?, b: List<CirAnnotation>?): Boolean {
|
||||
return super.isEqual(a, b)
|
||||
}
|
||||
}
|
||||
|
||||
private fun mockAnnotation(
|
||||
fqName: String,
|
||||
constantValueArguments: Map<Name, ConstantValue<*>> = emptyMap(),
|
||||
annotationValueArguments: Map<Name, CirAnnotation> = emptyMap()
|
||||
): CirAnnotation = CirAnnotation.create(
|
||||
fqName = FqName(fqName),
|
||||
constantValueArguments = constantValueArguments,
|
||||
annotationValueArguments = annotationValueArguments
|
||||
)
|
||||
|
||||
private fun mockDeprecated(
|
||||
message: String = "",
|
||||
level: DeprecationLevel = WARNING,
|
||||
replaceWithExpression: String = "",
|
||||
replaceWithImports: Array<String> = emptyArray()
|
||||
): CirAnnotation {
|
||||
val replaceWith: CirAnnotation? = if (replaceWithExpression.isNotEmpty() || replaceWithImports.isNotEmpty()) {
|
||||
mockAnnotation(
|
||||
fqName = "kotlin.ReplaceWith",
|
||||
constantValueArguments = mapOf(
|
||||
Name.identifier("expression") to StringValue(replaceWithExpression),
|
||||
Name.identifier("imports") to ArrayValue(replaceWithImports.map(::StringValue)) {
|
||||
it.builtIns.getArrayElementType(it.builtIns.stringType)
|
||||
}
|
||||
),
|
||||
annotationValueArguments = emptyMap()
|
||||
)
|
||||
} else null
|
||||
|
||||
return mockAnnotation(
|
||||
fqName = "kotlin.Deprecated",
|
||||
constantValueArguments = HashMap<Name, ConstantValue<*>>().apply {
|
||||
this[Name.identifier("message")] = StringValue(message)
|
||||
|
||||
if (level != WARNING)
|
||||
this[Name.identifier("level")] = EnumValue(
|
||||
ClassId.topLevel(FqName("kotlin.DeprecationLevel")),
|
||||
Name.identifier(level.name)
|
||||
)
|
||||
},
|
||||
annotationValueArguments = if (replaceWith != null) mapOf(Name.identifier("replaceWith") to replaceWith) else emptyMap()
|
||||
)
|
||||
}
|
||||
+19
-2
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.*
|
||||
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.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
@@ -429,6 +430,7 @@ internal class ComparingDeclarationsVisitor(
|
||||
constantValue = expectedValueArgument,
|
||||
constantName = name,
|
||||
owner = expected,
|
||||
allowAnnotationValues = true,
|
||||
onError = { context.fail(it) }
|
||||
)
|
||||
|
||||
@@ -437,11 +439,26 @@ internal class ComparingDeclarationsVisitor(
|
||||
constantValue = actualValueArgument,
|
||||
constantName = name,
|
||||
owner = actual,
|
||||
allowAnnotationValues = true,
|
||||
onError = { context.fail(it) }
|
||||
)
|
||||
|
||||
context.assertEquals(expectedValueArgument::class, actualValueArgument::class, "annotation value argument classe")
|
||||
context.assertEquals(expectedValueArgument.value, actualValueArgument.value, "annotation value argument value")
|
||||
context.assertEquals(expectedValueArgument::class, actualValueArgument::class, "annotation value argument value")
|
||||
if (expectedValueArgument is AnnotationValue && actualValueArgument is AnnotationValue) {
|
||||
context.assertEquals(
|
||||
expectedValueArgument.value.fqName,
|
||||
actualValueArgument.value.fqName,
|
||||
"nested annotation FQ name"
|
||||
)
|
||||
|
||||
visitAnnotation(
|
||||
expectedValueArgument.value,
|
||||
actualValueArgument.value,
|
||||
context.nextLevel("Annotation ${expectedValueArgument.value.fqName}")
|
||||
)
|
||||
} else {
|
||||
context.assertEquals(expectedValueArgument.value, actualValueArgument.value, "annotation value argument value")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user