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

org.jetbrains.kotlin.resolve.FunctionDescriptorResolver.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-Beta1
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

import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.FunctionExpressionDescriptor
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorResolver.*
import org.jetbrains.kotlin.resolve.DescriptorUtils.getDispatchReceiverParameterIfNeeded
import org.jetbrains.kotlin.resolve.ModifiersChecker.resolveModalityFromModifiers
import org.jetbrains.kotlin.resolve.ModifiersChecker.resolveVisibilityFromModifiers
import org.jetbrains.kotlin.resolve.bindingContextUtil.recordScope
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.DeferredType
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral
import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor
import java.util.*

class FunctionDescriptorResolver(
        private val typeResolver: TypeResolver,
        private val descriptorResolver: DescriptorResolver,
        private val annotationResolver: AnnotationResolver,
        private val storageManager: StorageManager,
        private val expressionTypingServices: ExpressionTypingServices,
        private val builtIns: KotlinBuiltIns,
        private val modifiersChecker: ModifiersChecker
) {
    public fun resolveFunctionDescriptor(
            containingDescriptor: DeclarationDescriptor,
            scope: LexicalScope,
            function: KtNamedFunction,
            trace: BindingTrace,
            dataFlowInfo: DataFlowInfo
    ): SimpleFunctionDescriptor {
        if (function.getName() == null) trace.report(FUNCTION_DECLARATION_WITH_NO_NAME.on(function))

        return resolveFunctionDescriptor(
                SimpleFunctionDescriptorImpl::create, containingDescriptor, scope, function, trace, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE)
    }


    public fun resolveFunctionExpressionDescriptor(
            containingDescriptor: DeclarationDescriptor,
            scope: LexicalScope,
            function: KtNamedFunction,
            trace: BindingTrace,
            dataFlowInfo: DataFlowInfo,
            expectedFunctionType: KotlinType
    ): SimpleFunctionDescriptor = resolveFunctionDescriptor(
            ::FunctionExpressionDescriptor, containingDescriptor, scope, function, trace, dataFlowInfo, expectedFunctionType)

    private fun resolveFunctionDescriptor(
            functionConstructor: (DeclarationDescriptor, Annotations, Name, CallableMemberDescriptor.Kind, SourceElement) -> SimpleFunctionDescriptorImpl,
            containingDescriptor: DeclarationDescriptor,
            scope: LexicalScope,
            function: KtNamedFunction,
            trace: BindingTrace,
            dataFlowInfo: DataFlowInfo,
            expectedFunctionType: KotlinType
    ): SimpleFunctionDescriptor {
        val functionDescriptor = functionConstructor(
                containingDescriptor,
                annotationResolver.resolveAnnotationsWithoutArguments(scope, function.getModifierList(), trace),
                function.getNameAsSafeName(),
                CallableMemberDescriptor.Kind.DECLARATION,
                function.toSourceElement()
        )
        initializeFunctionDescriptorAndExplicitReturnType(containingDescriptor, scope, function, functionDescriptor, trace, expectedFunctionType)
        initializeFunctionReturnTypeBasedOnFunctionBody(scope, function, functionDescriptor, trace, dataFlowInfo)
        BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, function, functionDescriptor)
        return functionDescriptor
    }

    private fun initializeFunctionReturnTypeBasedOnFunctionBody(
            scope: LexicalScope,
            function: KtNamedFunction,
            functionDescriptor: SimpleFunctionDescriptorImpl,
            trace: BindingTrace,
            dataFlowInfo: DataFlowInfo
    ) {
        if (functionDescriptor.getReturnType() != null) return
        assert(function.getTypeReference() == null) {
            "Return type must be initialized early for function: " + function.getText() + ", at: " + DiagnosticUtils.atLocation(function) }

        val returnType = if (function.hasBlockBody()) {
            builtIns.getUnitType()
        }
        else if (function.hasBody()) {
            DeferredType.createRecursionIntolerant(storageManager, trace) {
                PreliminaryDeclarationVisitor.createForDeclaration(function, trace);
                val type = expressionTypingServices.getBodyExpressionType(trace, scope, dataFlowInfo, function, functionDescriptor)
                transformAnonymousTypeIfNeeded(functionDescriptor, function, type, trace)
            }
        }
        else {
            ErrorUtils.createErrorType("No type, no body")
        }
        functionDescriptor.setReturnType(returnType)
    }

    fun initializeFunctionDescriptorAndExplicitReturnType(
            containingDescriptor: DeclarationDescriptor,
            scope: LexicalScope,
            function: KtFunction,
            functionDescriptor: SimpleFunctionDescriptorImpl,
            trace: BindingTrace,
            expectedFunctionType: KotlinType
    ) {
        val innerScope = LexicalWritableScope(scope, functionDescriptor, true, null,
                                              TraceBasedRedeclarationHandler(trace), LexicalScopeKind.FUNCTION_HEADER)

        val typeParameterDescriptors = descriptorResolver.
                resolveTypeParametersForCallableDescriptor(functionDescriptor, innerScope, scope, function.getTypeParameters(), trace)
        innerScope.changeLockLevel(LexicalWritableScope.LockLevel.BOTH)
        descriptorResolver.resolveGenericBounds(function, functionDescriptor, innerScope, typeParameterDescriptors, trace)

        val receiverTypeRef = function.getReceiverTypeReference()
        val receiverType =
                if (receiverTypeRef != null)
                    typeResolver.resolveType(innerScope, receiverTypeRef, trace, true)
                else
                    expectedFunctionType.getReceiverType()


        val valueParameterDescriptors = createValueParameterDescriptors(function, functionDescriptor, innerScope, trace, expectedFunctionType)

        innerScope.changeLockLevel(LexicalWritableScope.LockLevel.READING)

        val returnType = function.getTypeReference()?.let { typeResolver.resolveType(innerScope, it, trace, true) }

        val visibility = resolveVisibilityFromModifiers(function, getDefaultVisibility(function, containingDescriptor))
        val modality = resolveModalityFromModifiers(function, getDefaultModality(containingDescriptor, visibility, function.hasBody()))
        functionDescriptor.initialize(
                receiverType,
                getDispatchReceiverParameterIfNeeded(containingDescriptor),
                typeParameterDescriptors,
                valueParameterDescriptors,
                returnType,
                modality,
                visibility
        )
        functionDescriptor.isOperator = function.hasModifier(KtTokens.OPERATOR_KEYWORD)
        functionDescriptor.isInfix = function.hasModifier(KtTokens.INFIX_KEYWORD)
        functionDescriptor.isExternal = function.hasModifier(KtTokens.EXTERNAL_KEYWORD)
        functionDescriptor.isInline = function.hasModifier(KtTokens.INLINE_KEYWORD)
        functionDescriptor.isTailrec = function.hasModifier(KtTokens.TAILREC_KEYWORD)
        receiverType?.let { ForceResolveUtil.forceResolveAllContents(it.getAnnotations()) }
        for (valueParameterDescriptor in valueParameterDescriptors) {
            ForceResolveUtil.forceResolveAllContents(valueParameterDescriptor.getType().getAnnotations())
        }
    }

    private fun createValueParameterDescriptors(
            function: KtFunction,
            functionDescriptor: SimpleFunctionDescriptorImpl,
            innerScope: LexicalWritableScope,
            trace: BindingTrace,
            expectedFunctionType: KotlinType
    ): List {
        val expectedValueParameters = expectedFunctionType.getValueParameters(functionDescriptor)
        if (expectedValueParameters != null) {
            if (expectedValueParameters.size() == 1 && function is KtFunctionLiteral && function.getValueParameterList() == null) {
                // it parameter for lambda
                val valueParameterDescriptor = expectedValueParameters.first()
                val it = ValueParameterDescriptorImpl(functionDescriptor, null, 0, Annotations.EMPTY, Name.identifier("it"),
                                                      valueParameterDescriptor.getType(), valueParameterDescriptor.declaresDefaultValue(),
                                                      valueParameterDescriptor.isCrossinline, valueParameterDescriptor.isNoinline,
                                                      valueParameterDescriptor.varargElementType, SourceElement.NO_SOURCE)
                trace.record(BindingContext.AUTO_CREATED_IT, it)
                return listOf(it)
            }
            if (function.getValueParameters().size() != expectedValueParameters.size()) {
                val expectedParameterTypes = ExpressionTypingUtils.getValueParametersTypes(expectedValueParameters)
                trace.report(EXPECTED_PARAMETERS_NUMBER_MISMATCH.on(function, expectedParameterTypes.size(), expectedParameterTypes))
            }
        }

        trace.recordScope(innerScope, function.valueParameterList)

        return resolveValueParameters(
                functionDescriptor,
                innerScope,
                function.getValueParameters(),
                trace,
                expectedValueParameters
        )
    }

    private fun KotlinType.functionTypeExpected() = !TypeUtils.noExpectedType(this) && KotlinBuiltIns.isFunctionOrExtensionFunctionType(this)
    private fun KotlinType.getReceiverType(): KotlinType? =
            if (functionTypeExpected()) KotlinBuiltIns.getReceiverType(this) else null

    private fun KotlinType.getValueParameters(owner: FunctionDescriptor): List? =
            if (functionTypeExpected()) KotlinBuiltIns.getValueParameters(owner, this) else null

    public fun resolvePrimaryConstructorDescriptor(
            scope: LexicalScope,
            classDescriptor: ClassDescriptor,
            classElement: KtClassOrObject,
            trace: BindingTrace
    ): ConstructorDescriptorImpl? {
        if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY || !classElement.hasPrimaryConstructor()) return null
        return createConstructorDescriptor(
                scope,
                classDescriptor,
                true,
                classElement.getPrimaryConstructorModifierList(),
                classElement.getPrimaryConstructor() ?: classElement,
                classElement.getPrimaryConstructorParameters(),
                trace
        )
    }

    public fun resolveSecondaryConstructorDescriptor(
            scope: LexicalScope,
            classDescriptor: ClassDescriptor,
            constructor: KtSecondaryConstructor,
            trace: BindingTrace
    ): ConstructorDescriptorImpl {
        return createConstructorDescriptor(
                scope,
                classDescriptor,
                false,
                constructor.getModifierList(),
                constructor,
                constructor.getValueParameters(),
                trace
        )
    }

    private fun createConstructorDescriptor(
            scope: LexicalScope,
            classDescriptor: ClassDescriptor,
            isPrimary: Boolean,
            modifierList: KtModifierList?,
            declarationToTrace: KtDeclaration,
            valueParameters: List,
            trace: BindingTrace
    ): ConstructorDescriptorImpl {
        val constructorDescriptor = ConstructorDescriptorImpl.create(
                classDescriptor,
                annotationResolver.resolveAnnotationsWithoutArguments(scope, modifierList, trace),
                isPrimary,
                declarationToTrace.toSourceElement()
        )
        trace.record(BindingContext.CONSTRUCTOR, declarationToTrace, constructorDescriptor)
        val parameterScope = LexicalWritableScope(
                scope,
                constructorDescriptor,
                false, null,
                TraceBasedRedeclarationHandler(trace),
                LexicalScopeKind.CONSTRUCTOR_HEADER
        )
        parameterScope.changeLockLevel(LexicalWritableScope.LockLevel.BOTH)
        val constructor = constructorDescriptor.initialize(
                resolveValueParameters(constructorDescriptor, parameterScope, valueParameters, trace, null),
                resolveVisibilityFromModifiers(
                        modifierList,
                        DescriptorUtils.getDefaultConstructorVisibility(classDescriptor)
                )
        )
        if (DescriptorUtils.isAnnotationClass(classDescriptor)) {
            CompileTimeConstantUtils.checkConstructorParametersType(valueParameters, trace)
        }
        return constructor
    }

    private fun resolveValueParameters(
            functionDescriptor: FunctionDescriptor,
            parameterScope: LexicalWritableScope,
            valueParameters: List,
            trace: BindingTrace,
            expectedValueParameters: List?
    ): List {
        val result = ArrayList()

        for (i in valueParameters.indices) {
            val valueParameter = valueParameters.get(i)
            val typeReference = valueParameter.getTypeReference()
            val expectedType = expectedValueParameters?.let { if (i < it.size()) it[i].getType() else null }

            val type: KotlinType
            if (typeReference != null) {
                type = typeResolver.resolveType(parameterScope, typeReference, trace, true)
                if (expectedType != null && !TypeUtils.noExpectedType(expectedType)) {
                    if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(expectedType, type)) {
                        trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(valueParameter, expectedType))
                    }
                }
            }
            else {
                if (isFunctionLiteral(functionDescriptor) || isFunctionExpression(functionDescriptor)) {
                    val containsUninferredParameter = TypeUtils.containsSpecialType(expectedType) {
                        TypeUtils.isDontCarePlaceholder(it) || ErrorUtils.isUninferredParameter(it)
                    }
                    if (expectedType == null || containsUninferredParameter) {
                        trace.report(CANNOT_INFER_PARAMETER_TYPE.on(valueParameter))
                    }
                    if (expectedType != null) {
                        type = expectedType
                    }
                    else {
                        type = TypeUtils.CANT_INFER_FUNCTION_PARAM_TYPE
                    }
                }
                else {
                    trace.report(VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION.on(valueParameter))
                    type = ErrorUtils.createErrorType("Type annotation was missing for parameter ${valueParameter.getNameAsSafeName()}")
                }
            }

            if (functionDescriptor !is ConstructorDescriptor || !functionDescriptor.isPrimary()) {
                val isConstructor = functionDescriptor is ConstructorDescriptor
                with (modifiersChecker.withTrace(trace)) {
                    checkParameterHasNoValOrVar(
                            valueParameter,
                            if (isConstructor) VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER else VAL_OR_VAR_ON_FUN_PARAMETER
                    )
                }
            }

            val valueParameterDescriptor = descriptorResolver.resolveValueParameterDescriptor(parameterScope, functionDescriptor,
                                                                                              valueParameter, i, type, trace)
            parameterScope.addVariableDescriptor(valueParameterDescriptor)
            result.add(valueParameterDescriptor)
        }
        return result
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy