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

org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassMemberScope.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
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.resolve.lazy.descriptors

import com.google.common.collect.Lists
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE
import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.JetDeclaration
import org.jetbrains.kotlin.psi.JetProperty
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.DelegationResolver.generateDelegatedMembers
import org.jetbrains.kotlin.resolve.dataClassUtils.createComponentName
import org.jetbrains.kotlin.resolve.dataClassUtils.isComponentLike
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker
import org.jetbrains.kotlin.storage.NotNullLazyValue
import org.jetbrains.kotlin.storage.NullableLazyValue
import org.jetbrains.kotlin.types.DeferredType
import org.jetbrains.kotlin.types.JetType
import java.util.*

public open class LazyClassMemberScope(
        c: LazyClassContext,
        declarationProvider: ClassMemberDeclarationProvider,
        thisClass: LazyClassDescriptor,
        trace: BindingTrace
) : AbstractLazyMemberScope(c, declarationProvider, thisClass, trace) {

    private val descriptorsFromDeclaredElements = storageManager.createLazyValue {
        computeDescriptorsFromDeclaredElements(DescriptorKindFilter.ALL, JetScope.ALL_NAME_FILTER, NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS)
    }
    private val extraDescriptors: NotNullLazyValue> = storageManager.createLazyValue {
        computeExtraDescriptors(NoLookupLocation.FOR_ALREADY_TRACKED)
    }

    override fun getDescriptors(kindFilter: DescriptorKindFilter,
                                nameFilter: (Name) -> Boolean): Collection {
        val result = LinkedHashSet(descriptorsFromDeclaredElements())
        result.addAll(extraDescriptors())
        return result
    }

    protected open fun computeExtraDescriptors(location: LookupLocation): Collection {
        val result = ArrayList()
        for (supertype in thisDescriptor.typeConstructor.supertypes) {
            for (descriptor in supertype.memberScope.getDescriptors()) {
                if (descriptor is FunctionDescriptor) {
                    result.addAll(getFunctions(descriptor.name, location))
                }
                else if (descriptor is PropertyDescriptor) {
                    result.addAll(getProperties(descriptor.name, location))
                }
                // Nothing else is inherited
            }
        }

        addDataClassMethods(result, location)

        result.trimToSize()
        return result
    }

    private interface MemberExtractor {
        public fun extract(extractFrom: JetType, name: Name): Collection
    }

    private val primaryConstructor: NullableLazyValue
            = c.storageManager.createNullableLazyValue { resolvePrimaryConstructor() }

    override fun getScopeForMemberDeclarationResolution(declaration: JetDeclaration): LexicalScope {
        if (declaration is JetProperty) {
            return thisDescriptor.getScopeForInitializerResolution()
        }
        return thisDescriptor.getScopeForMemberDeclarationResolution()
    }

    private fun  generateFakeOverrides(name: Name, fromSupertypes: Collection, result: MutableCollection, exactDescriptorClass: Class) {
        OverridingUtil.generateOverridesInFunctionGroup(name, fromSupertypes, ArrayList(result), thisDescriptor, object : OverridingUtil.DescriptorSink {
            override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) {
                assert(exactDescriptorClass.isInstance(fakeOverride)) { "Wrong descriptor type in an override: " + fakeOverride + " while expecting " + exactDescriptorClass.getSimpleName() }
                @Suppress("UNCHECKED_CAST")
                result.add(fakeOverride as D)
            }

            override fun conflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) {
                val declaration = DescriptorToSourceUtils.descriptorToDeclaration(fromCurrent) as JetDeclaration?
                assert(declaration != null, "fromCurrent can not be a fake override")
                trace.report(Errors.CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromCurrent.getContainingDeclaration().getName().asString()))
            }
        })
        OverrideResolver.resolveUnknownVisibilities(result, trace)
    }

    override fun getFunctions(name: Name, location: LookupLocation): Collection {
        // TODO: this should be handled by lazy function descriptors
        val functions = super.getFunctions(name, location)
        resolveUnknownVisibilitiesForMembers(functions)
        return functions
    }

    protected override fun getNonDeclaredFunctions(name: Name, result: MutableSet) {
        val location = NoLookupLocation.FOR_ALREADY_TRACKED

        val fromSupertypes = Lists.newArrayList()
        for (supertype in thisDescriptor.typeConstructor.supertypes) {
            fromSupertypes.addAll(supertype.memberScope.getFunctions(name, location))
        }
        result.addAll(generateDelegatingDescriptors(name, EXTRACT_FUNCTIONS, result))
        generateDataClassMethods(result, name, location)
        generateFakeOverrides(name, fromSupertypes, result, javaClass())
    }

    private fun generateDataClassMethods(result: MutableCollection, name: Name, location: LookupLocation) {
        if (!KotlinBuiltIns.isData(thisDescriptor)) return

        val constructor = getPrimaryConstructor() ?: return

        val primaryConstructorParameters = declarationProvider.getOwnerInfo().getPrimaryConstructorParameters()
        assert(constructor.getValueParameters().size() == primaryConstructorParameters.size()) { "From descriptor: " + constructor.getValueParameters().size() + " but from PSI: " + primaryConstructorParameters.size() }

        if (isComponentLike(name)) {
            var componentIndex = 0

            for (parameter in constructor.getValueParameters()) {
                if (parameter.getType().isError()) continue
                if (!primaryConstructorParameters.get(parameter.getIndex()).hasValOrVar()) continue

                val properties = getProperties(parameter.name, location)
                if (properties.isEmpty()) continue

                val property = properties.iterator().next() as PropertyDescriptor

                ++componentIndex

                if (name == createComponentName(componentIndex)) {
                    val functionDescriptor = DescriptorResolver.createComponentFunctionDescriptor(componentIndex, property, parameter, thisDescriptor, trace)
                    result.add(functionDescriptor)
                    break
                }
            }
        }

        if (name == DescriptorResolver.COPY_METHOD_NAME) {
            for (parameter in constructor.getValueParameters()) {
                // force properties resolution to fill BindingContext.VALUE_PARAMETER_AS_PROPERTY slice
                getProperties(parameter.name, location)
            }

            val copyFunctionDescriptor = DescriptorResolver.createCopyFunctionDescriptor(constructor.getValueParameters(), thisDescriptor, trace)
            result.add(copyFunctionDescriptor)
        }
    }

    override fun getProperties(name: Name, location: LookupLocation): Collection {
        // TODO: this should be handled by lazy property descriptors
        val properties = super.getProperties(name, location)
        resolveUnknownVisibilitiesForMembers(properties as Collection)
        return properties
    }

    private fun resolveUnknownVisibilitiesForMembers(descriptors: Collection) {
        for (descriptor in descriptors) {
            if (descriptor.getKind() != FAKE_OVERRIDE && descriptor.getKind() != DELEGATION) {
                OverridingUtil.resolveUnknownVisibilityForMember(descriptor, OverrideResolver.createCannotInferVisibilityReporter(trace))
            }
            VarianceChecker.recordPrivateToThisIfNeeded(trace, descriptor);
        }
    }

    @Suppress("UNCHECKED_CAST")
    protected override fun getNonDeclaredProperties(name: Name, result: MutableSet) {
        createPropertiesFromPrimaryConstructorParameters(name, result)

        // Members from supertypes
        val fromSupertypes = ArrayList()
        for (supertype in thisDescriptor.typeConstructor.supertypes) {
            fromSupertypes.addAll(supertype.memberScope.getProperties(name, NoLookupLocation.FOR_ALREADY_TRACKED) as Collection)
        }
        result.addAll(generateDelegatingDescriptors(name, EXTRACT_PROPERTIES, result))
        generateFakeOverrides(name, fromSupertypes, result as MutableCollection, javaClass())
    }

    protected open fun createPropertiesFromPrimaryConstructorParameters(name: Name, result: MutableSet) {
        val classInfo = declarationProvider.getOwnerInfo()

        // From primary constructor parameters
        val primaryConstructor = getPrimaryConstructor() ?: return

        val valueParameterDescriptors = primaryConstructor.getValueParameters()
        val primaryConstructorParameters = classInfo.getPrimaryConstructorParameters()
        assert(valueParameterDescriptors.size() == primaryConstructorParameters.size()) {
            "From descriptor: ${valueParameterDescriptors.size()} but from PSI: ${primaryConstructorParameters.size()}"
        }

        for (valueParameterDescriptor in valueParameterDescriptors) {
            if (name != valueParameterDescriptor.getName()) continue

            val parameter = primaryConstructorParameters.get(valueParameterDescriptor.getIndex())
            if (parameter.hasValOrVar()) {
                val propertyDescriptor = c.descriptorResolver.resolvePrimaryConstructorParameterToAProperty(
                        thisDescriptor, valueParameterDescriptor, thisDescriptor.getScopeForClassHeaderResolution(), parameter, trace)
                result.add(propertyDescriptor)
            }
        }
    }

    private fun  generateDelegatingDescriptors(name: Name, extractor: MemberExtractor, existingDescriptors: Collection): Collection {
        val classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject()
            ?: return setOf()

        val lazyTypeResolver = DelegationResolver.TypeResolver { reference ->
            c.typeResolver.resolveType(thisDescriptor.getScopeForClassHeaderResolution(), reference, trace, false)
        }
        val lazyMemberExtractor = DelegationResolver.MemberExtractor {
            type -> extractor.extract(type, name)
        }
        return generateDelegatedMembers(classOrObject, thisDescriptor, existingDescriptors, trace, lazyMemberExtractor, lazyTypeResolver)
    }

    private fun addDataClassMethods(result: MutableCollection, location: LookupLocation) {
        if (!KotlinBuiltIns.isData(thisDescriptor)) return

        if (getPrimaryConstructor() == null) return

        // Generate componentN functions until there's no such function for some n
        var n = 1
        while (true) {
            val componentName = createComponentName(n)
            val functions = getFunctions(componentName, location)
            if (functions.isEmpty()) break

            result.addAll(functions)

            n++
        }
        result.addAll(getFunctions(Name.identifier("copy"), location))
    }

    override fun getPackage(name: Name): PackageViewDescriptor? = null

    private val secondaryConstructors: NotNullLazyValue>
            = c.storageManager.createLazyValue { resolveSecondaryConstructors() }

    public fun getConstructors(): Collection {
        val result = secondaryConstructors()
        val primaryConstructor = getPrimaryConstructor()
        return if (primaryConstructor == null) result else result + primaryConstructor
    }

    public fun getPrimaryConstructor(): ConstructorDescriptor? = primaryConstructor()

    protected open fun resolvePrimaryConstructor(): ConstructorDescriptor? {
        val ownerInfo = declarationProvider.getOwnerInfo()
        val classOrObject = ownerInfo.getCorrespondingClassOrObject() ?: return null

        val hasPrimaryConstructor = classOrObject.hasExplicitPrimaryConstructor()
        if (DescriptorUtils.isTrait(thisDescriptor) && !hasPrimaryConstructor) return null

        if (DescriptorUtils.canHaveDeclaredConstructors(thisDescriptor) || hasPrimaryConstructor) {
            val constructor = c.functionDescriptorResolver.resolvePrimaryConstructorDescriptor(
                    thisDescriptor.getScopeForClassHeaderResolution(), thisDescriptor, classOrObject, trace)
            constructor ?: return null
            setDeferredReturnType(constructor)
            return constructor
        }
        else {
            val constructor = DescriptorResolver.createAndRecordPrimaryConstructorForObject(classOrObject, thisDescriptor, trace)
            setDeferredReturnType(constructor)
            return constructor
        }
    }

    private fun resolveSecondaryConstructors(): Collection {
        val classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject() ?: return emptyList()

        return classOrObject.getSecondaryConstructors().map { constructor ->
            val descriptor = c.functionDescriptorResolver.resolveSecondaryConstructorDescriptor(
                    thisDescriptor.getScopeForClassHeaderResolution(), thisDescriptor, constructor, trace
            )
            setDeferredReturnType(descriptor)
            descriptor
        }
    }

    protected fun setDeferredReturnType(descriptor: ConstructorDescriptorImpl) {
        descriptor.setReturnType(DeferredType.create(c.storageManager, trace, { thisDescriptor.getDefaultType() }))
    }

    // Do not add details here, they may compromise the laziness during debugging
    override fun toString() = "lazy scope for class ${thisDescriptor.getName()}"

    companion object {
        private val EXTRACT_FUNCTIONS: MemberExtractor = object : MemberExtractor {
            override fun extract(extractFrom: JetType, name: Name): Collection {
                return extractFrom.memberScope.getFunctions(name, NoLookupLocation.FOR_ALREADY_TRACKED)
            }
        }

        private val EXTRACT_PROPERTIES: MemberExtractor = object : MemberExtractor {
            override fun extract(extractFrom: JetType, name: Name): Collection {
                @Suppress("UNCHECKED_CAST")
                return extractFrom.memberScope.getProperties(name, NoLookupLocation.FOR_ALREADY_TRACKED) as Collection
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy