[FIR] Don't report DEPRECATION on self-access in delegated property

#KT-60682
This commit is contained in:
Kirill Rakhman
2023-08-25 13:28:13 +02:00
committed by Space Team
parent 411210b520
commit 21f8ba1706
4 changed files with 70 additions and 1 deletions
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtRealSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.config.KotlinCompilerVersion
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
@@ -29,6 +28,7 @@ import org.jetbrains.kotlin.fir.references.resolved
import org.jetbrains.kotlin.fir.resolve.firClassLike
import org.jetbrains.kotlin.fir.resolve.typeAliasForConstructor
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
@@ -51,6 +51,9 @@ object FirDeprecationChecker : FirBasicExpressionChecker() {
val calleeReference = expression.calleeReference ?: return
val resolvedReference = calleeReference.resolved ?: return
val referencedSymbol = resolvedReference.resolvedSymbol
if (expression.isDelegatedPropertySelfAccess(context, referencedSymbol)) return
val source = resolvedReference.source ?: expression.source
if (expression is FirDelegatedConstructorCall) {
@@ -67,6 +70,19 @@ object FirDeprecationChecker : FirBasicExpressionChecker() {
}
}
/** Checks if this is an access to a delegated property inside the delegated property itself.
* Deprecations shouldn't be reported here. */
@OptIn(SymbolInternals::class)
private fun FirStatement.isDelegatedPropertySelfAccess(context: CheckerContext, referencedSymbol: FirBasedSymbol<*>): Boolean {
if (source?.kind != KtFakeSourceElementKind.DelegatedPropertyAccessor) return false
val containers = context.containingDeclarations
val size = containers.size
val fir = referencedSymbol.fir
return containers.getOrNull(size - 1) == fir // For `provideDelegate`, the call will be in the initializer
|| containers.getOrNull(size - 2) == fir // For `getValue`, the call will be in the accessor
}
internal fun reportApiStatusIfNeeded(
source: KtSourceElement?,
referencedSymbol: FirBasedSymbol<*>,
@@ -13,6 +13,15 @@ class Delegate() {
operator fun setValue(instance: Any, property: KProperty<*>, value: Int) {}
}
class Delegate2() {
operator fun getValue(instance: Any, property: KProperty<*>) : Int = 1
operator fun setValue(instance: Any, property: KProperty<*>, value: Int) {}
}
class DelegateProvider() {
operator fun provideDelegate(instance: Any, property: KProperty<*>) = Delegate2()
}
class PropertyHolder {
@Deprecated("text")
val x = 1
@@ -23,6 +32,14 @@ class PropertyHolder {
val valDelegate by <!DEPRECATION!>Delegate<!>()
var varDelegate by <!DEPRECATION, DEPRECATION!>Delegate<!>()
// no deprecation caused by access to itself
@Deprecated("text")
var deprecatedDelegated by Delegate2()
// no deprecation caused by access to itself
@Deprecated("text")
val deprecatedDelegated2 by DelegateProvider()
public val test1: String = ""
@Deprecated("val-getter") get
@@ -13,6 +13,15 @@ class Delegate() {
operator fun setValue(instance: Any, property: KProperty<*>, value: Int) {}
}
class Delegate2() {
operator fun getValue(instance: Any, property: KProperty<*>) : Int = 1
operator fun setValue(instance: Any, property: KProperty<*>, value: Int) {}
}
class DelegateProvider() {
operator fun provideDelegate(instance: Any, property: KProperty<*>) = Delegate2()
}
class PropertyHolder {
@Deprecated("text")
val x = 1
@@ -23,6 +32,14 @@ class PropertyHolder {
val valDelegate by <!DEPRECATION!>Delegate()<!>
var varDelegate by <!DEPRECATION, DEPRECATION!>Delegate()<!>
// no deprecation caused by access to itself
@Deprecated("text")
var deprecatedDelegated by Delegate2()
// no deprecation caused by access to itself
@Deprecated("text")
val deprecatedDelegated2 by DelegateProvider()
public val test1: String = ""
@Deprecated("val-getter") get
@@ -13,8 +13,27 @@ public final class Delegate {
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Delegate2 {
public constructor Delegate2()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final operator fun getValue(/*0*/ instance: kotlin.Any, /*1*/ property: kotlin.reflect.KProperty<*>): kotlin.Int
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final operator fun setValue(/*0*/ instance: kotlin.Any, /*1*/ property: kotlin.reflect.KProperty<*>, /*2*/ value: kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class DelegateProvider {
public constructor DelegateProvider()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final operator fun provideDelegate(/*0*/ instance: kotlin.Any, /*1*/ property: kotlin.reflect.KProperty<*>): Delegate2
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class PropertyHolder {
public constructor PropertyHolder()
@kotlin.Deprecated(message = "text") public final var deprecatedDelegated: kotlin.Int
@kotlin.Deprecated(message = "text") public final val deprecatedDelegated2: kotlin.Int
@kotlin.Deprecated(message = "text") public final var name: kotlin.String
@get:kotlin.Deprecated(message = "val-getter") public final val test1: kotlin.String = ""
@get:kotlin.Deprecated(message = "var-getter") @set:kotlin.Deprecated(message = "var-setter") public final var test2: kotlin.String