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

org.jetbrains.kotlin.fir.analysis.checkers.expression.FirUpperBoundViolatedExpressionChecker.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.analysis.checkers.expression

import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.checkers.TypeArgumentWithSourceInfo
import org.jetbrains.kotlin.fir.analysis.checkers.checkUpperBoundViolated
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableWrongReceiver
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.isTypeAliasedConstructor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*

object FirUpperBoundViolatedExpressionChecker : FirQualifiedAccessExpressionChecker() {
    override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
        // something that contains the type parameters
        // declarations with their declared bounds.
        // it may be the called function declaration
        // or the class declaration
        val calleReference = expression.calleeReference
        var calleeSymbol: FirCallableSymbol<*>? = null
        if (calleReference is FirResolvedNamedReference) {
            calleeSymbol = calleReference.toResolvedCallableSymbol()
        } else if (calleReference is FirErrorNamedReference) {
            if (calleReference.diagnostic is ConeInapplicableWrongReceiver) {
                return
            }
            calleeSymbol = calleReference.candidateSymbol as? FirCallableSymbol<*>
        }

        val typeArguments: List
        val typeParameters: List

        if (calleeSymbol is FirConstructorSymbol && calleeSymbol.isTypeAliasedConstructor) {
            val constructedType = expression.typeRef.coneType.fullyExpandedType(context.session)
            typeArguments = constructedType.typeArguments.map {
                TypeArgumentWithSourceInfo(it, typeRef = null, expression.source)
            }

            typeParameters = (constructedType.toSymbol(context.session) as? FirRegularClassSymbol)?.typeParameterSymbols ?: return
        } else {
            typeArguments = expression.typeArguments.map { firTypeProjection ->
                TypeArgumentWithSourceInfo(
                    firTypeProjection.toConeTypeProjection(),
                    (firTypeProjection as? FirTypeProjectionWithVariance)?.typeRef,
                    firTypeProjection.source
                )
            }
            typeParameters = calleeSymbol?.typeParameterSymbols ?: return
        }

        // Neither common calls nor type alias constructor calls may contain projections
        // That should be checked somewhere else
        if (typeArguments.any { it.coneTypeProjection !is ConeKotlinType }) {
            return
        }

        if (typeArguments.size != typeParameters.size) return

        val substitutor = substitutorByMap(
            typeParameters.withIndex().associate { Pair(it.value, typeArguments[it.index].coneTypeProjection as ConeKotlinType) },
            context.session,
        )

        checkUpperBoundViolated(
            context,
            reporter,
            typeParameters,
            typeArguments,
            substitutor,
        )
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy