FIR: support delegated types in secondary constructors

So #KT-24088 Fixed
This commit is contained in:
Mikhail Glukhikh
2018-04-13 11:46:31 +03:00
parent c06b0efdfa
commit dadc028884
3 changed files with 64 additions and 22 deletions
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.* import org.jetbrains.kotlin.fir.declarations.impl.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirBody import org.jetbrains.kotlin.fir.expressions.FirBody
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.impl.* import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
@@ -206,7 +207,7 @@ class RawFirBuilder(val session: FirSession) {
} }
} }
private fun KtClassOrObject.extractSuperTypeListEntriesTo(container: FirClassImpl) { private fun KtClassOrObject.extractSuperTypeListEntriesTo(container: FirClassImpl): FirType? {
var superTypeCallEntry: KtSuperTypeCallEntry? = null var superTypeCallEntry: KtSuperTypeCallEntry? = null
var delegatedSuperType: FirType? = null var delegatedSuperType: FirType? = null
for (superTypeListEntry in superTypeListEntries) { for (superTypeListEntry in superTypeListEntries) {
@@ -228,15 +229,21 @@ class RawFirBuilder(val session: FirSession) {
} }
} }
} }
if (this is KtClass && this.isInterface()) return delegatedSuperType
fun isEnum() = this is KtClass && this.isEnum() fun isEnum() = this is KtClass && this.isEnum()
if (this is KtClass && this.isInterface()) return // TODO: in case we have no primary constructor,
if (!this.hasPrimaryConstructor()) return // it may be not possible to determine delegated super type right here
delegatedSuperType = delegatedSuperType ?: (if (isEnum()) implicitEnumType else implicitAnyType)
if (!this.hasPrimaryConstructor()) return delegatedSuperType
val firPrimaryConstructor = primaryConstructor.toFirConstructor( val firPrimaryConstructor = primaryConstructor.toFirConstructor(
superTypeCallEntry, superTypeCallEntry,
delegatedSuperType = delegatedSuperType ?: (if (isEnum()) implicitEnumType else implicitAnyType), delegatedSuperType,
owner = this owner = this
) )
container.declarations += firPrimaryConstructor container.declarations += firPrimaryConstructor
return delegatedSuperType
} }
private fun KtPrimaryConstructor?.toFirConstructor( private fun KtPrimaryConstructor?.toFirConstructor(
@@ -288,6 +295,11 @@ class RawFirBuilder(val session: FirSession) {
return firFile return firFile
} }
private fun KtClassOrObject.toDelegatedSelfType(): FirType =
FirUserTypeImpl(session, this, isNullable = false).apply {
qualifier.add(FirQualifierPartImpl(nameAsSafeName))
}
override fun visitEnumEntry(enumEntry: KtEnumEntry, data: Unit): FirElement { override fun visitEnumEntry(enumEntry: KtEnumEntry, data: Unit): FirElement {
return withChildClassName(enumEntry.nameAsSafeName) { return withChildClassName(enumEntry.nameAsSafeName) {
val firEnumEntry = FirEnumEntryImpl( val firEnumEntry = FirEnumEntryImpl(
@@ -297,9 +309,17 @@ class RawFirBuilder(val session: FirSession) {
enumEntry.nameAsSafeName enumEntry.nameAsSafeName
) )
enumEntry.extractAnnotationsTo(firEnumEntry) enumEntry.extractAnnotationsTo(firEnumEntry)
enumEntry.extractSuperTypeListEntriesTo(firEnumEntry) val delegatedSuperType = enumEntry.extractSuperTypeListEntriesTo(firEnumEntry)
val delegatedSelfType = enumEntry.toDelegatedSelfType()
for (declaration in enumEntry.declarations) { for (declaration in enumEntry.declarations) {
firEnumEntry.declarations += declaration.convert<FirDeclaration>() firEnumEntry.declarations += when (declaration) {
is KtSecondaryConstructor -> declaration.toFirConstructor(
delegatedSuperType,
delegatedSelfType,
hasPrimaryConstructor = true
)
else -> declaration.convert<FirDeclaration>()
}
} }
firEnumEntry firEnumEntry
} }
@@ -345,15 +365,23 @@ class RawFirBuilder(val session: FirSession) {
) )
classOrObject.extractAnnotationsTo(firClass) classOrObject.extractAnnotationsTo(firClass)
classOrObject.extractTypeParametersTo(firClass) classOrObject.extractTypeParametersTo(firClass)
classOrObject.extractSuperTypeListEntriesTo(firClass) val delegatedSuperType = classOrObject.extractSuperTypeListEntriesTo(firClass)
classOrObject.primaryConstructor?.valueParameters?.forEach { classOrObject.primaryConstructor?.valueParameters?.forEach {
if (it.hasValOrVar()) { if (it.hasValOrVar()) {
firClass.declarations += it.toFirProperty() firClass.declarations += it.toFirProperty()
} }
} }
val delegatedSelfType = classOrObject.toDelegatedSelfType()
for (declaration in classOrObject.declarations) { for (declaration in classOrObject.declarations) {
firClass.declarations += declaration.convert<FirDeclaration>() firClass.declarations += when (declaration) {
is KtSecondaryConstructor -> declaration.toFirConstructor(
delegatedSuperType,
delegatedSelfType,
classOrObject.primaryConstructor != null
)
else -> declaration.convert<FirDeclaration>()
}
} }
firClass firClass
@@ -413,25 +441,38 @@ class RawFirBuilder(val session: FirSession) {
return firFunction return firFunction
} }
override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor, data: Unit): FirElement { private fun KtSecondaryConstructor.toFirConstructor(
delegatedSuperType: FirType?,
delegatedSelfType: FirType,
hasPrimaryConstructor: Boolean
): FirConstructor {
val firConstructor = FirConstructorImpl( val firConstructor = FirConstructorImpl(
session, session,
constructor, this,
constructor.visibility, visibility,
constructor.getDelegationCall().convert(), getDelegationCall().convert(delegatedSuperType, delegatedSelfType, hasPrimaryConstructor),
constructor.buildFirBody() buildFirBody()
) )
constructor.extractAnnotationsTo(firConstructor) extractAnnotationsTo(firConstructor)
constructor.extractValueParametersTo(firConstructor) extractValueParametersTo(firConstructor)
return firConstructor return firConstructor
} }
override fun visitConstructorDelegationCall(call: KtConstructorDelegationCall, data: Unit): FirElement { private fun KtConstructorDelegationCall.convert(
delegatedSuperType: FirType?,
delegatedSelfType: FirType,
hasPrimaryConstructor: Boolean
): FirDelegatedConstructorCall {
val isThis = isCallToThis || (isImplicit && hasPrimaryConstructor)
val delegatedType = when {
isThis -> delegatedSelfType
else -> delegatedSuperType ?: FirErrorTypeImpl(session, this, "No super type")
}
val firConstructorCall = FirDelegatedConstructorCallImpl( val firConstructorCall = FirDelegatedConstructorCallImpl(
session, session,
call, this,
FirErrorTypeImpl(session, call, "Not implemented yet"), delegatedType,
call.isCallToThis || call.isImplicit isThis
) )
// TODO: arguments are not needed for light classes, but will be needed later // TODO: arguments are not needed for light classes, but will be needed later
// call.extractArgumentsTo(firConstructorCall) // call.extractArgumentsTo(firConstructorCall)
@@ -512,6 +553,7 @@ class RawFirBuilder(val session: FirSession) {
typeReference, typeReference,
isNullable, isNullable,
unwrappedElement.receiverTypeReference.convertSafe(), unwrappedElement.receiverTypeReference.convertSafe(),
// TODO: probably implicit type should not be here
unwrappedElement.returnTypeReference.toFirOrImplicitType() unwrappedElement.returnTypeReference.toFirOrImplicitType()
) )
for (valueParameter in unwrappedElement.parameters) { for (valueParameter in unwrappedElement.parameters) {
@@ -3,9 +3,9 @@ FILE: noPrimaryConstructor.kt
public? final? property x(val): String public? final? property x(val): String
public? get(): String public? get(): String
public? constructor(x: String): this<<ERROR TYPE: Not implemented yet>>() { public? constructor(x: String): super<kotlin.Any>() {
} }
public? constructor(): this<<ERROR TYPE: Not implemented yet>>() public? constructor(): this<NoPrimary>()
} }
+1 -1
View File
@@ -23,7 +23,7 @@ FILE: Annotations.kt
STUB STUB
} }
@R|annotations/WithString|(STUB) public? constructor(): this<R|error: Not implemented yet|>() @R|annotations/WithString|(STUB) public? constructor(): this<R|test/Second|>()
} }
@R|annotations/WithInt|(STUB) @R|annotations/WithInt|(STUB) public? final typealias Third = @R|annotations/Simple|() R|test/Second| @R|annotations/WithInt|(STUB) @R|annotations/WithInt|(STUB) public? final typealias Third = @R|annotations/Simple|() R|test/Second|