Introduced IDEAPluginsCompatibilityAPI and returned some API
Please read the description of IDEAPluginsCompatibilityAPI. Also, you may notice, that Deprecation annotation was removed. That is because with level ERROR it isn't possible to opt-in to such API in the legit cases. And with level WARNING it won't be reported because We have diagnostic with level ERROR about OptIn marker. Sadly, there is no way to add ReplaceWith to the OptIn marker
This commit is contained in:
+10
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.utils.IDEAPlatforms
|
||||
import org.jetbrains.kotlin.utils.IDEAPluginsCompatibilityAPI
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
@@ -149,6 +151,14 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
|
||||
)
|
||||
var readDeserializedContracts: Boolean by FreezableVar(false)
|
||||
|
||||
@IDEAPluginsCompatibilityAPI(
|
||||
IDEAPlatforms._212, // maybe 211 AS used it too
|
||||
IDEAPlatforms._213,
|
||||
message = "Please migrate to -opt-in",
|
||||
plugins = "Android"
|
||||
)
|
||||
var experimental: Array<String>? = null
|
||||
|
||||
@Argument(
|
||||
value = "-Xuse-experimental",
|
||||
valueDescription = "<fq.name>",
|
||||
|
||||
@@ -17,59 +17,58 @@ import org.jetbrains.kotlin.resolve.calls.util.getCalleeExpressionIfAny
|
||||
import org.jetbrains.kotlin.resolve.calls.util.createLookupLocation
|
||||
import org.jetbrains.kotlin.resolve.calls.util.getValueArgumentForExpression
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.IDEAPlatforms
|
||||
import org.jetbrains.kotlin.utils.IDEAPluginsCompatibilityAPI
|
||||
|
||||
@Deprecated(
|
||||
"Use org.jetbrains.kotlin.resolve.calls.util.getResolvedCall instead.",
|
||||
ReplaceWith("getResolvedCall", "org.jetbrains.kotlin.resolve.calls.util.getResolvedCall"),
|
||||
level = DeprecationLevel.ERROR
|
||||
@IDEAPluginsCompatibilityAPI(
|
||||
IDEAPlatforms._213, // I'm not sure about 212 and 211 AS -- didn't check them
|
||||
message = "Use org.jetbrains.kotlin.resolve.calls.util.getResolvedCall instead.",
|
||||
plugins = "Android in IDEA"
|
||||
)
|
||||
fun Call?.getResolvedCall(context: BindingContext): ResolvedCall<out CallableDescriptor>? = getResolvedCall(context)
|
||||
|
||||
@Deprecated(
|
||||
"Use org.jetbrains.kotlin.resolve.calls.util.getResolvedCall instead.",
|
||||
ReplaceWith("getResolvedCall", "org.jetbrains.kotlin.resolve.calls.util.getResolvedCall"),
|
||||
level = DeprecationLevel.ERROR
|
||||
@IDEAPluginsCompatibilityAPI(
|
||||
IDEAPlatforms._213, // I'm not sure about 212 and 211 AS -- didn't check them
|
||||
message = "Use org.jetbrains.kotlin.resolve.calls.util.getResolvedCall instead.",
|
||||
plugins = "Android in IDEA"
|
||||
)
|
||||
fun KtElement?.getResolvedCall(context: BindingContext): ResolvedCall<out CallableDescriptor>? = getResolvedCall(context)
|
||||
|
||||
@Deprecated(
|
||||
"Use org.jetbrains.kotlin.resolve.calls.util.getType instead.",
|
||||
ReplaceWith("getType", "org.jetbrains.kotlin.resolve.calls.util.getType"),
|
||||
level = DeprecationLevel.ERROR
|
||||
|
||||
// TODO: find what IDEA's used it
|
||||
@IDEAPluginsCompatibilityAPI(
|
||||
message = "Use org.jetbrains.kotlin.resolve.calls.util.getType instead."
|
||||
)
|
||||
fun KtExpression.getType(context: BindingContext): KotlinType? = getType(context)
|
||||
|
||||
@Deprecated(
|
||||
"Use org.jetbrains.kotlin.resolve.calls.util.getCall instead.",
|
||||
ReplaceWith("getType", "org.jetbrains.kotlin.resolve.calls.util.getCall"),
|
||||
level = DeprecationLevel.ERROR
|
||||
@IDEAPluginsCompatibilityAPI(
|
||||
IDEAPlatforms._213, // I'm not sure about 212 and 211 AS -- didn't check them
|
||||
message = "Use org.jetbrains.kotlin.resolve.calls.util.getCall instead.",
|
||||
plugins = "Android in IDEA"
|
||||
)
|
||||
fun KtElement.getCall(context: BindingContext): Call? = getCall(context)
|
||||
|
||||
@Deprecated(
|
||||
"Use org.jetbrains.kotlin.resolve.calls.util.getCalleeExpressionIfAny instead.",
|
||||
ReplaceWith("getCalleeExpressionIfAny", "org.jetbrains.kotlin.resolve.calls.util.getCalleeExpressionIfAny"),
|
||||
level = DeprecationLevel.ERROR
|
||||
// TODO: find what IDEA's used it
|
||||
@IDEAPluginsCompatibilityAPI(
|
||||
message = "Use org.jetbrains.kotlin.resolve.calls.util.getCalleeExpressionIfAny instead."
|
||||
)
|
||||
fun KtElement?.getCalleeExpressionIfAny(): KtExpression? = getCalleeExpressionIfAny()
|
||||
|
||||
@Deprecated(
|
||||
"Use org.jetbrains.kotlin.resolve.calls.util.createLookupLocation instead.",
|
||||
ReplaceWith("createLookupLocation", "org.jetbrains.kotlin.resolve.calls.util.createLookupLocation"),
|
||||
level = DeprecationLevel.ERROR
|
||||
// TODO: find what IDEA's used it
|
||||
@IDEAPluginsCompatibilityAPI(
|
||||
message = "Use org.jetbrains.kotlin.resolve.calls.util.createLookupLocation instead."
|
||||
)
|
||||
fun Call.createLookupLocation(): KotlinLookupLocation = createLookupLocation()
|
||||
|
||||
@Deprecated(
|
||||
"Use org.jetbrains.kotlin.resolve.calls.util.createLookupLocation instead.",
|
||||
ReplaceWith("createLookupLocation", "org.jetbrains.kotlin.resolve.calls.util.createLookupLocation"),
|
||||
level = DeprecationLevel.ERROR
|
||||
// TODO: find what IDEA's used it
|
||||
@IDEAPluginsCompatibilityAPI(
|
||||
message = "Use org.jetbrains.kotlin.resolve.calls.util.createLookupLocation instead."
|
||||
)
|
||||
fun KtExpression.createLookupLocation(): KotlinLookupLocation? = createLookupLocation()
|
||||
|
||||
@Deprecated(
|
||||
"Use org.jetbrains.kotlin.resolve.calls.util.getValueArgumentForExpression instead.",
|
||||
ReplaceWith("getValueArgumentForExpression", "org.jetbrains.kotlin.resolve.calls.util.getValueArgumentForExpression"),
|
||||
level = DeprecationLevel.ERROR
|
||||
@IDEAPluginsCompatibilityAPI(
|
||||
IDEAPlatforms._213, // I'm not sure about 212 and 211 AS -- didn't check them
|
||||
message = "Use org.jetbrains.kotlin.resolve.calls.util.getValueArgumentForExpression instead.",
|
||||
plugins = "Android in IDEA"
|
||||
)
|
||||
fun Call.getValueArgumentForExpression(expression: KtExpression): ValueArgument? = getValueArgumentForExpression(expression)
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.utils
|
||||
|
||||
import kotlin.annotation.AnnotationTarget.*
|
||||
|
||||
/**
|
||||
* AS 211-based, IU211 or IC211 is the same _211 key.
|
||||
*
|
||||
* Usage in 213 platform means, that there was a **released** IDEA build or plugin on plugin marketplace compatible with
|
||||
* `213.*` platform that has used this API. If you found a usage in the IDEA and removed it usage before the first official release of the
|
||||
* corresponding platform it is considered as "not used" in this platform. In other words, if API was used in 221 EAP's
|
||||
* or even 221 RC but not in the 221 release -- then API don't have the 221 usage.
|
||||
*/
|
||||
enum class IDEAPlatforms {
|
||||
_211,
|
||||
_212,
|
||||
_213,
|
||||
_221,
|
||||
_222,
|
||||
_223
|
||||
}
|
||||
|
||||
/**
|
||||
* This annotation is created to handle the following situation:
|
||||
* Sometimes IDE plugins are using some API from Kotlin plugin. But it is known that Kotlin plugin includes some parts of
|
||||
* the kotlin compiler. It means, that sometimes the IDE plugins are using API from kotlin compiler itself.
|
||||
* Also, we are providing updates of the Kotlin plugin with the new kotlin front-end inside.
|
||||
* But it also means, that because of such update some third-party plugins could be broken, because they have been using the API
|
||||
* from kotlin compiler that was removed or changed in the new version of the compiler.
|
||||
*
|
||||
* To prevent that we have some teamcity configuration that are checking such compatibility with all the plugins published into plugin side.
|
||||
* So, once we detected, that some API was broken, we should return corresponding API in the compiler and mark it.
|
||||
* Exactly for these usages this annotation should be used.
|
||||
*
|
||||
* List of IDEA platforms is needed to be able to remove the API completely at some point, once we'll stop support of the corresponding
|
||||
* IDEA platform.
|
||||
*
|
||||
* Instead of that we could use just Deprecation annotation with level Error, because it also preserves the binary compatibility and
|
||||
* enforce third-party plugin migrate to the new API, but unfortunately it isn't always possible. With OptIn Annotation that is more
|
||||
* flexible. And yes, please use Opt-in mechanic only as a last reserve.
|
||||
*
|
||||
* One of the legit use-cases for OptIn usage is the following:
|
||||
* Sometimes third-party plugins sources located inside IDEA monorepo. And in kt-*- branches we don't want to change the sources outside
|
||||
* the kotlin plugin, because it is incorrect. So instead of that we could add the corresponding OptIn in the corresponding module where
|
||||
* old API is used and **remove** such usages in the IDEA master.
|
||||
*
|
||||
* P.S. usedIn is declared as first parameter to force its usage -- without it is easy enough forget about it and declare only message
|
||||
*
|
||||
* [usedIn] see description for [IDEAPlatforms]
|
||||
* [message] -- you could add details what API should be used instead
|
||||
* [plugins] -- if you want, you could mention what IDEA plugins used these APIs. It is not mandatory, but sometimes could be helpful.
|
||||
*/
|
||||
@Target(CLASS, ANNOTATION_CLASS, PROPERTY, FIELD, CONSTRUCTOR, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER, TYPEALIAS)
|
||||
@RequiresOptIn("This API will be removed from the Kotlin compiler, you shouldn't use it", level = RequiresOptIn.Level.ERROR)
|
||||
annotation class IDEAPluginsCompatibilityAPI(vararg val usedIn: IDEAPlatforms, val message: String, val plugins: String = "")
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.utils.addToStdlib
|
||||
|
||||
import org.jetbrains.kotlin.utils.IDEAPlatforms
|
||||
import org.jetbrains.kotlin.utils.IDEAPluginsCompatibilityAPI
|
||||
import java.lang.reflect.Modifier
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
@@ -99,10 +101,12 @@ fun String.indexOfOrNull(char: Char, startIndex: Int = 0, ignoreCase: Boolean =
|
||||
fun String.lastIndexOfOrNull(char: Char, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int? =
|
||||
lastIndexOf(char, startIndex, ignoreCase).takeIf { it >= 0 }
|
||||
|
||||
@Deprecated(
|
||||
@IDEAPluginsCompatibilityAPI(
|
||||
IDEAPlatforms._211,
|
||||
IDEAPlatforms._212,
|
||||
IDEAPlatforms._213,
|
||||
message = "Use firstNotNullOfOrNull from stdlib instead",
|
||||
replaceWith = ReplaceWith("firstNotNullOfOrNull(transform)"),
|
||||
level = DeprecationLevel.ERROR
|
||||
plugins = "Android plugin in the IDEA, kotlin-ultimate.kotlin-ocswift"
|
||||
)
|
||||
inline fun <T, R : Any> Iterable<T>.firstNotNullResult(transform: (T) -> R?): R? {
|
||||
for (element in this) {
|
||||
@@ -112,6 +116,21 @@ inline fun <T, R : Any> Iterable<T>.firstNotNullResult(transform: (T) -> R?): R?
|
||||
return null
|
||||
}
|
||||
|
||||
@IDEAPluginsCompatibilityAPI(
|
||||
IDEAPlatforms._211,
|
||||
IDEAPlatforms._212,
|
||||
IDEAPlatforms._213,
|
||||
message = "Use firstNotNullOfOrNull from stdlib instead",
|
||||
plugins = "Android plugin in the IDEA"
|
||||
)
|
||||
inline fun <T, R : Any> Array<T>.firstNotNullResult(transform: (T) -> R?): R? {
|
||||
for (element in this) {
|
||||
val result = transform(element)
|
||||
if (result != null) return result
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
inline fun <T> Iterable<T>.sumByLong(selector: (T) -> Long): Long {
|
||||
var sum: Long = 0
|
||||
for (element in this) {
|
||||
|
||||
Reference in New Issue
Block a user