Search in sources :

Example 1 with ResolvedCall

use of org.jetbrains.kotlin.resolve.calls.model.ResolvedCall in project kotlin by JetBrains.

the class BasicExpressionTypingVisitor method recordThisOrSuperCallInTraceAndCallExtension.

private void recordThisOrSuperCallInTraceAndCallExtension(ExpressionTypingContext context, ReceiverParameterDescriptor descriptor, KtExpression expression) {
    BindingTrace trace = context.trace;
    Call call = CallMaker.makeCall(expression, null, null, expression, Collections.<ValueArgument>emptyList());
    ResolutionCandidate<ReceiverParameterDescriptor> resolutionCandidate = ResolutionCandidate.create(call, descriptor, null, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, null);
    ResolvedCallImpl<ReceiverParameterDescriptor> resolvedCall = ResolvedCallImpl.create(resolutionCandidate, TemporaryBindingTrace.create(trace, "Fake trace for fake 'this' or 'super' resolved call"), TracingStrategy.EMPTY, new DataFlowInfoForArgumentsImpl(context.dataFlowInfo, call));
    resolvedCall.markCallAsCompleted();
    trace.record(RESOLVED_CALL, call, resolvedCall);
    trace.record(CALL, expression, call);
    if (context.trace.wantsDiagnostics()) {
        CallCheckerContext callCheckerContext = new CallCheckerContext(context, components.languageVersionSettings);
        for (CallChecker checker : components.callCheckers) {
            checker.check(resolvedCall, expression, callCheckerContext);
        }
    }
}
Also used : ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) DataFlowInfoForArgumentsImpl(org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl)

Example 2 with ResolvedCall

use of org.jetbrains.kotlin.resolve.calls.model.ResolvedCall in project kotlin by JetBrains.

the class ControlStructureTypingUtils method createTracingForSpecialConstruction.

@NotNull
private TracingStrategy createTracingForSpecialConstruction(@NotNull final Call call, @NotNull String constructionName, @NotNull final ExpressionTypingContext context) {
    class CheckTypeContext {

        public BindingTrace trace;

        public KotlinType expectedType;

        CheckTypeContext(@NotNull BindingTrace trace, @NotNull KotlinType expectedType) {
            this.trace = trace;
            this.expectedType = expectedType;
        }

        CheckTypeContext makeTypeNullable() {
            if (TypeUtils.noExpectedType(expectedType))
                return this;
            return new CheckTypeContext(trace, TypeUtils.makeNullable(expectedType));
        }
    }
    final KtVisitor<Boolean, CheckTypeContext> checkTypeVisitor = new KtVisitor<Boolean, CheckTypeContext>() {

        private boolean checkExpressionType(@NotNull KtExpression expression, CheckTypeContext c) {
            KotlinTypeInfo typeInfo = BindingContextUtils.getRecordedTypeInfo(expression, c.trace.getBindingContext());
            if (typeInfo == null)
                return false;
            Ref<Boolean> hasError = Ref.create();
            dataFlowAnalyzer.checkType(typeInfo.getType(), expression, context.replaceExpectedType(c.expectedType).replaceDataFlowInfo(typeInfo.getDataFlowInfo()).replaceBindingTrace(c.trace), hasError);
            return hasError.get();
        }

        private boolean checkExpressionTypeRecursively(@Nullable KtExpression expression, CheckTypeContext c) {
            if (expression == null)
                return false;
            return expression.accept(this, c);
        }

        private boolean checkSubExpressions(KtExpression firstSub, KtExpression secondSub, KtExpression expression, CheckTypeContext firstContext, CheckTypeContext secondContext, CheckTypeContext context) {
            boolean errorWasReported = checkExpressionTypeRecursively(firstSub, firstContext);
            errorWasReported |= checkExpressionTypeRecursively(secondSub, secondContext);
            return errorWasReported || checkExpressionType(expression, context);
        }

        @Override
        public Boolean visitWhenExpression(@NotNull KtWhenExpression whenExpression, CheckTypeContext c) {
            boolean errorWasReported = false;
            for (KtWhenEntry whenEntry : whenExpression.getEntries()) {
                KtExpression entryExpression = whenEntry.getExpression();
                if (entryExpression != null) {
                    errorWasReported |= checkExpressionTypeRecursively(entryExpression, c);
                }
            }
            errorWasReported |= checkExpressionType(whenExpression, c);
            return errorWasReported;
        }

        @Override
        public Boolean visitIfExpression(@NotNull KtIfExpression ifExpression, CheckTypeContext c) {
            KtExpression thenBranch = ifExpression.getThen();
            KtExpression elseBranch = ifExpression.getElse();
            if (thenBranch == null || elseBranch == null) {
                return checkExpressionType(ifExpression, c);
            }
            return checkSubExpressions(thenBranch, elseBranch, ifExpression, c, c, c);
        }

        @Override
        public Boolean visitBlockExpression(@NotNull KtBlockExpression expression, CheckTypeContext c) {
            if (expression.getStatements().isEmpty()) {
                return checkExpressionType(expression, c);
            }
            KtExpression lastStatement = KtPsiUtil.getLastStatementInABlock(expression);
            if (lastStatement != null) {
                return checkExpressionTypeRecursively(lastStatement, c);
            }
            return false;
        }

        @Override
        public Boolean visitPostfixExpression(@NotNull KtPostfixExpression expression, CheckTypeContext c) {
            if (expression.getOperationReference().getReferencedNameElementType() == KtTokens.EXCLEXCL) {
                return checkExpressionTypeRecursively(expression.getBaseExpression(), c.makeTypeNullable());
            }
            return super.visitPostfixExpression(expression, c);
        }

        @Override
        public Boolean visitBinaryExpression(@NotNull KtBinaryExpression expression, CheckTypeContext c) {
            if (expression.getOperationReference().getReferencedNameElementType() == KtTokens.ELVIS) {
                return checkSubExpressions(expression.getLeft(), expression.getRight(), expression, c.makeTypeNullable(), c, c);
            }
            return super.visitBinaryExpression(expression, c);
        }

        @Override
        public Boolean visitExpression(@NotNull KtExpression expression, CheckTypeContext c) {
            return checkExpressionType(expression, c);
        }
    };
    return new ThrowingOnErrorTracingStrategy("resolve " + constructionName + " as a call") {

        @Override
        public <D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCall<D> resolvedCall) {
        //do nothing
        }

        @Override
        public void bindCall(@NotNull BindingTrace trace, @NotNull Call call) {
            trace.record(CALL, call.getCalleeExpression(), call);
        }

        @Override
        public <D extends CallableDescriptor> void bindResolvedCall(@NotNull BindingTrace trace, @NotNull ResolvedCall<D> resolvedCall) {
            trace.record(RESOLVED_CALL, call, resolvedCall);
        }

        @Override
        public void typeInferenceFailed(@NotNull ResolutionContext<?> context, @NotNull InferenceErrorData data) {
            ConstraintSystem constraintSystem = data.constraintSystem;
            ConstraintSystemStatus status = constraintSystem.getStatus();
            assert !status.isSuccessful() : "Report error only for not successful constraint system";
            if (status.hasErrorInConstrainingTypes() || status.hasUnknownParameters()) {
                return;
            }
            KtExpression expression = (KtExpression) call.getCallElement();
            if (status.hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION) || status.hasConflictingConstraints() || status.hasTypeInferenceIncorporationError()) {
                // todo after KT-... remove this line
                if (noTypeCheckingErrorsInExpression(expression, context.trace, data.expectedType)) {
                    KtExpression calleeExpression = call.getCalleeExpression();
                    if (calleeExpression instanceof KtWhenExpression || calleeExpression instanceof KtIfExpression) {
                        if (status.hasConflictingConstraints() || status.hasTypeInferenceIncorporationError()) {
                            // TODO provide comprehensible error report for hasConflictingConstraints() case (if possible)
                            context.trace.report(TYPE_INFERENCE_FAILED_ON_SPECIAL_CONSTRUCT.on(expression));
                        }
                    }
                }
                return;
            }
            KtDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, KtNamedDeclaration.class);
            logError("Expression: " + (parentDeclaration != null ? parentDeclaration.getText() : expression.getText()) + "\nConstraint system status: \n" + ConstraintsUtil.getDebugMessageForStatus(status));
        }

        private boolean noTypeCheckingErrorsInExpression(KtExpression expression, @NotNull BindingTrace trace, @NotNull KotlinType expectedType) {
            return Boolean.TRUE != expression.accept(checkTypeVisitor, new CheckTypeContext(trace, expectedType));
        }
    };
}
Also used : ResolutionContext(org.jetbrains.kotlin.resolve.calls.context.ResolutionContext) ConstraintSystem(org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem) ConstraintSystemStatus(org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemStatus) NotNull(org.jetbrains.annotations.NotNull) InferenceErrorData(org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData) ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) BindingTrace(org.jetbrains.kotlin.resolve.BindingTrace) ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) Nullable(org.jetbrains.annotations.Nullable) NotNull(org.jetbrains.annotations.NotNull)

Example 3 with ResolvedCall

use of org.jetbrains.kotlin.resolve.calls.model.ResolvedCall in project kotlin by JetBrains.

the class BasicExpressionTypingVisitor method checkLValue.

/**
     * @return {@code true} iff expression can be assigned to
     */
public boolean checkLValue(@NotNull BindingTrace trace, @NotNull ExpressionTypingContext context, @NotNull KtExpression expressionWithParenthesis, @Nullable KtExpression rightHandSide, @NotNull KtOperationExpression operationExpression) {
    KtExpression expression = KtPsiUtil.deparenthesize(expressionWithParenthesis);
    if (expression instanceof KtArrayAccessExpression) {
        KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) expression;
        KtExpression arrayExpression = arrayAccessExpression.getArrayExpression();
        if (arrayExpression == null || rightHandSide == null)
            return false;
        TemporaryBindingTrace ignoreReportsTrace = TemporaryBindingTrace.create(trace, "Trace for checking set function");
        ExpressionTypingContext findSetterContext = context.replaceBindingTrace(ignoreReportsTrace);
        KotlinTypeInfo info = resolveArrayAccessSetMethod(arrayAccessExpression, rightHandSide, findSetterContext, ignoreReportsTrace);
        IElementType operationType = operationExpression.getOperationReference().getReferencedNameElementType();
        if (KtTokens.AUGMENTED_ASSIGNMENTS.contains(operationType) || operationType == KtTokens.PLUSPLUS || operationType == KtTokens.MINUSMINUS) {
            ResolvedCall<?> resolvedCall = ignoreReportsTrace.get(INDEXED_LVALUE_SET, expression);
            if (resolvedCall != null && trace.wantsDiagnostics()) {
                // Call must be validated with the actual, not temporary trace in order to report operator diagnostic
                // Only unary assignment expressions (++, --) and +=/... must be checked, normal assignments have the proper trace
                CallCheckerContext callCheckerContext = new CallCheckerContext(context, trace, components.languageVersionSettings);
                for (CallChecker checker : components.callCheckers) {
                    checker.check(resolvedCall, expression, callCheckerContext);
                }
            }
        }
        return info.getType() != null;
    }
    VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorFromReference(trace.getBindingContext(), expression);
    boolean result = true;
    KtExpression reportOn = expression != null ? expression : expressionWithParenthesis;
    if (reportOn instanceof KtQualifiedExpression) {
        KtExpression selector = ((KtQualifiedExpression) reportOn).getSelectorExpression();
        if (selector != null)
            reportOn = selector;
    }
    if (variable instanceof PropertyDescriptor) {
        PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
        PropertySetterDescriptor setter = propertyDescriptor.getSetter();
        if (propertyDescriptor.isSetterProjectedOut()) {
            trace.report(SETTER_PROJECTED_OUT.on(reportOn, propertyDescriptor));
            result = false;
        } else if (setter != null) {
            ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expressionWithParenthesis, context.trace.getBindingContext());
            assert resolvedCall != null : "Call is not resolved for property setter: " + PsiUtilsKt.getElementTextWithContext(expressionWithParenthesis);
            checkPropertySetterCall(context.replaceBindingTrace(trace), setter, resolvedCall, reportOn);
        }
    }
    if (variable == null) {
        trace.report(VARIABLE_EXPECTED.on(reportOn));
        result = false;
    } else if (!variable.isVar()) {
        result = false;
    }
    return result;
}
Also used : IElementType(com.intellij.psi.tree.IElementType) ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall)

Example 4 with ResolvedCall

use of org.jetbrains.kotlin.resolve.calls.model.ResolvedCall in project kotlin by JetBrains.

the class BasicExpressionTypingVisitor method checkPropertySetterCall.

private void checkPropertySetterCall(@NotNull ExpressionTypingContext context, @NotNull PropertySetterDescriptor descriptor, @NotNull ResolvedCall<?> propertyResolvedCall, @NotNull KtExpression expression) {
    Call call = propertyResolvedCall.getCall();
    ResolutionCandidate<PropertySetterDescriptor> resolutionCandidate = ResolutionCandidate.create(call, descriptor, propertyResolvedCall.getDispatchReceiver(), propertyResolvedCall.getExplicitReceiverKind(), null);
    ResolvedCallImpl<PropertySetterDescriptor> resolvedCall = ResolvedCallImpl.create(resolutionCandidate, TemporaryBindingTrace.create(context.trace, "Trace for fake property setter resolved call"), TracingStrategy.EMPTY, new DataFlowInfoForArgumentsImpl(propertyResolvedCall.getDataFlowInfoForArguments().getResultInfo(), call));
    resolvedCall.markCallAsCompleted();
    if (context.trace.wantsDiagnostics()) {
        CallCheckerContext callCheckerContext = new CallCheckerContext(context, components.languageVersionSettings);
        for (CallChecker checker : components.callCheckers) {
            checker.check(resolvedCall, expression, callCheckerContext);
        }
    }
}
Also used : ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) DataFlowInfoForArgumentsImpl(org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl)

Example 5 with ResolvedCall

use of org.jetbrains.kotlin.resolve.calls.model.ResolvedCall in project kotlin by JetBrains.

the class FunctionReferenceGenerationStrategy method doGenerateBody.

@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
    /*
         Here we need to put the arguments from our locals to the stack and invoke the referenced method. Since invocation
         of methods is highly dependent on expressions, we create a fake call expression. Then we create a new instance of
         ExpressionCodegen and, in order for it to generate code correctly, we save to its 'tempVariables' field every
         argument of our fake expression, pointing it to the corresponding index in our locals. This way generation of
         every argument boils down to calling LOAD with the corresponding index
         */
    KtCallExpression fakeExpression = CodegenUtil.constructFakeFunctionCall(state.getProject(), referencedFunction);
    final List<? extends ValueArgument> fakeArguments = fakeExpression.getValueArguments();
    final ReceiverValue dispatchReceiver = computeAndSaveReceiver(signature, codegen, referencedFunction.getDispatchReceiverParameter());
    final ReceiverValue extensionReceiver = computeAndSaveReceiver(signature, codegen, referencedFunction.getExtensionReceiverParameter());
    computeAndSaveArguments(fakeArguments, codegen);
    ResolvedCall<CallableDescriptor> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) {

        private final Map<ValueParameterDescriptor, ResolvedValueArgument> argumentMap;

        {
            argumentMap = new LinkedHashMap<ValueParameterDescriptor, ResolvedValueArgument>(fakeArguments.size());
            int index = 0;
            List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
            for (ValueArgument argument : fakeArguments) {
                argumentMap.put(parameters.get(index), new ExpressionValueArgument(argument));
                index++;
            }
        }

        @Nullable
        @Override
        public ReceiverValue getExtensionReceiver() {
            return extensionReceiver;
        }

        @Nullable
        @Override
        public ReceiverValue getDispatchReceiver() {
            return dispatchReceiver;
        }

        @NotNull
        @Override
        public List<ResolvedValueArgument> getValueArgumentsByIndex() {
            return new ArrayList<ResolvedValueArgument>(argumentMap.values());
        }

        @NotNull
        @Override
        public Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments() {
            return argumentMap;
        }
    };
    StackValue result;
    Type returnType = codegen.getReturnType();
    if (referencedFunction instanceof ConstructorDescriptor) {
        if (returnType.getSort() == Type.ARRAY) {
            //noinspection ConstantConditions
            result = codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType(), fakeResolvedCall);
        } else {
            result = codegen.generateConstructorCall(fakeResolvedCall, returnType);
        }
    } else {
        Call call = CallMaker.makeCall(fakeExpression, null, null, fakeExpression, fakeArguments);
        result = codegen.invokeFunction(call, fakeResolvedCall, StackValue.none());
    }
    InstructionAdapter v = codegen.v;
    result.put(returnType, v);
    v.areturn(returnType);
}
Also used : ResolvedValueArgument(org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument) ExpressionValueArgument(org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument) ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) DelegatingResolvedCall(org.jetbrains.kotlin.resolve.calls.model.DelegatingResolvedCall) Type(org.jetbrains.org.objectweb.asm.Type) DelegatingResolvedCall(org.jetbrains.kotlin.resolve.calls.model.DelegatingResolvedCall) InstructionAdapter(org.jetbrains.org.objectweb.asm.commons.InstructionAdapter) ExpressionValueArgument(org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument) ResolvedValueArgument(org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument) ReceiverValue(org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue)

Aggregations

ResolvedCall (org.jetbrains.kotlin.resolve.calls.model.ResolvedCall)11 NotNull (org.jetbrains.annotations.NotNull)4 PsiElement (com.intellij.psi.PsiElement)2 IElementType (com.intellij.psi.tree.IElementType)2 DeclarationDescriptor (org.jetbrains.kotlin.descriptors.DeclarationDescriptor)2 DataFlowInfoForArgumentsImpl (org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl)2 DataFlowInfo (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo)2 DataFlowValue (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue)2 KotlinType (org.jetbrains.kotlin.types.KotlinType)2 Collection (java.util.Collection)1 Nullable (org.jetbrains.annotations.Nullable)1 AccessTarget (org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.AccessTarget)1 CallableDescriptor (org.jetbrains.kotlin.descriptors.CallableDescriptor)1 PropertyDescriptor (org.jetbrains.kotlin.descriptors.PropertyDescriptor)1 VariableDescriptor (org.jetbrains.kotlin.descriptors.VariableDescriptor)1 Diagnostic (org.jetbrains.kotlin.diagnostics.Diagnostic)1 DiagnosticFactory (org.jetbrains.kotlin.diagnostics.DiagnosticFactory)1 BindingContext (org.jetbrains.kotlin.resolve.BindingContext)1 BindingTrace (org.jetbrains.kotlin.resolve.BindingTrace)1 ResolutionContext (org.jetbrains.kotlin.resolve.calls.context.ResolutionContext)1