[FIR] Move check for INSTANCE_ACCESS_BEFORE_SUPER_CALL from resolution stage to checker

^KT-48870
This commit is contained in:
Dmitriy Novozhilov
2023-06-07 13:31:28 +03:00
committed by Space Team
parent 4a501a257e
commit c745ef09d1
25 changed files with 290 additions and 40 deletions
@@ -1,6 +1,6 @@
FILE: instanceAccessBeforeSuperCall.kt
public final class A : R|kotlin/Any| {
public constructor(x: R|kotlin/Int| = this@R|/A|.R|/A.getSomeInt<Inapplicable(RESOLVED_WITH_ERROR): /A.getSomeInt>#|(), other: R|A| = this@R|/A|, header: R|kotlin/String| = this@R|/A|.R|/A.keker<Inapplicable(RESOLVED_WITH_ERROR): /A.keker>#|): R|A| {
public constructor(x: R|kotlin/Int| = R|A|this@R|/A|.R|/A.getSomeInt|(), other: R|A| = this@R|/A|, header: R|kotlin/String| = R|A|this@R|/A|.R|/A.keker|): R|A| {
super<R|kotlin/Any|>()
}
@@ -5,17 +5,17 @@
package org.jetbrains.kotlin.fir.checkers.generator
import org.jetbrains.kotlin.fir.builder.SYNTAX_DIAGNOSTIC_LIST
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.DIAGNOSTICS_LIST
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.JS_DIAGNOSTICS_LIST
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.JVM_DIAGNOSTICS_LIST
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.NATIVE_DIAGNOSTICS_LIST
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.ErrorListDiagnosticListRenderer
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.generateDiagnostics
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.types.FirTypeRef
import java.io.File
import org.jetbrains.kotlin.fir.builder.SYNTAX_DIAGNOSTIC_LIST
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.NATIVE_DIAGNOSTICS_LIST
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.ErrorListDiagnosticListRenderer
fun main(args: Array<String>) {
val arguments = args.toList()
@@ -62,6 +62,7 @@ fun main(args: Array<String>) {
alias<FirDoWhileLoop>("DoWhileLoopChecker")
alias<FirArrayOfCall>("ArrayOfCallChecker")
alias<FirClassReferenceExpression>("ClassReferenceExpressionChecker")
alias<FirInaccessibleReceiverExpression>("InaccessibleReceiverChecker")
}
val declarationPackage = "$basePackage.checkers.declaration"
@@ -77,6 +77,8 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
get() = _arrayOfCallCheckers
override val classReferenceExpressionCheckers: Set<FirClassReferenceExpressionChecker>
get() = _classReferenceExpressionCheckers
override val inaccessibleReceiverCheckers: Set<FirInaccessibleReceiverChecker>
get() = _inaccessibleReceiverCheckers
private val _basicExpressionCheckers: MutableSet<FirBasicExpressionChecker> = mutableSetOf()
private val _qualifiedAccessExpressionCheckers: MutableSet<FirQualifiedAccessExpressionChecker> = mutableSetOf()
@@ -110,6 +112,7 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
private val _doWhileLoopCheckers: MutableSet<FirDoWhileLoopChecker> = mutableSetOf()
private val _arrayOfCallCheckers: MutableSet<FirArrayOfCallChecker> = mutableSetOf()
private val _classReferenceExpressionCheckers: MutableSet<FirClassReferenceExpressionChecker> = mutableSetOf()
private val _inaccessibleReceiverCheckers: MutableSet<FirInaccessibleReceiverChecker> = mutableSetOf()
@CheckersComponentInternal
fun register(checkers: ExpressionCheckers) {
@@ -145,5 +148,6 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
_doWhileLoopCheckers += checkers.doWhileLoopCheckers
_arrayOfCallCheckers += checkers.arrayOfCallCheckers
_classReferenceExpressionCheckers += checkers.classReferenceExpressionCheckers
_inaccessibleReceiverCheckers += checkers.inaccessibleReceiverCheckers
}
}
@@ -49,6 +49,7 @@ abstract class ExpressionCheckers {
open val doWhileLoopCheckers: Set<FirDoWhileLoopChecker> = emptySet()
open val arrayOfCallCheckers: Set<FirArrayOfCallChecker> = emptySet()
open val classReferenceExpressionCheckers: Set<FirClassReferenceExpressionChecker> = emptySet()
open val inaccessibleReceiverCheckers: Set<FirInaccessibleReceiverChecker> = emptySet()
@CheckersComponentInternal internal val allBasicExpressionCheckers: Set<FirBasicExpressionChecker> by lazy { basicExpressionCheckers }
@CheckersComponentInternal internal val allQualifiedAccessExpressionCheckers: Set<FirQualifiedAccessExpressionChecker> by lazy { qualifiedAccessExpressionCheckers + basicExpressionCheckers }
@@ -82,4 +83,5 @@ abstract class ExpressionCheckers {
@CheckersComponentInternal internal val allDoWhileLoopCheckers: Set<FirDoWhileLoopChecker> by lazy { doWhileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allArrayOfCallCheckers: Set<FirArrayOfCallChecker> by lazy { arrayOfCallCheckers + basicExpressionCheckers + callCheckers }
@CheckersComponentInternal internal val allClassReferenceExpressionCheckers: Set<FirClassReferenceExpressionChecker> by lazy { classReferenceExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allInaccessibleReceiverCheckers: Set<FirInaccessibleReceiverChecker> by lazy { inaccessibleReceiverCheckers + basicExpressionCheckers }
}
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.expressions.FirElvisExpression
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
import org.jetbrains.kotlin.fir.expressions.FirInaccessibleReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirIntegerLiteralOperatorCall
import org.jetbrains.kotlin.fir.expressions.FirLoop
import org.jetbrains.kotlin.fir.expressions.FirLoopJump
@@ -75,3 +76,4 @@ typealias FirThrowExpressionChecker = FirExpressionChecker<FirThrowExpression>
typealias FirDoWhileLoopChecker = FirExpressionChecker<FirDoWhileLoop>
typealias FirArrayOfCallChecker = FirExpressionChecker<FirArrayOfCall>
typealias FirClassReferenceExpressionChecker = FirExpressionChecker<FirClassReferenceExpression>
typealias FirInaccessibleReceiverChecker = FirExpressionChecker<FirInaccessibleReceiverExpression>
@@ -162,4 +162,9 @@ object CommonExpressionCheckers : ExpressionCheckers() {
get() = setOf(
FirUnsupportedArrayLiteralChecker
)
override val inaccessibleReceiverCheckers: Set<FirInaccessibleReceiverChecker>
get() = setOf(
FirReceiverAccessBeforeSuperCallChecker,
)
}
@@ -0,0 +1,23 @@
/*
* Copyright 2010-2023 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.fir.analysis.checkers.expression
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.expressions.FirInaccessibleReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
object FirReceiverAccessBeforeSuperCallChecker : FirInaccessibleReceiverChecker() {
override fun check(expression: FirInaccessibleReceiverExpression, context: CheckerContext, reporter: DiagnosticReporter) {
val containingCall = context.qualifiedAccessOrAssignmentsOrAnnotationCalls.last() as FirQualifiedAccessExpression
containingCall.run {
require(expression == dispatchReceiver || expression == extensionReceiver || expression in contextReceiverArguments)
}
reporter.reportOn(containingCall.calleeReference.source, FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL, "<this>", context)
}
}
@@ -5,14 +5,14 @@
package org.jetbrains.kotlin.fir.analysis.collectors.components
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.CheckersComponentInternal
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirExpressionChecker
import org.jetbrains.kotlin.fir.analysis.checkersComponent
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.expressions.*
@OptIn(CheckersComponentInternal::class)
@@ -83,6 +83,13 @@ class ExpressionCheckersDiagnosticComponent(
checkers.allThisReceiverExpressionCheckers.check(thisReceiverExpression, data)
}
override fun visitInaccessibleReceiverExpression(
inaccessibleReceiverExpression: FirInaccessibleReceiverExpression,
data: CheckerContext,
) {
checkers.allInaccessibleReceiverCheckers.check(inaccessibleReceiverExpression, data)
}
override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: CheckerContext) {
checkers.allResolvedQualifierCheckers.check(resolvedQualifier, data)
}
@@ -302,8 +302,6 @@ private fun mapInapplicableCandidateError(
isError = rootCause.isError
)
is InaccessibleReceiver -> FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL.createOn(source, "<this>")
else -> genericDiagnostic
}
}.distinct()
@@ -632,6 +632,19 @@ class Fir2IrVisitor(
return visitQualifiedAccessExpression(thisReceiverExpression, data)
}
override fun visitInaccessibleReceiverExpression(
inaccessibleReceiverExpression: FirInaccessibleReceiverExpression,
data: Any?,
): IrElement {
return inaccessibleReceiverExpression.convertWithOffsets { startOffset, endOffset ->
IrErrorExpressionImpl(
startOffset, endOffset,
inaccessibleReceiverExpression.typeRef.toIrType(),
"Receiver is inaccessible"
)
}
}
override fun visitSmartCastExpression(smartCastExpression: FirSmartCastExpression, data: Any?): IrElement {
// Generate the expression with the original type and then cast it to the smart cast type.
val value = convertToIrExpression(smartCastExpression.originalExpression)
@@ -11,7 +11,11 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.copyWithNewSourceKind
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.FirCheckNotNullCall
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
import org.jetbrains.kotlin.fir.expressions.arguments
import org.jetbrains.kotlin.fir.expressions.builder.buildInaccessibleReceiverExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildSmartCastExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildThisReceiverExpression
import org.jetbrains.kotlin.fir.references.builder.buildImplicitThisReference
@@ -97,6 +101,7 @@ sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>(
protected val scopeSession: ScopeSession,
private val mutable: Boolean,
val contextReceiverNumber: Int = -1,
private val inaccessibleReceiver: Boolean = false
) : ReceiverValue {
final override var type: ConeKotlinType = type
private set
@@ -118,7 +123,8 @@ sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>(
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope? = implicitScope
private val originalReceiverExpression: FirThisReceiverExpression = receiverExpression(boundSymbol, type, contextReceiverNumber)
private val originalReceiverExpression: FirExpression =
receiverExpression(boundSymbol, type, contextReceiverNumber, inaccessibleReceiver)
final override var receiverExpression: FirExpression = originalReceiverExpression
private set
@@ -128,7 +134,7 @@ sealed class ImplicitReceiverValue<S : FirBasedSymbol<*>>(
@Deprecated(level = DeprecationLevel.ERROR, message = "Builder inference should not modify implicit receivers. KT-54708")
fun updateTypeInBuilderInference(type: ConeKotlinType) {
this.type = type
receiverExpression = receiverExpression(boundSymbol, type, contextReceiverNumber)
receiverExpression = receiverExpression(boundSymbol, type, contextReceiverNumber, inaccessibleReceiver)
implicitScope = type.scope(
useSiteSession = useSiteSession,
scopeSession = scopeSession,
@@ -176,18 +182,28 @@ private fun receiverExpression(
symbol: FirBasedSymbol<*>,
type: ConeKotlinType,
contextReceiverNumber: Int,
): FirThisReceiverExpression =
buildThisReceiverExpression {
// NB: we can't use `symbol.fir.source` as the source of `this` receiver. For instance, if this is an implicit receiver for a class,
// the entire class itself will be set as a source. If combined with an implicit type operation, a certain assertion, like null
// check assertion, will retrieve source as an assertion message, which is literally the entire class (!).
calleeReference = buildImplicitThisReference {
boundSymbol = symbol
this.contextReceiverNumber = contextReceiverNumber
}
typeRef = type.toFirResolvedTypeRef()
isImplicit = true
inaccessibleReceiver: Boolean
): FirExpression {
// NB: we can't use `symbol.fir.source` as the source of `this` receiver. For instance, if this is an implicit receiver for a class,
// the entire class itself will be set as a source. If combined with an implicit type operation, a certain assertion, like null
// check assertion, will retrieve source as an assertion message, which is literally the entire class (!).
val calleeReference = buildImplicitThisReference {
boundSymbol = symbol
this.contextReceiverNumber = contextReceiverNumber
}
val typeRef = type.toFirResolvedTypeRef()
return when (inaccessibleReceiver) {
false -> buildThisReceiverExpression {
this.calleeReference = calleeReference
this.typeRef = typeRef
isImplicit = true
}
true -> buildInaccessibleReceiverExpression {
this.calleeReference = calleeReference
this.typeRef = typeRef
}
}
}
class ImplicitDispatchReceiverValue(
boundSymbol: FirClassSymbol<*>,
@@ -233,7 +249,7 @@ class InaccessibleImplicitReceiverValue(
useSiteSession: FirSession,
scopeSession: ScopeSession,
mutable: Boolean = true,
) : ImplicitReceiverValue<FirClassSymbol<*>>(boundSymbol, type, useSiteSession, scopeSession, mutable) {
) : ImplicitReceiverValue<FirClassSymbol<*>>(boundSymbol, type, useSiteSession, scopeSession, mutable, inaccessibleReceiver = true) {
override fun createSnapshot(): ImplicitReceiverValue<FirClassSymbol<*>> {
return InaccessibleImplicitReceiverValue(boundSymbol, type, useSiteSession, scopeSession, false)
}
@@ -24,7 +24,6 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
LowerPriorityIfDynamic,
ConstraintSystemForks,
CheckIncompatibleTypeVariableUpperBounds,
InaccessibleReceiverResolutionStage,
)
object SyntheticSelect : CallKind(
@@ -60,7 +59,6 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
LowerPriorityIfDynamic,
ConstraintSystemForks,
CheckIncompatibleTypeVariableUpperBounds,
InaccessibleReceiverResolutionStage,
)
object DelegatingConstructorCall : CallKind(
@@ -96,7 +94,6 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
CheckIncompatibleTypeVariableUpperBounds,
ProcessDynamicExtensionAnnotation,
LowerPriorityIfDynamic,
InaccessibleReceiverResolutionStage,
)
object SyntheticIdForCallableReferencesResolution : CallKind(
@@ -712,14 +712,3 @@ internal object ConstraintSystemForks : ResolutionStage() {
}
}
}
internal object InaccessibleReceiverResolutionStage : ResolutionStage() {
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
if (
candidate.dispatchReceiverValue is InaccessibleImplicitReceiverValue ||
candidate.givenExtensionReceiverOptions.any { it is InaccessibleImplicitReceiverValue }
) {
sink.yieldDiagnostic(InaccessibleReceiver)
}
}
}
@@ -141,5 +141,3 @@ class NoApplicableValueForContextReceiver(
class AmbiguousValuesForContextReceiverParameter(
val expectedContextReceiverType: ConeKotlinType,
) : ResolutionDiagnostic(INAPPLICABLE)
object InaccessibleReceiver : ResolutionDiagnostic(RESOLVED_WITH_ERROR)
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2023 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.fir.expressions
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.FirThisReference
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.*
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
abstract class FirInaccessibleReceiverExpression : FirExpression(), FirResolvable {
abstract override val source: KtSourceElement?
abstract override val typeRef: FirTypeRef
abstract override val annotations: List<FirAnnotation>
abstract override val calleeReference: FirThisReference
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitInaccessibleReceiverExpression(this, data)
@Suppress("UNCHECKED_CAST")
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformInaccessibleReceiverExpression(this, data) as E
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
abstract fun replaceCalleeReference(newCalleeReference: FirThisReference)
abstract override fun replaceCalleeReference(newCalleeReference: FirReference)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirInaccessibleReceiverExpression
abstract override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirInaccessibleReceiverExpression
}
@@ -0,0 +1,53 @@
/*
* Copyright 2010-2023 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.
*/
@file:Suppress("DuplicatedCode")
package org.jetbrains.kotlin.fir.expressions.builder
import kotlin.contracts.*
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirInaccessibleReceiverExpression
import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder
import org.jetbrains.kotlin.fir.expressions.impl.FirInaccessibleReceiverExpressionImpl
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.FirThisReference
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.*
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
@FirBuilderDsl
class FirInaccessibleReceiverExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBuilder {
override var source: KtSourceElement? = null
override lateinit var typeRef: FirTypeRef
override val annotations: MutableList<FirAnnotation> = mutableListOf()
lateinit var calleeReference: FirThisReference
override fun build(): FirInaccessibleReceiverExpression {
return FirInaccessibleReceiverExpressionImpl(
source,
typeRef,
annotations.toMutableOrEmpty(),
calleeReference,
)
}
}
@OptIn(ExperimentalContracts::class)
inline fun buildInaccessibleReceiverExpression(init: FirInaccessibleReceiverExpressionBuilder.() -> Unit): FirInaccessibleReceiverExpression {
contract {
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
}
return FirInaccessibleReceiverExpressionBuilder().apply(init).build()
}
@@ -0,0 +1,70 @@
/*
* Copyright 2010-2023 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.
*/
@file:Suppress("DuplicatedCode")
package org.jetbrains.kotlin.fir.expressions.impl
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirInaccessibleReceiverExpression
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.FirThisReference
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.fir.MutableOrEmptyList
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
internal class FirInaccessibleReceiverExpressionImpl(
override val source: KtSourceElement?,
override var typeRef: FirTypeRef,
override var annotations: MutableOrEmptyList<FirAnnotation>,
override var calleeReference: FirThisReference,
) : FirInaccessibleReceiverExpression() {
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
typeRef.accept(visitor, data)
annotations.forEach { it.accept(visitor, data) }
calleeReference.accept(visitor, data)
}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirInaccessibleReceiverExpressionImpl {
typeRef = typeRef.transform(transformer, data)
transformAnnotations(transformer, data)
transformCalleeReference(transformer, data)
return this
}
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirInaccessibleReceiverExpressionImpl {
annotations.transformInplace(transformer, data)
return this
}
override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirInaccessibleReceiverExpressionImpl {
calleeReference = calleeReference.transform(transformer, data)
return this
}
override fun replaceTypeRef(newTypeRef: FirTypeRef) {
typeRef = newTypeRef
}
override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) {
annotations = newAnnotations.toMutableOrEmpty()
}
override fun replaceCalleeReference(newCalleeReference: FirThisReference) {
calleeReference = newCalleeReference
}
override fun replaceCalleeReference(newCalleeReference: FirReference) {
require(newCalleeReference is FirThisReference)
replaceCalleeReference(newCalleeReference)
}
}
@@ -109,6 +109,7 @@ import org.jetbrains.kotlin.fir.expressions.FirMultiDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.FirComponentCall
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirInaccessibleReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
@@ -109,6 +109,7 @@ import org.jetbrains.kotlin.fir.expressions.FirMultiDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.FirComponentCall
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirInaccessibleReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
@@ -109,6 +109,7 @@ import org.jetbrains.kotlin.fir.expressions.FirMultiDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.FirComponentCall
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirInaccessibleReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
@@ -578,6 +579,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformElement(thisReceiverExpression, data)
}
open fun transformInaccessibleReceiverExpression(inaccessibleReceiverExpression: FirInaccessibleReceiverExpression, data: D): FirStatement {
return transformElement(inaccessibleReceiverExpression, data)
}
open fun transformSmartCastExpression(smartCastExpression: FirSmartCastExpression, data: D): FirStatement {
return transformElement(smartCastExpression, data)
}
@@ -1182,6 +1187,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformThisReceiverExpression(thisReceiverExpression, data)
}
final override fun visitInaccessibleReceiverExpression(inaccessibleReceiverExpression: FirInaccessibleReceiverExpression, data: D): FirStatement {
return transformInaccessibleReceiverExpression(inaccessibleReceiverExpression, data)
}
final override fun visitSmartCastExpression(smartCastExpression: FirSmartCastExpression, data: D): FirStatement {
return transformSmartCastExpression(smartCastExpression, data)
}
@@ -109,6 +109,7 @@ import org.jetbrains.kotlin.fir.expressions.FirMultiDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.FirComponentCall
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirInaccessibleReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
@@ -371,6 +372,8 @@ abstract class FirVisitor<out R, in D> {
open fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression, data: D): R = visitElement(thisReceiverExpression, data)
open fun visitInaccessibleReceiverExpression(inaccessibleReceiverExpression: FirInaccessibleReceiverExpression, data: D): R = visitElement(inaccessibleReceiverExpression, data)
open fun visitSmartCastExpression(smartCastExpression: FirSmartCastExpression, data: D): R = visitElement(smartCastExpression, data)
open fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: D): R = visitElement(safeCallExpression, data)
@@ -109,6 +109,7 @@ import org.jetbrains.kotlin.fir.expressions.FirMultiDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.FirComponentCall
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirInaccessibleReceiverExpression
import org.jetbrains.kotlin.fir.expressions.FirSmartCastExpression
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
@@ -577,6 +578,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitElement(thisReceiverExpression)
}
open fun visitInaccessibleReceiverExpression(inaccessibleReceiverExpression: FirInaccessibleReceiverExpression) {
visitElement(inaccessibleReceiverExpression)
}
open fun visitSmartCastExpression(smartCastExpression: FirSmartCastExpression) {
visitElement(smartCastExpression)
}
@@ -1181,6 +1186,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitThisReceiverExpression(thisReceiverExpression)
}
final override fun visitInaccessibleReceiverExpression(inaccessibleReceiverExpression: FirInaccessibleReceiverExpression, data: Nothing?) {
visitInaccessibleReceiverExpression(inaccessibleReceiverExpression)
}
final override fun visitSmartCastExpression(smartCastExpression: FirSmartCastExpression, data: Nothing?) {
visitSmartCastExpression(smartCastExpression)
}
@@ -133,6 +133,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
val componentCall by element(Expression, functionCall)
val callableReferenceAccess by element(Expression, qualifiedAccessExpression)
val thisReceiverExpression by element(Expression, qualifiedAccessExpression)
val inaccessibleReceiverExpression by element(Expression, expression, resolvable)
val smartCastExpression by element(Expression, expression)
val safeCallExpression by element(Expression, expression)
@@ -666,7 +666,8 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
"FirReceiverParameterImpl",
"FirClassReferenceExpressionImpl",
"FirGetClassCallImpl",
"FirSmartCastExpressionImpl"
"FirSmartCastExpressionImpl",
"FirInaccessibleReceiverExpressionImpl"
)
configureFieldInAllImplementations(
field = "typeRef",
@@ -727,6 +727,10 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+booleanField("isImplicit")
}
inaccessibleReceiverExpression.configure {
+field("calleeReference", thisReference)
}
whenExpression.configure {
+field("subject", expression, nullable = true).withTransform()
+field("subjectVariable", variable.withArgs("E" to "*"), nullable = true)