Search in sources :

Example 1 with ExpressionTypingServices

use of org.jetbrains.kotlin.types.expressions.ExpressionTypingServices in project kotlin by JetBrains.

the class BodyResolver method resolveSuperTypeEntryList.

public void resolveSuperTypeEntryList(@NotNull final DataFlowInfo outerDataFlowInfo, @NotNull KtClassOrObject ktClass, @NotNull final ClassDescriptor descriptor, @Nullable final ConstructorDescriptor primaryConstructor, @NotNull LexicalScope scopeForConstructorResolution, @NotNull final LexicalScope scopeForMemberResolution) {
    final LexicalScope scopeForConstructor = primaryConstructor == null ? null : FunctionDescriptorUtil.getFunctionInnerScope(scopeForConstructorResolution, primaryConstructor, trace, overloadChecker);
    // TODO : flow
    final ExpressionTypingServices typeInferrer = expressionTypingServices;
    final Map<KtTypeReference, KotlinType> supertypes = Maps.newLinkedHashMap();
    final ResolvedCall<?>[] primaryConstructorDelegationCall = new ResolvedCall[1];
    KtVisitorVoid visitor = new KtVisitorVoid() {

        private void recordSupertype(KtTypeReference typeReference, KotlinType supertype) {
            if (supertype == null)
                return;
            supertypes.put(typeReference, supertype);
        }

        @Override
        public void visitDelegatedSuperTypeEntry(@NotNull KtDelegatedSuperTypeEntry specifier) {
            if (descriptor.getKind() == ClassKind.INTERFACE) {
                trace.report(DELEGATION_IN_INTERFACE.on(specifier));
            }
            KotlinType supertype = trace.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
            recordSupertype(specifier.getTypeReference(), supertype);
            if (supertype != null) {
                DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor();
                if (declarationDescriptor instanceof ClassDescriptor) {
                    ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
                    if (classDescriptor.getKind() != ClassKind.INTERFACE) {
                        trace.report(DELEGATION_NOT_TO_INTERFACE.on(specifier.getTypeReference()));
                    }
                }
            }
            KtExpression delegateExpression = specifier.getDelegateExpression();
            if (delegateExpression != null) {
                LexicalScope scope = scopeForConstructor == null ? scopeForMemberResolution : scopeForConstructor;
                KotlinType expectedType = supertype != null ? supertype : NO_EXPECTED_TYPE;
                typeInferrer.getType(scope, delegateExpression, expectedType, outerDataFlowInfo, trace);
            }
            if (primaryConstructor == null) {
                trace.report(UNSUPPORTED.on(specifier, "Delegation without primary constructor is not supported"));
            }
        }

        @Override
        public void visitSuperTypeCallEntry(@NotNull KtSuperTypeCallEntry call) {
            KtValueArgumentList valueArgumentList = call.getValueArgumentList();
            PsiElement elementToMark = valueArgumentList == null ? call : valueArgumentList;
            if (descriptor.getKind() == ClassKind.INTERFACE) {
                trace.report(SUPERTYPE_INITIALIZED_IN_INTERFACE.on(elementToMark));
            }
            KtTypeReference typeReference = call.getTypeReference();
            if (typeReference == null)
                return;
            if (primaryConstructor == null) {
                if (descriptor.getKind() != ClassKind.INTERFACE) {
                    trace.report(SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR.on(call));
                }
                recordSupertype(typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
                return;
            }
            OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveFunctionCall(trace, scopeForConstructor, CallMaker.makeConstructorCallWithoutTypeArguments(call), NO_EXPECTED_TYPE, outerDataFlowInfo, false);
            if (results.isSuccess()) {
                KotlinType supertype = results.getResultingDescriptor().getReturnType();
                recordSupertype(typeReference, supertype);
                ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
                if (classDescriptor != null) {
                    // allow only one delegating constructor
                    if (primaryConstructorDelegationCall[0] == null) {
                        primaryConstructorDelegationCall[0] = results.getResultingCall();
                    } else {
                        primaryConstructorDelegationCall[0] = null;
                    }
                }
                // Recording type info for callee to use later in JetObjectLiteralExpression
                trace.record(PROCESSED, call.getCalleeExpression(), true);
                trace.record(EXPRESSION_TYPE_INFO, call.getCalleeExpression(), TypeInfoFactoryKt.noTypeInfo(results.getResultingCall().getDataFlowInfoForArguments().getResultInfo()));
            } else {
                recordSupertype(typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
            }
        }

        @Override
        public void visitSuperTypeEntry(@NotNull KtSuperTypeEntry specifier) {
            KtTypeReference typeReference = specifier.getTypeReference();
            KotlinType supertype = trace.getBindingContext().get(BindingContext.TYPE, typeReference);
            recordSupertype(typeReference, supertype);
            if (supertype == null)
                return;
            ClassDescriptor superClass = TypeUtils.getClassDescriptor(supertype);
            if (superClass == null)
                return;
            if (superClass.getKind().isSingleton()) {
                // A "singleton in supertype" diagnostic will be reported later
                return;
            }
            if (descriptor.getKind() != ClassKind.INTERFACE && descriptor.getUnsubstitutedPrimaryConstructor() != null && superClass.getKind() != ClassKind.INTERFACE && !superClass.getConstructors().isEmpty() && !descriptor.isHeader() && !DescriptorUtils.isEffectivelyExternal(descriptor) && !ErrorUtils.isError(superClass)) {
                trace.report(SUPERTYPE_NOT_INITIALIZED.on(specifier));
            }
        }

        @Override
        public void visitKtElement(@NotNull KtElement element) {
            throw new UnsupportedOperationException(element.getText() + " : " + element);
        }
    };
    if (ktClass instanceof KtEnumEntry && DescriptorUtils.isEnumEntry(descriptor) && ktClass.getSuperTypeListEntries().isEmpty()) {
        assert scopeForConstructor != null : "Scope for enum class constructor should be non-null: " + descriptor;
        resolveConstructorCallForEnumEntryWithoutInitializer((KtEnumEntry) ktClass, descriptor, scopeForConstructor, outerDataFlowInfo);
    }
    for (KtSuperTypeListEntry delegationSpecifier : ktClass.getSuperTypeListEntries()) {
        delegationSpecifier.accept(visitor);
    }
    if (DescriptorUtils.isAnnotationClass(descriptor) && ktClass.getSuperTypeList() != null) {
        trace.report(SUPERTYPES_FOR_ANNOTATION_CLASS.on(ktClass.getSuperTypeList()));
    }
    if (primaryConstructorDelegationCall[0] != null && primaryConstructor != null) {
        recordConstructorDelegationCall(trace, primaryConstructor, primaryConstructorDelegationCall[0]);
    }
    checkSupertypeList(descriptor, supertypes, ktClass);
}
Also used : ExpressionTypingServices(org.jetbrains.kotlin.types.expressions.ExpressionTypingServices) NotNull(org.jetbrains.annotations.NotNull) ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) PsiElement(com.intellij.psi.PsiElement)

Aggregations

PsiElement (com.intellij.psi.PsiElement)1 NotNull (org.jetbrains.annotations.NotNull)1 ResolvedCall (org.jetbrains.kotlin.resolve.calls.model.ResolvedCall)1 ExpressionTypingServices (org.jetbrains.kotlin.types.expressions.ExpressionTypingServices)1