All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2010-2020 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.lazy

import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.declareThisReceiverParameter
import org.jetbrains.kotlin.fir.backend.toIrType
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.Fir2IrClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.isNullableAny
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.descriptors.DescriptorVisibility

class Fir2IrLazyClass(
    components: Fir2IrComponents,
    override val startOffset: Int,
    override val endOffset: Int,
    override var origin: IrDeclarationOrigin,
    override val fir: FirRegularClass,
    override val symbol: Fir2IrClassSymbol,
) : IrClass(), AbstractFir2IrLazyDeclaration, Fir2IrComponents by components {
    init {
        symbol.bind(this)
        classifierStorage.preCacheTypeParameters(fir)
    }

    override var annotations: List by createLazyAnnotations()
    override lateinit var typeParameters: List
    override lateinit var parent: IrDeclarationParent

    override val source: SourceElement
        get() = SourceElement.NO_SOURCE

    @ObsoleteDescriptorBasedAPI
    override val descriptor: ClassDescriptor
        get() = symbol.descriptor

    override val name: Name
        get() = fir.name

    @Suppress("SetterBackingFieldAssignment")
    override var visibility: DescriptorVisibility = components.visibilityConverter.convertToDescriptorVisibility(fir.visibility)
        set(_) {
            error("Mutating Fir2Ir lazy elements is not possible")
        }

    override var modality: Modality
        get() = fir.modality!!
        set(_) {
            error("Mutating Fir2Ir lazy elements is not possible")
        }

    override var attributeOwnerId: IrAttributeContainer
        get() = this
        set(_) {
            error("Mutating Fir2Ir lazy elements is not possible")
        }

    override val kind: ClassKind
        get() = fir.classKind

    override val isCompanion: Boolean
        get() = fir.isCompanion

    override val isInner: Boolean
        get() = fir.isInner

    override val isData: Boolean
        get() = fir.isData

    override val isExternal: Boolean
        get() = fir.isExternal

    override val isInline: Boolean
        get() = fir.isInline

    override val isExpect: Boolean
        get() = fir.isExpect

    override val isFun: Boolean
        get() = fir.isFun

    override var superTypes: List by lazyVar {
        fir.superTypeRefs.map { it.toIrType(typeConverter) }
    }

    override var thisReceiver: IrValueParameter? by lazyVar {
        symbolTable.enterScope(this)
        val typeArguments = fir.typeParameters.map {
            IrSimpleTypeImpl(
                classifierStorage.getCachedIrTypeParameter(it.symbol.fir)!!.symbol,
                hasQuestionMark = false, arguments = emptyList(), annotations = emptyList()
            )
        }
        val receiver = declareThisReceiverParameter(
            symbolTable,
            thisType = IrSimpleTypeImpl(symbol, hasQuestionMark = false, arguments = typeArguments, annotations = emptyList()),
            thisOrigin = IrDeclarationOrigin.INSTANCE_RECEIVER
        )
        symbolTable.leaveScope(this)
        receiver
    }

    override val declarations: MutableList by lazyVar {
        val result = mutableListOf()
        val processedNames = mutableSetOf()
        // NB: it's necessary to take all callables from scope,
        // e.g. to avoid accessing un-enhanced Java declarations with FirJavaTypeRef etc. inside
        val scope = fir.unsubstitutedScope(session, scopeSession)
        scope.processDeclaredConstructors {
            result += declarationStorage.getIrConstructorSymbol(it).owner
        }
        for (declaration in fir.declarations) {
            when (declaration) {
                is FirSimpleFunction -> {
                    if (declaration.name !in processedNames) {
                        processedNames += declaration.name
                        if (fir.classKind == ClassKind.ENUM_CLASS && declaration.isStatic &&
                            declaration.returnTypeRef is FirResolvedTypeRef
                        ) {
                            // Handle values() / valueOf() separately
                            // TODO: handle other static functions / properties properly
                            result += declarationStorage.getIrFunctionSymbol(declaration.symbol).owner
                        } else {
                            scope.processFunctionsByName(declaration.name) {
                                if (it is FirNamedFunctionSymbol && it.callableId.classId == fir.symbol.classId) {
                                    if (it.isAbstractMethodOfAny()) {
                                        return@processFunctionsByName
                                    }
                                    result += declarationStorage.getIrFunctionSymbol(it).owner
                                }
                            }
                        }
                    }
                }
                is FirProperty -> {
                    if (declaration.name !in processedNames) {
                        processedNames += declaration.name
                        scope.processPropertiesByName(declaration.name) {
                            if (it is FirPropertySymbol) {
                                result += declarationStorage.getIrPropertySymbol(it).owner as IrProperty
                            }
                        }
                    }
                }
                is FirRegularClass -> {
                    val nestedSymbol = classifierStorage.getIrClassSymbol(declaration.symbol)
                    result += nestedSymbol.owner
                }
                else -> continue
            }
        }
        with(fakeOverrideGenerator) {
            val fakeOverrides = getFakeOverrides(fir, processedNames)
            bindOverriddenSymbols(fakeOverrides)
            result += fakeOverrides
        }
        // TODO: remove this check to save time
        for (declaration in result) {
            if (declaration.parent != this) {
                throw AssertionError("Unmatched parent for lazy class member")
            }
        }
        result
    }

    override var metadata: MetadataSource?
        get() = null
        set(_) = error("We should never need to store metadata of external declarations.")

    private fun FirNamedFunctionSymbol.isAbstractMethodOfAny(): Boolean {
        val fir = fir
        if (fir.modality != Modality.ABSTRACT) return false
        return when (fir.name.asString()) {
            "equals" -> fir.valueParameters.singleOrNull()?.returnTypeRef?.isNullableAny == true
            "hashCode", "toString" -> fir.valueParameters.isEmpty()
            else -> false
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy