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

org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer.kt Maven / Gradle / Ivy

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

import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirImport
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.builder.buildResolvedImport
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName

class FirImportResolveProcessor(session: FirSession, scopeSession: ScopeSession) : FirTransformerBasedResolveProcessor(session, scopeSession) {
    override val transformer = FirImportResolveTransformer(session)
}

open class FirImportResolveTransformer protected constructor(
    final override val session: FirSession,
    phase: FirResolvePhase
) : FirAbstractTreeTransformer(phase) {
    override fun  transformElement(element: E, data: Nothing?): CompositeTransformResult {
        return element.compose()
    }

    constructor(session: FirSession) : this(session, FirResolvePhase.IMPORTS)

    private val symbolProvider: FirSymbolProvider = session.firSymbolProvider

    override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult {
        checkSessionConsistency(file)
        file.replaceResolvePhase(transformerPhase)
        return file.also { it.transformChildren(this, null) }.compose()
    }

    override fun transformImport(import: FirImport, data: Nothing?): CompositeTransformResult {
        val fqName = import.importedFqName?.takeUnless { it.isRoot } ?: return import.compose()

        if (!fqName.isAcceptable) return import.compose()

        if (import.isAllUnder) {
            return transformImportForFqName(fqName, import)
        }

        val parentFqName = fqName.parent()
        return transformImportForFqName(parentFqName, import)
    }

    protected open val FqName.isAcceptable: Boolean
        get() = true

    private fun transformImportForFqName(fqName: FqName, delegate: FirImport): CompositeTransformResult {
        val (packageFqName, relativeClassFqName) = resolveToPackageOrClass(symbolProvider, fqName) ?: return delegate.compose()
        return buildResolvedImport {
            this.delegate = delegate
            this.packageFqName = packageFqName
            relativeClassName = relativeClassFqName
        }.compose()
    }
}

fun resolveToPackageOrClass(symbolProvider: FirSymbolProvider, fqName: FqName): PackageOrClass? {
    var currentPackage = fqName

    val pathSegments = fqName.pathSegments()
    var prefixSize = pathSegments.size
    while (!currentPackage.isRoot && prefixSize > 0) {
        if (symbolProvider.getPackage(currentPackage) != null) {
            break
        }
        currentPackage = currentPackage.parent()
        prefixSize--
    }

    if (currentPackage == fqName) return PackageOrClass(currentPackage, null, null)
    val relativeClassFqName =
        FqName.fromSegments((prefixSize until pathSegments.size).map { pathSegments[it].asString() })

    val classId = ClassId(currentPackage, relativeClassFqName, false)
    val symbol = symbolProvider.getClassLikeSymbolByFqName(classId) ?: return null

    return PackageOrClass(currentPackage, relativeClassFqName, symbol)
}

data class PackageOrClass(val packageFqName: FqName, val relativeClassFqName: FqName?, val classSymbol: FirClassLikeSymbol<*>?)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy