FIR: partial implementation of delegate resolve #KT-32217 Fixed

This commit is contained in:
Mikhail Glukhikh
2019-07-11 19:21:11 +03:00
parent 63b7fa70f9
commit 213f951da3
56 changed files with 753 additions and 266 deletions
@@ -12,7 +12,9 @@ import org.jetbrains.kotlin.name.Name
object StandardClassIds {
private val BASE_KOTLIN_PACKAGE = FqName("kotlin")
private val BASE_REFLECT_PACKAGE = BASE_KOTLIN_PACKAGE.child(Name.identifier("reflect"))
private fun String.baseId() = ClassId(BASE_KOTLIN_PACKAGE, Name.identifier(this))
private fun String.reflectId() = ClassId(BASE_REFLECT_PACKAGE, Name.identifier(this))
private fun Name.arrayId() = ClassId(Array.packageFqName, Name.identifier(identifier + Array.shortClassName.identifier))
val Nothing = "Nothing".baseId()
@@ -33,6 +35,8 @@ object StandardClassIds {
val String = "String".baseId()
val KProperty = "KProperty".reflectId()
fun byName(name: String) = name.baseId()
val primitiveArrayTypeByElementType: Map<ClassId, ClassId> = mutableMapOf<ClassId, ClassId>().apply {
@@ -848,7 +848,7 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
}
withIdentLevel {
generate(property.getter)
property.getter?.let { generate(it) }
property.setter?.let { generate(it) }
}
}
@@ -107,7 +107,8 @@ fun FirNamedReference.toSymbol(declarationStorage: Fir2IrDeclarationStorage): Ir
is FirFunctionSymbol<*> -> return callableSymbol.toFunctionSymbol(declarationStorage)
is FirPropertySymbol -> return callableSymbol.toPropertyOrFieldSymbol(declarationStorage)
is FirFieldSymbol -> return callableSymbol.toPropertyOrFieldSymbol(declarationStorage)
is FirBackingFieldSymbol -> return callableSymbol.toPropertyOrFieldSymbol(declarationStorage)
is FirBackingFieldSymbol -> return callableSymbol.toBackingFieldSymbol(declarationStorage)
is FirDelegateFieldSymbol<*> -> return callableSymbol.toBackingFieldSymbol(declarationStorage)
is FirVariableSymbol<*> -> return callableSymbol.toValueSymbol(declarationStorage)
}
}
@@ -130,6 +131,10 @@ fun FirVariableSymbol<*>.toPropertyOrFieldSymbol(declarationStorage: Fir2IrDecla
return declarationStorage.getIrPropertyOrFieldSymbol(this)
}
fun FirVariableSymbol<*>.toBackingFieldSymbol(declarationStorage: Fir2IrDeclarationStorage): IrSymbol {
return declarationStorage.getIrBackingFieldSymbol(this)
}
fun FirVariableSymbol<*>.toValueSymbol(declarationStorage: Fir2IrDeclarationStorage): IrValueSymbol {
return declarationStorage.getIrValueSymbol(this)
}
@@ -541,6 +541,20 @@ class Fir2IrDeclarationStorage(
}
}
fun getIrBackingFieldSymbol(firVariableSymbol: FirVariableSymbol<*>): IrSymbol {
return when (val fir = firVariableSymbol.fir) {
is FirProperty -> {
val irProperty = getIrProperty(fir).apply {
setAndModifyParent(findIrParent(fir))
}
irSymbolTable.referenceField(irProperty.backingField!!.descriptor)
}
else -> {
getIrVariableSymbol(fir)
}
}
}
private fun getIrVariableSymbol(firVariable: FirVariable<*>): IrVariableSymbol {
val irDeclaration = localStorage.getVariable(firVariable)
?: throw IllegalArgumentException("Cannot find variable ${firVariable.render()} in local storage")
@@ -456,8 +456,37 @@ internal class Fir2IrVisitor(
}
}
private fun IrProperty.createBackingField(
property: FirProperty,
origin: IrDeclarationOrigin,
descriptor: PropertyDescriptor,
visibility: Visibility,
name: Name,
isFinal: Boolean,
firInitializerExpression: FirExpression?,
type: IrType? = null
): IrField {
val inferredType = type ?: firInitializerExpression!!.typeRef.toIrType(session, declarationStorage)
return symbolTable.declareField(
startOffset, endOffset, origin, descriptor, inferredType
) { symbol ->
IrFieldImpl(
startOffset, endOffset, origin, symbol,
name, inferredType,
visibility, isFinal = isFinal, isExternal = false,
isStatic = property.isStatic || parent !is IrClass
)
}.setParentByParentStack().withParent {
declarationStorage.enterScope(descriptor)
val initializerExpression = firInitializerExpression?.toIrExpression()
this.initializer = initializerExpression?.let { IrExpressionBodyImpl(it) }
declarationStorage.leaveScope(descriptor)
}
}
private fun IrProperty.setPropertyContent(descriptor: PropertyDescriptor, property: FirProperty): IrProperty {
val initializer = property.initializer
val delegate = property.delegate
val irParent = this.parent
val type = property.returnTypeRef.toIrType(session, declarationStorage)
// TODO: this checks are very preliminary, FIR resolve should determine backing field presence itself
@@ -465,27 +494,20 @@ internal class Fir2IrVisitor(
if (initializer != null || property.getter is FirDefaultPropertyGetter ||
property.isVar && property.setter is FirDefaultPropertySetter
) {
val backingOrigin = IrDeclarationOrigin.PROPERTY_BACKING_FIELD
backingField = symbolTable.declareField(
startOffset, endOffset, backingOrigin, descriptor, type
) { symbol ->
IrFieldImpl(
startOffset, endOffset, backingOrigin, symbol,
property.name, type, property.visibility,
isFinal = property.isVal, isExternal = false,
isStatic = property.isStatic || irParent !is IrClass
)
}.setParentByParentStack().withParent {
declarationStorage.enterScope(descriptor)
val initializerExpression = initializer?.toIrExpression()
this.initializer = initializerExpression?.let { IrExpressionBodyImpl(it) }
declarationStorage.leaveScope(descriptor)
}
backingField = createBackingField(
property, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, descriptor,
property.visibility, property.name, property.isVal, initializer, type
)
} else if (delegate != null) {
backingField = createBackingField(
property, IrDeclarationOrigin.DELEGATE, descriptor,
Visibilities.PRIVATE, Name.identifier("${property.name}\$delegate"), true, delegate
)
}
}
getter = property.getter.accept(this@Fir2IrVisitor, type) as IrSimpleFunction
getter = property.getter?.let { convertPropertyAccessor(it, type, delegate != null) }
if (property.isVar) {
setter = property.setter!!.accept(this@Fir2IrVisitor, type) as IrSimpleFunction
setter = property.setter?.let { convertPropertyAccessor(it, type, delegate != null) }
}
property.annotations.forEach {
annotations += it.accept(this@Fir2IrVisitor, null) as IrConstructorCall
@@ -511,10 +533,11 @@ internal class Fir2IrVisitor(
private fun createPropertyAccessor(
propertyAccessor: FirPropertyAccessor, startOffset: Int, endOffset: Int,
correspondingProperty: IrProperty, isDefault: Boolean, propertyType: IrType
correspondingProperty: IrProperty, isDefault: Boolean, hasDelegate: Boolean, propertyType: IrType
): IrSimpleFunction {
val origin = when {
isDefault -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
hasDelegate -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
else -> IrDeclarationOrigin.DEFINED
}
val isSetter = propertyAccessor.isSetter
@@ -581,13 +604,13 @@ internal class Fir2IrVisitor(
}
}
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: Any?): IrElement {
private fun convertPropertyAccessor(propertyAccessor: FirPropertyAccessor, type: IrType, hasDelegate: Boolean): IrSimpleFunction {
val correspondingProperty = propertyStack.last()
return propertyAccessor.convertWithOffsets { startOffset, endOffset ->
createPropertyAccessor(
propertyAccessor, startOffset, endOffset, correspondingProperty,
isDefault = propertyAccessor is FirDefaultPropertyGetter || propertyAccessor is FirDefaultPropertySetter,
propertyType = data as IrType
hasDelegate = hasDelegate, propertyType = type
)
}
}
@@ -750,6 +773,34 @@ internal class Fir2IrVisitor(
return qualifiedAccessExpression.toIrExpression(qualifiedAccessExpression.typeRef).applyReceivers(qualifiedAccessExpression)
}
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement {
val symbol = callableReferenceAccess.calleeReference.toSymbol(declarationStorage)
val type = callableReferenceAccess.typeRef.toIrType(this@Fir2IrVisitor.session, declarationStorage)
return callableReferenceAccess.convertWithOffsets { startOffset, endOffset ->
when (symbol) {
is IrPropertySymbol -> {
IrPropertyReferenceImpl(
startOffset, endOffset, type, symbol, 0,
symbol.owner.backingField?.symbol,
symbol.owner.getter?.symbol,
symbol.owner.setter?.symbol
)
}
is IrFunctionSymbol -> {
IrFunctionReferenceImpl(
startOffset, endOffset, type, symbol,
symbol.descriptor, 0
)
}
else -> {
IrErrorCallExpressionImpl(
startOffset, endOffset, type, "Unsupported callable reference: ${callableReferenceAccess.render()}"
)
}
}
}
}
private fun generateErrorCallExpression(startOffset: Int, endOffset: Int, calleeReference: FirReference): IrErrorCallExpression {
return IrErrorCallExpressionImpl(
startOffset, endOffset, IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT),
@@ -11,8 +11,10 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirField
import org.jetbrains.kotlin.fir.declarations.impl.FirAbstractCallableMember
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFieldSymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.name.Name
class FirJavaField(
@@ -40,7 +42,14 @@ class FirJavaField(
override val initializer: FirExpression?
get() = null
override val delegateFieldSymbol: FirDelegateFieldSymbol<FirField>?
get() = null
init {
status.isStatic = isStatic
}
override fun <D> transformChildrenWithoutAccessors(transformer: FirTransformer<D>, data: D) {
transformChildren(transformer, data)
}
}
@@ -8,20 +8,25 @@ package org.jetbrains.kotlin.fir.builder
import com.intellij.psi.PsiElement
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirFunctionTarget
import org.jetbrains.kotlin.fir.FirReference
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirWhenSubject
import org.jetbrains.kotlin.fir.declarations.impl.FirModifiableAccessorsOwner
import org.jetbrains.kotlin.fir.declarations.impl.FirPropertyAccessorImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirVariableImpl
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirExplicitThisReference
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.ConeStarProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBooleanTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitKPropertyTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
@@ -563,4 +568,67 @@ internal fun KtExpression?.generateAssignment(
return FirVariableAssignmentImpl(session, psi, value, operation).apply {
lValue = initializeLValue(session, this@generateAssignment) { convert() as? FirQualifiedAccess }
}
}
}
internal fun FirModifiableAccessorsOwner.generateAccessorsByDelegate(session: FirSession, member: Boolean) {
val variable = this as FirVariable<*>
val delegateFieldSymbol = delegateFieldSymbol ?: return
fun delegateAccess() = FirQualifiedAccessExpressionImpl(session, null).apply {
calleeReference = FirDelegateFieldReferenceImpl(session, null, delegateFieldSymbol)
}
fun thisRef() =
if (member) FirQualifiedAccessExpressionImpl(session, null).apply {
calleeReference = FirExplicitThisReference(session, null, null)
}
else FirConstExpressionImpl(session, null, IrConstKind.Null, null)
fun propertyRef() = FirCallableReferenceAccessImpl(session, null).apply {
calleeReference = FirResolvedCallableReferenceImpl(session, null, variable.name, variable.symbol)
typeRef = FirImplicitKPropertyTypeRef(session, null, ConeStarProjection)
}
getter = (getter as? FirPropertyAccessorImpl)
?: FirPropertyAccessorImpl(session, null, true, Visibilities.UNKNOWN, FirImplicitTypeRefImpl(session, null)).apply Accessor@{
body = FirSingleExpressionBlock(
session,
FirReturnExpressionImpl(
session, null,
FirFunctionCallImpl(session, null).apply {
explicitReceiver = delegateAccess()
calleeReference = FirSimpleNamedReference(session, null, GET_VALUE)
arguments += thisRef()
arguments += propertyRef()
}
).apply {
target = FirFunctionTarget(null)
target.bind(this@Accessor)
}
)
}
setter = (setter as? FirPropertyAccessorImpl)
?: FirPropertyAccessorImpl(session, null, false, Visibilities.UNKNOWN, FirImplicitUnitTypeRef(session, null)).apply {
val parameter = FirValueParameterImpl(
session, null, DELEGATED_SETTER_PARAM,
FirImplicitTypeRefImpl(session, null),
defaultValue = null, isCrossinline = false,
isNoinline = false, isVararg = false
)
valueParameters += parameter
body = FirSingleExpressionBlock(
session, FirFunctionCallImpl(session, null).apply {
explicitReceiver = delegateAccess()
calleeReference = FirSimpleNamedReference(session, null, SET_VALUE)
arguments += thisRef()
arguments += propertyRef()
arguments += FirQualifiedAccessExpressionImpl(session, null).apply {
calleeReference = FirResolvedCallableReferenceImpl(session, psi, DELEGATED_SETTER_PARAM, parameter.symbol)
}
}
)
}
}
private val GET_VALUE = Name.identifier("getValue")
private val SET_VALUE = Name.identifier("setValue")
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 =
@@ -285,10 +285,11 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
this@RawFirBuilder.session, this@toFirProperty, nameAsSafeName, firParameter.symbol
)
},
getter = FirDefaultPropertyGetter(session, this, type, visibility),
setter = if (isMutable) FirDefaultPropertySetter(session, this, type, visibility) else null,
delegate = null
)
).apply {
getter = FirDefaultPropertyGetter(this@RawFirBuilder.session, this@toFirProperty, type, visibility)
setter = if (isMutable) FirDefaultPropertySetter(this@RawFirBuilder.session, this@toFirProperty, type, visibility) else null
}
extractAnnotationsTo(firProperty)
return firProperty
}
@@ -782,7 +783,9 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
isVar,
initializer,
delegate = property.delegate?.expression?.toFirExpression("Incorrect delegate expression")
)
).apply {
generateAccessorsByDelegate(this@RawFirBuilder.session, member = false)
}
} else {
FirMemberPropertyImpl(
session,
@@ -800,13 +803,14 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
propertyType,
isVar,
initializer,
property.getter.toFirPropertyAccessor(property, propertyType, isGetter = true),
if (isVar) property.setter.toFirPropertyAccessor(property, propertyType, isGetter = false) else null,
if (property.hasDelegate()) {
{ property.delegate?.expression }.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)
}
}
property.extractAnnotationsTo(firProperty)
@@ -173,14 +173,14 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
returnTypeRef = returnTypeRef,
isVar = isVar,
initializer = null,
getter = FirDefaultPropertyGetter(c.session, null, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(getterFlags))),
setter = if (isVar) {
FirDefaultPropertySetter(c.session, null, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags)))
} else null,
delegate = null
).apply {
typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir }
annotations += c.annotationDeserializer.loadPropertyAnnotations(proto, local.nameResolver)
getter = FirDefaultPropertyGetter(c.session, null, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(getterFlags)))
setter = if (isVar) {
FirDefaultPropertySetter(c.session, null, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags)))
} else null
}
}
@@ -61,10 +61,11 @@ class FirSyntheticPropertiesScope(
returnTypeRef = returnTypeRef,
isVar = true,
initializer = null,
getter = FirDefaultPropertyGetter(session, null, returnTypeRef, fir.visibility),
setter = FirDefaultPropertySetter(session, null, returnTypeRef, fir.visibility),
delegate = null
)
).apply {
getter = FirDefaultPropertyGetter(this@FirSyntheticPropertiesScope.session, null, returnTypeRef, fir.visibility)
setter = FirDefaultPropertySetter(this@FirSyntheticPropertiesScope.session, null, returnTypeRef, fir.visibility)
}
return processor(synthetic)
}
@@ -414,6 +414,11 @@ open class FirBodyResolveTransformer(
}
return qualifiedAccessExpression.compose()
}
is FirDelegateFieldReference -> {
val delegateFieldSymbol = callee.coneSymbol
qualifiedAccessExpression.resultType = delegateFieldSymbol.delegate.typeRef
return qualifiedAccessExpression.compose()
}
is FirResolvedCallableReference -> {
if (qualifiedAccessExpression.typeRef !is FirResolvedTypeRef) {
storeTypeFromCallee(qualifiedAccessExpression)
@@ -1020,21 +1025,10 @@ open class FirBodyResolveTransformer(
}
)
}
variable.delegate != null -> {
// TODO: type from delegate
variable.getter != null && variable.getter !is FirDefaultPropertyAccessor -> {
variable.transformReturnTypeRef(
this,
FirErrorTypeRefImpl(
session,
null,
"Not supported: type from delegate"
)
)
}
variable is FirProperty && variable.getter !is FirDefaultPropertyAccessor -> {
variable.transformReturnTypeRef(
this,
when (val resultType = variable.getter.returnTypeRef) {
when (val resultType = variable.getter?.returnTypeRef) {
is FirImplicitTypeRef -> FirErrorTypeRefImpl(
session,
null,
@@ -1050,15 +1044,31 @@ open class FirBodyResolveTransformer(
)
}
}
if (variable is FirProperty && variable.getter.returnTypeRef is FirImplicitTypeRef) {
variable.getter.transformReturnTypeRef(this, variable.returnTypeRef)
if (variable.getter?.returnTypeRef is FirImplicitTypeRef) {
variable.getter?.transformReturnTypeRef(this, variable.returnTypeRef)
}
}
}
private fun <F : FirVariable<F>> FirVariable<F>.transformAccessors() {
var enhancedTypeRef = returnTypeRef
getter?.transform<FirDeclaration, Any?>(this@FirBodyResolveTransformer, enhancedTypeRef)
if (returnTypeRef is FirImplicitTypeRef) {
storeVariableReturnType(this)
enhancedTypeRef = returnTypeRef
}
setter?.let {
it.transform<FirDeclaration, Any?>(this@FirBodyResolveTransformer, enhancedTypeRef)
it.valueParameters[0].transformReturnTypeRef(StoreType, enhancedTypeRef)
}
}
override fun <F : FirVariable<F>> transformVariable(variable: FirVariable<F>, data: Any?): CompositeTransformResult<FirDeclaration> {
val variable = super.transformVariable(variable, variable.returnTypeRef).single as FirVariable<*>
storeVariableReturnType(variable)
variable.transformChildrenWithoutAccessors(this, variable.returnTypeRef)
if (variable.initializer != null) {
storeVariableReturnType(variable)
}
variable.transformAccessors()
if (variable !is FirProperty) {
localScopes.lastOrNull()?.storeDeclaration(variable)
}
@@ -1075,23 +1085,14 @@ open class FirBodyResolveTransformer(
localScopes.addIfNotNull(primaryConstructorParametersScope)
withContainer(property) {
property.transformChildrenWithoutAccessors(this, returnTypeRef)
if (property.returnTypeRef is FirImplicitTypeRef && property.initializer != null) {
if (property.initializer != null) {
storeVariableReturnType(property)
}
withScopeCleanup(localScopes) {
localScopes.add(FirLocalScope().apply {
storeBackingField(property)
})
var enhancedTypeRef = property.returnTypeRef
property.getter.transform<FirDeclaration, Any?>(this, enhancedTypeRef)
if (property.returnTypeRef is FirImplicitTypeRef) {
storeVariableReturnType(property)
enhancedTypeRef = property.returnTypeRef
}
property.setter?.let {
it.transform<FirDeclaration, Any?>(this, enhancedTypeRef)
it.valueParameters[0].transformReturnTypeRef(StoreType, enhancedTypeRef)
}
property.transformAccessors()
}
}
property.compose()
@@ -43,7 +43,7 @@ class FirStatusResolveTransformer : FirAbstractTreeTransformer() {
Modality.FINAL
this is FirNamedFunction && body == null ->
Modality.ABSTRACT
this is FirProperty && initializer == null && getter.body == null && setter?.body == null ->
this is FirProperty && initializer == null && getter?.body == null && setter?.body == null ->
Modality.ABSTRACT
else ->
Modality.OPEN
@@ -0,0 +1,5 @@
class C(val map: MutableMap<String, Any>) {
var foo by map
}
var bar by hashMapOf<String, Any>()
@@ -0,0 +1,25 @@
FILE: simpleDelegatedToMap.kt
public final class C : R|kotlin/Any| {
public constructor(map: R|kotlin/collections/MutableMap<kotlin/String, kotlin/Any>|): R|C| {
super<R|kotlin/Any|>()
}
public final val map: R|kotlin/collections/MutableMap<kotlin/String, kotlin/Any>| = R|<local>/map|
public get(): R|kotlin/collections/MutableMap<kotlin/String, kotlin/Any>|
public final var foo: <ERROR TYPE REF: Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>by R|<local>/map|
public get(): <ERROR TYPE REF: Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]> {
^ D|/C.foo|.<Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>#(this#, ::R|/C.foo|)
}
public set(<set-?>: <ERROR TYPE REF: Ambiguity: getValue, [kotlin/collections/getValue, kotlin/collections/getValue, kotlin/collections/getValue]>): R|kotlin/Unit| {
D|/C.foo|.<Inapplicable(INAPPLICABLE): [kotlin/collections/setValue]>#(this#, ::R|/C.foo|, R|<local>/<set-?>|)
}
}
public final var bar: <ERROR TYPE REF: Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/collections/getValue]>by R|kotlin/collections/hashMapOf|<R|kotlin/String|, R|kotlin/Any|>()
public get(): <ERROR TYPE REF: Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/collections/getValue]> {
^ D|/bar|.<Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/collections/getValue]>#(Null(null), ::R|/bar|)
}
public set(<set-?>: <ERROR TYPE REF: Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/collections/getValue]>): R|kotlin/Unit| {
D|/bar|.<Inapplicable(WRONG_RECEIVER): [kotlin/collections/setValue]>#(Null(null), ::R|/bar|, R|<local>/<set-?>|)
}
@@ -0,0 +1,9 @@
//val x = lazy { "Hello" }.getValue(null, throw null)
val x by lazy { "Hello" }
fun foo() {
x.length
val y by lazy { "Bye" }
y.length
}
@@ -0,0 +1,16 @@
FILE: simpleLazy.kt
public final val x: R|kotlin/String|by R|kotlin/lazy|<R|kotlin/String|>(<L> = lazy@fun <anonymous>(): R|kotlin/String| {
String(Hello)
}
)
public get(): R|kotlin/String| {
^ D|/x|.R|kotlin/getValue|<R|kotlin/String|>(Null(null), ::R|/x|)
}
public final fun foo(): R|kotlin/Unit| {
R|/x|.R|kotlin/String.length|
lval y: R|kotlin/String|by R|kotlin/lazy|<R|kotlin/String|>(<L> = lazy@fun <anonymous>(): R|kotlin/String| {
String(Bye)
}
)
R|<local>/y|.R|kotlin/String.length|
}
@@ -94,6 +94,16 @@ public class FirResolveTestCaseWithStdlibGenerated extends AbstractFirResolveTes
runTest("compiler/fir/resolve/testData/resolve/stdlib/reflectionClass.kt");
}
@TestMetadata("simpleDelegatedToMap.kt")
public void testSimpleDelegatedToMap() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/simpleDelegatedToMap.kt");
}
@TestMetadata("simpleLazy.kt")
public void testSimpleLazy() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/simpleLazy.kt");
}
@TestMetadata("topLevelResolve.kt")
public void testTopLevelResolve() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/topLevelResolve.kt");
@@ -0,0 +1,25 @@
/*
* 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
import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.Name
interface FirDelegateFieldReference : FirResolvedCallableReference {
override val name: Name
get() = NAME
override val coneSymbol: FirDelegateFieldSymbol<*>
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitDelegateFieldReference(this, data)
companion object {
val NAME = Name.identifier("\$delegate")
}
}
@@ -346,8 +346,8 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
visitVariable(property)
println()
pushIndent()
property.getter.accept(this)
if (property.getter.body == null) {
property.getter?.accept(this)
if (property.getter?.body == null) {
println()
}
if (property.isVar) {
@@ -804,6 +804,12 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
print("|")
}
override fun visitDelegateFieldReference(delegateFieldReference: FirDelegateFieldReference) {
print("D|")
print(delegateFieldReference.coneSymbol.callableId)
print("|")
}
override fun visitResolvedCallableReference(resolvedCallableReference: FirResolvedCallableReference) {
print("R|")
val isFakeOverride = (resolvedCallableReference.coneSymbol as? FirNamedFunctionSymbol)?.isFakeOverride == true
@@ -23,14 +23,13 @@ interface FirProperty :
override val isOverride: Boolean get() = status.isOverride
// Should it be nullable or have some default?
val getter: FirPropertyAccessor
override val getter: FirPropertyAccessor?
val setter: FirPropertyAccessor?
override val setter: FirPropertyAccessor?
// TODO: it should be probably nullable
val backingFieldSymbol: FirBackingFieldSymbol
fun <D> transformChildrenWithoutAccessors(transformer: FirTransformer<D>, data: D)
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitProperty(this, data)
@@ -38,7 +37,7 @@ interface FirProperty :
super<FirCallableMemberDeclaration>.acceptChildren(visitor, data)
initializer?.accept(visitor, data)
delegate?.accept(visitor, data)
getter.accept(visitor, data)
getter?.accept(visitor, data)
setter?.accept(visitor, data)
}
}
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.VisitedSupertype
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirVariable
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
@BaseTransformedType
@@ -24,6 +25,10 @@ interface FirValueParameter : @VisitedSupertype FirDeclaration, FirTypedDeclarat
override val symbol: FirVariableSymbol<FirValueParameter>
override fun <D> transformChildrenWithoutAccessors(transformer: FirTransformer<D>, data: D) {
transformChildren(transformer, data)
}
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitValueParameter(this, data)
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.transformSingle
import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -33,6 +34,8 @@ class FirDefaultSetterValueParameter(
get() = null
override val receiverTypeRef: FirTypeRef?
get() = null
override val delegateFieldSymbol: FirDelegateFieldSymbol<FirValueParameter>?
get() = null
override val isCrossinline = false
@@ -14,6 +14,7 @@ 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.symbols.impl.FirBackingFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.transformInplace
import org.jetbrains.kotlin.fir.transformSingle
@@ -37,17 +38,24 @@ class FirMemberPropertyImpl(
returnTypeRef: FirTypeRef,
override val isVar: Boolean,
override var initializer: FirExpression?,
override var getter: FirPropertyAccessor,
override var setter: FirPropertyAccessor?,
override var delegate: FirExpression?
) : FirAbstractCallableMember<FirProperty>(
session, psi, name, visibility, modality, isExpect, isActual, isOverride, receiverTypeRef, returnTypeRef
), FirProperty {
), FirProperty, FirModifiableAccessorsOwner {
// TODO: backing field may not exist
override val backingFieldSymbol = FirBackingFieldSymbol(symbol.callableId)
override val delegateFieldSymbol: FirDelegateFieldSymbol<FirProperty>? =
delegate?.let { FirDelegateFieldSymbol(symbol.callableId) }
override var getter: FirPropertyAccessor? = null
override var setter: FirPropertyAccessor? = null
init {
symbol.bind(this)
backingFieldSymbol.bind(this)
delegateFieldSymbol?.bind(this)
status.isConst = isConst
status.isLateInit = isLateInit
}
@@ -63,7 +71,7 @@ class FirMemberPropertyImpl(
}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
getter = getter.transformSingle(transformer, data)
getter = getter?.transformSingle(transformer, data)
setter = setter?.transformSingle(transformer, data)
transformChildrenWithoutAccessors(transformer, data)
// Everything other (annotations, etc.) is done above
@@ -0,0 +1,17 @@
/*
* 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.declarations.impl
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol
interface FirModifiableAccessorsOwner {
var getter: FirPropertyAccessor?
var setter: FirPropertyAccessor?
val delegateFieldSymbol: FirDelegateFieldSymbol<*>?
}
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.transformSingle
import org.jetbrains.kotlin.fir.types.FirTypeRef
@@ -40,6 +41,8 @@ open class FirValueParameterImpl(
get() = null
override val receiverTypeRef: FirTypeRef?
get() = null
override val delegateFieldSymbol: FirDelegateFieldSymbol<FirValueParameter>?
get() = null
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
returnTypeRef = returnTypeRef.transformSingle(transformer, data)
@@ -8,9 +8,13 @@ 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
import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.transformInplace
import org.jetbrains.kotlin.fir.transformSingle
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.FirTransformer
@@ -25,21 +29,36 @@ class FirVariableImpl(
override var initializer: FirExpression?,
override val symbol: FirVariableSymbol<FirVariableImpl> = FirVariableSymbol(name),
override var delegate: FirExpression? = null
) : FirAbstractNamedAnnotatedDeclaration(session, psiElement, name), FirVariable<FirVariableImpl> {
) : FirAbstractNamedAnnotatedDeclaration(session, psiElement, name), FirVariable<FirVariableImpl>, FirModifiableAccessorsOwner {
override val delegateFieldSymbol: FirDelegateFieldSymbol<FirVariableImpl>? =
delegate?.let { FirDelegateFieldSymbol(symbol.callableId) }
override var getter: FirPropertyAccessor? = null
override var setter: FirPropertyAccessor? = null
init {
symbol.bind(this)
delegateFieldSymbol?.bind(this)
}
override val receiverTypeRef: FirTypeRef?
get() = null
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
override fun <D> transformChildrenWithoutAccessors(transformer: FirTransformer<D>, data: D) {
returnTypeRef = returnTypeRef.transformSingle(transformer, data)
initializer = initializer?.transformSingle(transformer, data)
delegate = delegate?.transformSingle(transformer, data)
annotations.transformInplace(transformer, data)
}
return super<FirAbstractNamedAnnotatedDeclaration>.transformChildren(transformer, data)
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
getter = getter?.transformSingle(transformer, data)
setter = setter?.transformSingle(transformer, data)
transformChildrenWithoutAccessors(transformer, data)
// Everything other (annotations, etc.) is done above
return this
}
override fun <D> transformReturnTypeRef(transformer: FirTransformer<D>, data: D) {
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.fir.expressions
import org.jetbrains.kotlin.fir.VisitedSupertype
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.FirVisitor
interface FirVariable<F : FirVariable<F>> :
@@ -23,12 +25,22 @@ interface FirVariable<F : FirVariable<F>> :
override val symbol: FirVariableSymbol<F>
val getter: FirPropertyAccessor? get() = null
val setter: FirPropertyAccessor? get() = null
val delegateFieldSymbol: FirDelegateFieldSymbol<F>?
fun <D> transformChildrenWithoutAccessors(transformer: FirTransformer<D>, data: D)
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitVariable(this, data)
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
initializer?.accept(visitor, data)
delegate?.accept(visitor, data)
getter?.accept(visitor, data)
setter?.accept(visitor, data)
super<FirCallableDeclaration>.acceptChildren(visitor, data)
}
}
@@ -0,0 +1,18 @@
/*
* 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.references
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.FirAbstractElement
import org.jetbrains.kotlin.fir.FirDelegateFieldReference
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol
class FirDelegateFieldReferenceImpl(
session: FirSession,
psi: PsiElement?,
override val coneSymbol: FirDelegateFieldSymbol<*>
) : FirAbstractElement(session, psi), FirDelegateFieldReference
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.symbols.impl
import org.jetbrains.kotlin.fir.declarations.FirField
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirVariable
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.ConePropertySymbol
@@ -23,4 +24,9 @@ open class FirPropertySymbol(callableId: CallableId) : ConePropertySymbol, FirVa
class FirBackingFieldSymbol(callableId: CallableId) : FirVariableSymbol<FirProperty>(callableId)
class FirDelegateFieldSymbol<D : FirVariable<D>>(callableId: CallableId) : FirVariableSymbol<D>(callableId) {
val delegate: FirExpression
get() = fir.delegate!!
}
class FirFieldSymbol(callableId: CallableId) : FirVariableSymbol<FirField>(callableId)
@@ -12,18 +12,20 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTagImpl
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeKotlinTypeProjection
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.name.ClassId
sealed class FirImplicitBuiltinTypeRef(
session: FirSession,
psi: PsiElement?,
val id: ClassId
val id: ClassId,
typeArguments: Array<out ConeKotlinTypeProjection> = emptyArray()
) : FirResolvedTypeRef, FirAbstractElement(session, psi) {
override val annotations: List<FirAnnotationCall>
get() = emptyList()
override val type: ConeKotlinType = ConeClassTypeImpl(ConeClassLikeLookupTagImpl(id), emptyArray(), false)
override val type: ConeKotlinType = ConeClassTypeImpl(ConeClassLikeLookupTagImpl(id), typeArguments, false)
}
class FirImplicitUnitTypeRef(
@@ -61,3 +63,8 @@ class FirImplicitStringTypeRef(
psi: PsiElement?
) : FirImplicitBuiltinTypeRef(session, psi, StandardClassIds.String)
class FirImplicitKPropertyTypeRef(
session: FirSession,
psi: PsiElement?,
typeArgument: ConeKotlinTypeProjection
) : FirImplicitBuiltinTypeRef(session, psi, StandardClassIds.KProperty, arrayOf(typeArgument))
@@ -168,6 +168,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
return transformResolvedCallableReference(backingFieldReference, data)
}
open fun transformDelegateFieldReference(delegateFieldReference: FirDelegateFieldReference, data: D): CompositeTransformResult<FirNamedReference> {
return transformResolvedCallableReference(delegateFieldReference, data)
}
open fun <E : FirReference> transformSuperReference(superReference: E, data: D): CompositeTransformResult<E> {
return transformReference(superReference, data)
}
@@ -552,6 +556,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
return transformDefaultPropertyAccessor(defaultPropertyAccessor, data)
}
final override fun visitDelegateFieldReference(delegateFieldReference: FirDelegateFieldReference, data: D): CompositeTransformResult<FirElement> {
return transformDelegateFieldReference(delegateFieldReference, data)
}
final override fun visitDelegatedConstructorCall(delegatedConstructorCall: FirDelegatedConstructorCall, data: D): CompositeTransformResult<FirElement> {
return transformDelegatedConstructorCall(delegatedConstructorCall, data)
}
@@ -168,6 +168,10 @@ abstract class FirVisitor<out R, in D> {
return visitResolvedCallableReference(backingFieldReference, data)
}
open fun visitDelegateFieldReference(delegateFieldReference: FirDelegateFieldReference, data: D): R {
return visitResolvedCallableReference(delegateFieldReference, data)
}
open fun visitSuperReference(superReference: FirSuperReference, data: D): R {
return visitReference(superReference, data)
}
@@ -168,6 +168,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitResolvedCallableReference(backingFieldReference, null)
}
open fun visitDelegateFieldReference(delegateFieldReference: FirDelegateFieldReference) {
visitResolvedCallableReference(delegateFieldReference, null)
}
open fun visitSuperReference(superReference: FirSuperReference) {
visitReference(superReference, null)
}
@@ -552,6 +556,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitDefaultPropertyAccessor(defaultPropertyAccessor)
}
final override fun visitDelegateFieldReference(delegateFieldReference: FirDelegateFieldReference, data: Nothing?) {
visitDelegateFieldReference(delegateFieldReference)
}
final override fun visitDelegatedConstructorCall(delegatedConstructorCall: FirDelegatedConstructorCall, data: Nothing?) {
visitDelegatedConstructorCall(delegatedConstructorCall)
}