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

org.jetbrains.kotlin.fir.scopes.impl.AbstractFirOverrideScope.kt Maven / Gradle / Ivy

/*
 * Copyright 2010-2019 JetBrains s.r.o. 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.scopes.impl

import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker
import org.jetbrains.kotlin.utils.addToStdlib.cast

abstract class AbstractFirOverrideScope(val session: FirSession) : FirScope() {
    //base symbol as key
    val overrides = mutableMapOf, FirCallableSymbol<*>?>()

    val context: ConeTypeContext = session.typeContext

    private fun isEqualTypes(a: ConeKotlinType, b: ConeKotlinType, substitution: ConeSubstitutor) =
        AbstractStrictEqualityTypeChecker.strictEqualTypes(context, substitution.substituteOrSelf(a), substitution.substituteOrSelf(b))

    private fun isEqualTypes(a: FirTypeRef, b: FirTypeRef, substitution: ConeSubstitutor) =
        isEqualTypes(a.cast().type, b.cast().type, substitution)

    private fun isOverriddenFunCheck(member: FirNamedFunction, self: FirNamedFunction): Boolean {
        if (member.valueParameters.size != self.valueParameters.size) return false
        if (member.typeParameters.size != self.typeParameters.size) return false

        val types = self.typeParameters.map {
            ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false)
        }
        val substitution = substitutorByMap(member.typeParameters.map { it.symbol }.zip(types).toMap())
        if (!member.typeParameters.zip(self.typeParameters).all { (a, b) ->
                a.bounds.size == b.bounds.size &&
                        a.bounds.zip(b.bounds).all { (aBound, bBound) -> isEqualTypes(aBound, bBound, substitution) }
            }
        ) return false
        if (!sameReceivers(member.receiverTypeRef, self.receiverTypeRef, substitution)) return false

        return member.valueParameters.zip(self.valueParameters).all { (memberParam, selfParam) ->
            isEqualTypes(memberParam.returnTypeRef, selfParam.returnTypeRef, substitution)
        }
    }

    private fun sameReceivers(memberTypeRef: FirTypeRef?, selfTypeRef: FirTypeRef?, substitution: ConeSubstitutor): Boolean {
        return when {
            memberTypeRef != null && selfTypeRef != null -> isEqualTypes(memberTypeRef, selfTypeRef, substitution)
            else -> memberTypeRef == null && selfTypeRef == null
        }
    }

    protected fun FirCallableSymbol<*>.isOverridden(seen: Set>): FirCallableSymbol<*>? {
        if (overrides.containsKey(this)) return overrides[this]

        fun similarFunctionsOrBothProperties(declaration: FirCallableDeclaration<*>, self: FirCallableDeclaration<*>): Boolean {
            return when (declaration) {
                is FirNamedFunction -> self is FirNamedFunction && isOverriddenFunCheck(declaration, self)
                is FirConstructor -> false
                is FirProperty -> self is FirProperty && sameReceivers(
                    declaration.receiverTypeRef,
                    self.receiverTypeRef,
                    ConeSubstitutor.Empty // TODO
                )
                is FirField -> false
                else -> error("Unknown fir callable type: $declaration, $self")
            }
        }

        val self = (this as AbstractFirBasedSymbol<*>).fir as FirCallableMemberDeclaration<*>
        val overriding = seen.firstOrNull {
            val member = (it as AbstractFirBasedSymbol<*>).fir as FirCallableMemberDeclaration<*>
            self.modality != Modality.FINAL
                    && similarFunctionsOrBothProperties(member, self)
        } // TODO: two or more overrides for one fun?
        overrides[this] = overriding
        return overriding
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy