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

org.jetbrains.kotlin.fir.FirQualifiedNameResolver.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * 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.expressions.FirQualifiedAccess
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.expressions.builder.buildResolvedQualifier
import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.resolve.transformers.PackageOrClass
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolve.transformers.resolveToPackageOrClass
import org.jetbrains.kotlin.fir.resolve.typeForQualifier
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name

class FirQualifiedNameResolver(private val components: BodyResolveComponents) {
    private val session = components.session
    private var qualifierStack = mutableListOf()
    private var qualifierPartsToDrop = 0

    fun reset() {
        qualifierStack.clear()
        qualifierPartsToDrop = 0
    }


    /**
     * NB: 0 if current 'qualifiedAccess.safe || callee.name.isSpecial', 1 if current is fine, 2 if potential qualifier
     * a.b.c
     *   ^ here stack will be ['c', 'b'], so possible
     * a.b?.c
     *   ^ here stack will be ['b'], so impossible
     * a?.b.c
     *    ^ here stack will be [], so impossible
     */
    fun isPotentialQualifierPartPosition() = qualifierStack.size > 1

    fun initProcessingQualifiedAccess(callee: FirSimpleNamedReference) {
        if (callee.name.isSpecial) {
            qualifierStack.clear()
        } else {
            qualifierStack.add(callee.name)
        }
    }

    fun replacedQualifier(qualifiedAccess: FirQualifiedAccess): FirStatement? =
        if (qualifierPartsToDrop > 0) {
            qualifierPartsToDrop--
            qualifiedAccess.explicitReceiver ?: qualifiedAccess
        } else {
            null
        }

    fun tryResolveAsQualifier(source: FirSourceElement?): FirResolvedQualifier? {
        if (qualifierStack.isEmpty()) {
            return null
        }
        val symbolProvider = session.firSymbolProvider
        var qualifierParts = qualifierStack.asReversed().map { it.asString() }
        var resolved: PackageOrClass?
        do {
            resolved = resolveToPackageOrClass(
                symbolProvider,
                FqName.fromSegments(qualifierParts)
            )
            if (resolved == null)
                qualifierParts = qualifierParts.dropLast(1)
        } while (resolved == null && qualifierParts.isNotEmpty())

        if (resolved != null) {
            qualifierPartsToDrop = qualifierParts.size - 1
            return buildResolvedQualifier {
                this.source = source
                packageFqName = resolved.packageFqName
                relativeClassFqName = resolved.relativeClassFqName
                symbol = resolved.classSymbol
            }.apply {
                resultType = components.typeForQualifier(this)
            }
        }

        return null
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy