FIR: implementation of delegateProvider in delegate resolve

This commit is contained in:
Mikhail Glukhikh
2019-07-19 15:46:16 +03:00
parent 213f951da3
commit d32e5065c5
21 changed files with 278 additions and 66 deletions
@@ -570,9 +570,10 @@ internal fun KtExpression?.generateAssignment(
}
}
internal fun FirModifiableAccessorsOwner.generateAccessorsByDelegate(session: FirSession, member: Boolean) {
internal fun FirModifiableAccessorsOwner.generateAccessorsByDelegate(session: FirSession, member: Boolean, stubMode: Boolean) {
val variable = this as FirVariable<*>
val delegateFieldSymbol = delegateFieldSymbol ?: return
val delegate = delegate as? FirWrappedDelegateExpressionImpl ?: return
fun delegateAccess() = FirQualifiedAccessExpressionImpl(session, null).apply {
calleeReference = FirDelegateFieldReferenceImpl(session, null, delegateFieldSymbol)
}
@@ -588,6 +589,13 @@ internal fun FirModifiableAccessorsOwner.generateAccessorsByDelegate(session: Fi
typeRef = FirImplicitKPropertyTypeRef(session, null, ConeStarProjection)
}
delegate.delegateProvider = if (stubMode) FirExpressionStub(session, null) else FirFunctionCallImpl(session, null).apply {
explicitReceiver = delegate.expression
calleeReference = FirSimpleNamedReference(session, null, PROVIDE_DELEGATE)
arguments += thisRef()
arguments += propertyRef()
}
if (stubMode) return
getter = (getter as? FirPropertyAccessorImpl)
?: FirPropertyAccessorImpl(session, null, true, Visibilities.UNKNOWN, FirImplicitTypeRefImpl(session, null)).apply Accessor@{
body = FirSingleExpressionBlock(
@@ -631,4 +639,5 @@ internal fun FirModifiableAccessorsOwner.generateAccessorsByDelegate(session: Fi
private val GET_VALUE = Name.identifier("getValue")
private val SET_VALUE = Name.identifier("setValue")
private val PROVIDE_DELEGATE = Name.identifier("provideDelegate")
private val DELEGATED_SETTER_PARAM = Name.special("<set-?>")
@@ -70,7 +70,7 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
}
private inner class Visitor : KtVisitor<FirElement, Unit>() {
private inline fun <reified R : FirElement> KtElement?. convertSafe(): R? =
private inline fun <reified R : FirElement> KtElement?.convertSafe(): R? =
this?.accept(this@Visitor, Unit) as? R
private inline fun <reified R : FirElement> KtElement.convert(): R =
@@ -774,6 +774,7 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
val initializer = if (property.hasInitializer()) {
{ property.initializer }.toFirExpression("Should have initializer")
} else null
val delegateExpression by lazy { property.delegate?.expression }
val firProperty = if (property.isLocal) {
FirVariableImpl(
session,
@@ -782,9 +783,14 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
propertyType,
isVar,
initializer,
delegate = property.delegate?.expression?.toFirExpression("Incorrect delegate expression")
delegate = delegateExpression?.let {
FirWrappedDelegateExpressionImpl(
session, it,
it.toFirExpression("Incorrect delegate expression")
)
}
).apply {
generateAccessorsByDelegate(this@RawFirBuilder.session, member = false)
generateAccessorsByDelegate(this@RawFirBuilder.session, member = false, stubMode = stubMode)
}
} else {
FirMemberPropertyImpl(
@@ -804,13 +810,16 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
isVar,
initializer,
if (property.hasDelegate()) {
{ property.delegate?.expression }.toFirExpression("Should have delegate")
FirWrappedDelegateExpressionImpl(
session, if (stubMode) null else delegateExpression,
{ delegateExpression }.toFirExpression("Should have delegate")
)
} else null
).apply {
property.extractTypeParametersTo(this)
getter = property.getter.toFirPropertyAccessor(property, propertyType, isGetter = true)
setter = if (isVar) property.setter.toFirPropertyAccessor(property, propertyType, isGetter = false) else null
generateAccessorsByDelegate(this@RawFirBuilder.session, member = !property.isTopLevel)
generateAccessorsByDelegate(this@RawFirBuilder.session, member = !property.isTopLevel, stubMode = stubMode)
}
}
property.extractAnnotationsTo(firProperty)
@@ -1063,6 +1063,20 @@ open class FirBodyResolveTransformer(
}
}
override fun transformWrappedDelegateExpression(
wrappedDelegateExpression: FirWrappedDelegateExpression,
data: Any?
): CompositeTransformResult<FirStatement> {
super.transformWrappedDelegateExpression(wrappedDelegateExpression, data)
with(wrappedDelegateExpression) {
val delegateProviderTypeRef = delegateProvider.typeRef
val useDelegateProvider = delegateProviderTypeRef is FirResolvedTypeRef &&
delegateProviderTypeRef !is FirErrorTypeRef &&
delegateProviderTypeRef.type !is ConeKotlinErrorType
return if (useDelegateProvider) delegateProvider.compose() else expression.compose()
}
}
override fun <F : FirVariable<F>> transformVariable(variable: FirVariable<F>, data: Any?): CompositeTransformResult<FirDeclaration> {
variable.transformChildrenWithoutAccessors(this, variable.returnTypeRef)
if (variable.initializer != null) {
@@ -1100,7 +1114,7 @@ open class FirBodyResolveTransformer(
}
override fun transformExpression(expression: FirExpression, data: Any?): CompositeTransformResult<FirStatement> {
if (expression.resultType is FirImplicitTypeRef && expression !is FirWrappedArgumentExpression) {
if (expression.resultType is FirImplicitTypeRef && expression !is FirWrappedExpression) {
val type = FirErrorTypeRefImpl(session, expression.psi, "Type calculating for ${expression::class} is not supported")
expression.resultType = type
}
@@ -0,0 +1,9 @@
class Delegate(val value: String) {
operator fun getValue(thisRef: Any?, property: Any?) = value
}
class DelegateProvider(val value: String) {
operator fun provideDelegate(thisRef: Any?, property: Any?) = Delegate(value)
}
val testTopLevel by DelegateProvider("OK")
@@ -0,0 +1,31 @@
FILE: simpleDelegateProvider.kt
public final class Delegate : R|kotlin/Any| {
public constructor(value: R|kotlin/String|): R|Delegate| {
super<R|kotlin/Any|>()
}
public final val value: R|kotlin/String| = R|<local>/value|
public get(): R|kotlin/String|
public final operator fun getValue(thisRef: R|kotlin/Any|?, property: R|kotlin/Any|?): R|kotlin/String| {
^getValue R|/Delegate.value|
}
}
public final class DelegateProvider : R|kotlin/Any| {
public constructor(value: R|kotlin/String|): R|DelegateProvider| {
super<R|kotlin/Any|>()
}
public final val value: R|kotlin/String| = R|<local>/value|
public get(): R|kotlin/String|
public final operator fun provideDelegate(thisRef: R|kotlin/Any|?, property: R|kotlin/Any|?): R|Delegate| {
^provideDelegate R|/Delegate.Delegate|(R|/DelegateProvider.value|)
}
}
public final val testTopLevel: R|kotlin/String|by R|/DelegateProvider.DelegateProvider|(String(OK)).R|/DelegateProvider.provideDelegate|(Null(null), ::R|/testTopLevel|)
public get(): R|kotlin/String| {
^ D|/testTopLevel|.R|/Delegate.getValue|(Null(null), ::R|/testTopLevel|)
}
@@ -94,6 +94,11 @@ public class FirResolveTestCaseWithStdlibGenerated extends AbstractFirResolveTes
runTest("compiler/fir/resolve/testData/resolve/stdlib/reflectionClass.kt");
}
@TestMetadata("simpleDelegateProvider.kt")
public void testSimpleDelegateProvider() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/simpleDelegateProvider.kt");
}
@TestMetadata("simpleDelegatedToMap.kt")
public void testSimpleDelegatedToMap() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/simpleDelegatedToMap.kt");
@@ -625,6 +625,10 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
print("${constExpression.kind}(${constExpression.value})")
}
override fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression) {
wrappedDelegateExpression.expression.accept(this)
}
override fun visitNamedArgumentExpression(namedArgumentExpression: FirNamedArgumentExpression) {
print(namedArgumentExpression.name)
print(" = ")
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.declarations.impl
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirVariable
@@ -13,24 +13,13 @@ import org.jetbrains.kotlin.fir.visitors.FirVisitor
abstract class FirWrappedArgumentExpression(
session: FirSession,
psi: PsiElement?
) : FirExpression(session, psi) {
abstract val expression: FirExpression
) : FirWrappedExpression(session, psi) {
open val isSpread: Boolean
get() = false
override val typeRef: FirTypeRef
get() = expression.typeRef
override fun replaceTypeRef(newTypeRef: FirTypeRef) {
throw AssertionError("We should not try to replace type reference in ${this::class}")
}
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitWrappedArgumentExpression(this, data)
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
expression.accept(visitor, data)
super.acceptChildren(visitor, data)
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2019 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 com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.FirVisitor
abstract class FirWrappedDelegateExpression(
session: FirSession,
psi: PsiElement?
) : FirWrappedExpression(session, psi) {
abstract val delegateProvider: FirExpression
override val typeRef: FirTypeRef
get() = expression.typeRef
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R {
return visitor.visitWrappedDelegateExpression(this, data)
}
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
delegateProvider.accept(visitor, data)
super.acceptChildren(visitor, data)
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2019 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 com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.FirVisitor
abstract class FirWrappedExpression(
session: FirSession,
psi: PsiElement?
) : FirExpression(session, psi) {
abstract val expression: FirExpression
override fun replaceTypeRef(newTypeRef: FirTypeRef) {
throw AssertionError("We should not try to replace type reference in ${this::class}")
}
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitWrappedExpression(this, data)
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
expression.accept(visitor, data)
super.acceptChildren(visitor, data)
}
}
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2019 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.impl
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression
import org.jetbrains.kotlin.fir.transformSingle
import org.jetbrains.kotlin.fir.visitors.FirTransformer
class FirWrappedDelegateExpressionImpl(
session: FirSession,
psi: PsiElement?,
override var expression: FirExpression
) : FirWrappedDelegateExpression(session, psi) {
override lateinit var delegateProvider: FirExpression
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
expression = expression.transformSingle(transformer, data)
delegateProvider = delegateProvider.transformSingle(transformer, data)
return super.transformChildren(transformer, data)
}
}
@@ -320,8 +320,12 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
return transformUnknownTypeExpression(whenSubjectExpression, data)
}
open fun transformWrappedExpression(wrappedExpression: FirWrappedExpression, data: D): CompositeTransformResult<FirStatement> {
return transformExpression(wrappedExpression, data)
}
open fun transformWrappedArgumentExpression(wrappedArgumentExpression: FirWrappedArgumentExpression, data: D): CompositeTransformResult<FirStatement> {
return transformExpression(wrappedArgumentExpression, data)
return transformWrappedExpression(wrappedArgumentExpression, data)
}
open fun transformLambdaArgumentExpression(lambdaArgumentExpression: FirLambdaArgumentExpression, data: D): CompositeTransformResult<FirStatement> {
@@ -336,6 +340,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
return transformWrappedArgumentExpression(spreadArgumentExpression, data)
}
open fun transformWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression, data: D): CompositeTransformResult<FirStatement> {
return transformWrappedExpression(wrappedDelegateExpression, data)
}
open fun transformClass(klass: FirClass, data: D): CompositeTransformResult<FirStatement> {
return transformStatement(klass, data)
}
@@ -872,6 +880,14 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
return transformWrappedArgumentExpression(wrappedArgumentExpression, data)
}
final override fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression, data: D): CompositeTransformResult<FirElement> {
return transformWrappedDelegateExpression(wrappedDelegateExpression, data)
}
final override fun visitWrappedExpression(wrappedExpression: FirWrappedExpression, data: D): CompositeTransformResult<FirElement> {
return transformWrappedExpression(wrappedExpression, data)
}
final override fun visitElement(element: FirElement, data: D): CompositeTransformResult<FirElement> {
return transformElement(element, data)
}
@@ -320,8 +320,12 @@ abstract class FirVisitor<out R, in D> {
return visitUnknownTypeExpression(whenSubjectExpression, data)
}
open fun visitWrappedExpression(wrappedExpression: FirWrappedExpression, data: D): R {
return visitExpression(wrappedExpression, data)
}
open fun visitWrappedArgumentExpression(wrappedArgumentExpression: FirWrappedArgumentExpression, data: D): R {
return visitExpression(wrappedArgumentExpression, data)
return visitWrappedExpression(wrappedArgumentExpression, data)
}
open fun visitLambdaArgumentExpression(lambdaArgumentExpression: FirLambdaArgumentExpression, data: D): R {
@@ -336,6 +340,10 @@ abstract class FirVisitor<out R, in D> {
return visitWrappedArgumentExpression(spreadArgumentExpression, data)
}
open fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression, data: D): R {
return visitWrappedExpression(wrappedDelegateExpression, data)
}
open fun visitClass(klass: FirClass, data: D): R {
return visitStatement(klass, data)
}
@@ -320,8 +320,12 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitUnknownTypeExpression(whenSubjectExpression, null)
}
open fun visitWrappedExpression(wrappedExpression: FirWrappedExpression) {
visitExpression(wrappedExpression, null)
}
open fun visitWrappedArgumentExpression(wrappedArgumentExpression: FirWrappedArgumentExpression) {
visitExpression(wrappedArgumentExpression, null)
visitWrappedExpression(wrappedArgumentExpression, null)
}
open fun visitLambdaArgumentExpression(lambdaArgumentExpression: FirLambdaArgumentExpression) {
@@ -336,6 +340,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitWrappedArgumentExpression(spreadArgumentExpression, null)
}
open fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression) {
visitWrappedExpression(wrappedDelegateExpression, null)
}
open fun visitClass(klass: FirClass) {
visitStatement(klass, null)
}
@@ -872,6 +880,14 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitWrappedArgumentExpression(wrappedArgumentExpression)
}
final override fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression, data: Nothing?) {
visitWrappedDelegateExpression(wrappedDelegateExpression)
}
final override fun visitWrappedExpression(wrappedExpression: FirWrappedExpression, data: Nothing?) {
visitWrappedExpression(wrappedExpression)
}
final override fun visitElement(element: FirElement, data: Nothing?) {
visitElement(element)
}