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

org.jetbrains.kotlin.types.expressions.LocalClassifierAnalyzer.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0-RC2
Show newest version
/*
 * Copyright 2010-2015 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jetbrains.kotlin.types.expressions

import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.context.GlobalContext
import org.jetbrains.kotlin.context.withModule
import org.jetbrains.kotlin.context.withProject
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker
import org.jetbrains.kotlin.frontend.di.createContainerForLazyLocalClassifierAnalyzer
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.debugText.getDebugText
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.lazy.*
import org.jetbrains.kotlin.resolve.lazy.data.KtClassInfoUtil
import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider
import org.jetbrains.kotlin.resolve.lazy.declarations.PsiBasedClassMemberDeclarationProvider
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.DynamicTypesSettings

class LocalClassifierAnalyzer(
        private val globalContext: GlobalContext,
        private val storageManager: StorageManager,
        private val descriptorResolver: DescriptorResolver,
        private val funcionDescriptorResolver: FunctionDescriptorResolver,
        private val typeResolver: TypeResolver,
        private val annotationResolver: AnnotationResolver,
        private val platform: TargetPlatform,
        private val dynamicTypesSettings: DynamicTypesSettings,
        private val lookupTracker: LookupTracker,
        private val supertypeLoopChecker: SupertypeLoopChecker
) {
    fun processClassOrObject(
            scope: LexicalWritableScope?,
            context: ExpressionTypingContext,
            containingDeclaration: DeclarationDescriptor,
            classOrObject: KtClassOrObject
    ) {
        val module = DescriptorUtils.getContainingModule(containingDeclaration)
        val moduleContext = globalContext.withProject(classOrObject.getProject()).withModule(module)
        val container = createContainerForLazyLocalClassifierAnalyzer(
                moduleContext,
                context.trace,
                platform,
                lookupTracker,
                LocalClassDescriptorHolder(
                        scope,
                        classOrObject,
                        containingDeclaration,
                        storageManager,
                        context,
                        module,
                        descriptorResolver,
                        funcionDescriptorResolver,
                        typeResolver,
                        annotationResolver,
                        supertypeLoopChecker
                )
        )

        container.get().analyzeDeclarations(
                TopDownAnalysisMode.LocalDeclarations,
                listOf(classOrObject),
                context.dataFlowInfo
        )
    }
}

class LocalClassDescriptorHolder(
        val writableScope: LexicalWritableScope?,
        val myClass: KtClassOrObject,
        val containingDeclaration: DeclarationDescriptor,
        val storageManager: StorageManager,
        val expressionTypingContext: ExpressionTypingContext,
        val moduleDescriptor: ModuleDescriptor,
        val descriptorResolver: DescriptorResolver,
        val functionDescriptorResolver: FunctionDescriptorResolver,
        val typeResolver: TypeResolver,
        val annotationResolver: AnnotationResolver,
        val supertypeLoopChecker: SupertypeLoopChecker
) {
    // We do not need to synchronize here, because this code is used strictly from one thread
    private var classDescriptor: ClassDescriptor? = null

    fun isMyClass(element: PsiElement): Boolean = element == myClass
    fun insideMyClass(element: PsiElement): Boolean = PsiTreeUtil.isAncestor(myClass, element, false)

    fun getClassDescriptor(classOrObject: KtClassOrObject, declarationScopeProvider: DeclarationScopeProvider): ClassDescriptor {
        assert(isMyClass(classOrObject)) { "Called on a wrong class: ${classOrObject.getDebugText()}" }
        if (classDescriptor == null) {
            classDescriptor = LazyClassDescriptor(
                    object : LazyClassContext {
                        override val declarationScopeProvider = declarationScopeProvider
                        override val storageManager = [email protected]
                        override val trace = expressionTypingContext.trace
                        override val moduleDescriptor = [email protected]
                        override val descriptorResolver = [email protected]
                        override val functionDescriptorResolver = [email protected]
                        override val typeResolver = [email protected]
                        override val declarationProviderFactory = object : DeclarationProviderFactory {
                            override fun getClassMemberDeclarationProvider(classLikeInfo: KtClassLikeInfo): ClassMemberDeclarationProvider {
                                return PsiBasedClassMemberDeclarationProvider(storageManager, classLikeInfo)
                            }

                            override fun getPackageMemberDeclarationProvider(packageFqName: FqName): PackageMemberDeclarationProvider? {
                                throw UnsupportedOperationException("Should not be called for top-level declarations")
                            }

                            override fun diagnoseMissingPackageFragment(file: KtFile?) {
                                throw UnsupportedOperationException()
                            }
                        }
                        override val annotationResolver = [email protected]
                        override val lookupTracker: LookupTracker = LookupTracker.DO_NOTHING
                        override val supertypeLoopChecker = [email protected]
                    }
                    ,
                    containingDeclaration,
                    classOrObject.getNameAsSafeName(),
                    KtClassInfoUtil.createClassLikeInfo(classOrObject)
            )
            writableScope?.addClassifierDescriptor(classDescriptor!!)
        }

        return classDescriptor!!
    }

    fun getResolutionScopeForClass(classOrObject: KtClassOrObject): LexicalScope {
        assert (isMyClass(classOrObject)) { "Called on a wrong class: ${classOrObject.getDebugText()}" }
        return expressionTypingContext.scope
    }
}

class LocalLazyDeclarationResolver(
        globalContext: GlobalContext,
        trace: BindingTrace,
        private val localClassDescriptorManager: LocalClassDescriptorHolder,
        topLevelDescriptorProvider : TopLevelDescriptorProvider,
        absentDescriptorHandler: AbsentDescriptorHandler
) : LazyDeclarationResolver(globalContext, trace, topLevelDescriptorProvider, absentDescriptorHandler) {

    override fun getClassDescriptor(classOrObject: KtClassOrObject, location: LookupLocation): ClassDescriptor {
        if (localClassDescriptorManager.isMyClass(classOrObject)) {
            return localClassDescriptorManager.getClassDescriptor(classOrObject, scopeProvider)
        }
        return super.getClassDescriptor(classOrObject, location)
    }
}


class DeclarationScopeProviderForLocalClassifierAnalyzer(
        lazyDeclarationResolver: LazyDeclarationResolver,
        fileScopeProvider: FileScopeProvider,
        private val localClassDescriptorManager: LocalClassDescriptorHolder
) : DeclarationScopeProviderImpl(lazyDeclarationResolver, fileScopeProvider) {
    override fun getResolutionScopeForDeclaration(elementOfDeclaration: PsiElement): LexicalScope {
        if (localClassDescriptorManager.isMyClass(elementOfDeclaration)) {
            return localClassDescriptorManager.getResolutionScopeForClass(elementOfDeclaration as KtClassOrObject)
        }
        return super.getResolutionScopeForDeclaration(elementOfDeclaration)
    }

    override fun getOuterDataFlowInfoForDeclaration(elementOfDeclaration: PsiElement): DataFlowInfo {
        // nested (non-inner) classes and companion objects are forbidden in local classes, so it's enough to be simply inside the class
        if (localClassDescriptorManager.insideMyClass(elementOfDeclaration)) {
            return localClassDescriptorManager.expressionTypingContext.dataFlowInfo
        }
        return super.getOuterDataFlowInfoForDeclaration(elementOfDeclaration)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy