Search in sources :

Example 6 with DataFlowInfo

use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo in project kotlin by JetBrains.

the class ExpressionTypingVisitorForStatements method visitAssignment.

@NotNull
protected KotlinTypeInfo visitAssignment(KtBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
    ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(scope).replaceContextDependency(INDEPENDENT);
    KtExpression leftOperand = expression.getLeft();
    if (leftOperand instanceof KtAnnotatedExpression) {
        basic.resolveAnnotationsOnExpression((KtAnnotatedExpression) leftOperand, context);
    }
    KtExpression left = deparenthesize(leftOperand);
    KtExpression right = expression.getRight();
    if (left instanceof KtArrayAccessExpression) {
        KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) left;
        if (right == null)
            return TypeInfoFactoryKt.noTypeInfo(context);
        KotlinTypeInfo typeInfo = basic.resolveArrayAccessSetMethod(arrayAccessExpression, right, context, context.trace);
        basic.checkLValue(context.trace, context, arrayAccessExpression, right, expression);
        return typeInfo.replaceType(checkAssignmentType(typeInfo.getType(), expression, contextWithExpectedType));
    }
    KotlinTypeInfo leftInfo = ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
    KotlinType expectedType = refineTypeFromPropertySetterIfPossible(context.trace.getBindingContext(), leftOperand, leftInfo.getType());
    DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
    KotlinTypeInfo resultInfo;
    if (right != null) {
        resultInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo).replaceExpectedType(expectedType).replaceCallPosition(new CallPosition.PropertyAssignment(leftOperand)));
        dataFlowInfo = resultInfo.getDataFlowInfo();
        KotlinType rightType = resultInfo.getType();
        if (left != null && expectedType != null && rightType != null) {
            DataFlowValue leftValue = DataFlowValueFactory.createDataFlowValue(left, expectedType, context);
            DataFlowValue rightValue = DataFlowValueFactory.createDataFlowValue(right, rightType, context);
            // We cannot say here anything new about rightValue except it has the same value as leftValue
            resultInfo = resultInfo.replaceDataFlowInfo(dataFlowInfo.assign(leftValue, rightValue, components.languageVersionSettings));
        }
    } else {
        resultInfo = leftInfo;
    }
    if (expectedType != null && leftOperand != null) {
        //if expectedType == null, some other error has been generated
        basic.checkLValue(context.trace, context, leftOperand, right, expression);
    }
    return resultInfo.replaceType(components.dataFlowAnalyzer.checkStatementType(expression, contextWithExpectedType));
}
Also used : KotlinType(org.jetbrains.kotlin.types.KotlinType) CallPosition(org.jetbrains.kotlin.resolve.calls.context.CallPosition) DataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue) DataFlowInfo(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo) NotNull(org.jetbrains.annotations.NotNull)

Example 7 with DataFlowInfo

use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo in project kotlin by JetBrains.

the class BodyResolver method resolveFunctionBody.

private void resolveFunctionBody(@NotNull DataFlowInfo outerDataFlowInfo, @NotNull BindingTrace trace, @NotNull KtDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, @NotNull LexicalScope scope, @Nullable Function1<LexicalScope, DataFlowInfo> beforeBlockBody, // Creates wrapper scope for header resolution if necessary (see resolveSecondaryConstructorBody)
@Nullable Function1<LexicalScope, LexicalScope> headerScopeFactory) {
    PreliminaryDeclarationVisitor.Companion.createForDeclaration(function, trace);
    LexicalScope innerScope = FunctionDescriptorUtil.getFunctionInnerScope(scope, functionDescriptor, trace, overloadChecker);
    List<KtParameter> valueParameters = function.getValueParameters();
    List<ValueParameterDescriptor> valueParameterDescriptors = functionDescriptor.getValueParameters();
    LexicalScope headerScope = headerScopeFactory != null ? headerScopeFactory.invoke(innerScope) : innerScope;
    valueParameterResolver.resolveValueParameters(valueParameters, valueParameterDescriptors, headerScope, outerDataFlowInfo, trace);
    // Synthetic "field" creation
    if (functionDescriptor instanceof PropertyAccessorDescriptor && functionDescriptor.getExtensionReceiverParameter() == null) {
        PropertyAccessorDescriptor accessorDescriptor = (PropertyAccessorDescriptor) functionDescriptor;
        KtProperty property = (KtProperty) function.getParent();
        final SyntheticFieldDescriptor fieldDescriptor = new SyntheticFieldDescriptor(accessorDescriptor, property);
        innerScope = new LexicalScopeImpl(innerScope, functionDescriptor, true, null, LexicalScopeKind.PROPERTY_ACCESSOR_BODY, LocalRedeclarationChecker.DO_NOTHING.INSTANCE, new Function1<LexicalScopeImpl.InitializeHandler, Unit>() {

            @Override
            public Unit invoke(LexicalScopeImpl.InitializeHandler handler) {
                handler.addVariableDescriptor(fieldDescriptor);
                return Unit.INSTANCE;
            }
        });
        // Check parameter name shadowing
        for (KtParameter parameter : function.getValueParameters()) {
            if (SyntheticFieldDescriptor.NAME.equals(parameter.getNameAsName())) {
                trace.report(Errors.ACCESSOR_PARAMETER_NAME_SHADOWING.on(parameter));
            }
        }
    }
    DataFlowInfo dataFlowInfo = null;
    if (beforeBlockBody != null) {
        dataFlowInfo = beforeBlockBody.invoke(headerScope);
    }
    if (function.hasBody()) {
        expressionTypingServices.checkFunctionReturnType(innerScope, function, functionDescriptor, dataFlowInfo != null ? dataFlowInfo : outerDataFlowInfo, null, trace);
    }
    assert functionDescriptor.getReturnType() != null;
}
Also used : SyntheticFieldDescriptor(org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor) Function1(kotlin.jvm.functions.Function1) DataFlowInfo(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo)

Example 8 with DataFlowInfo

use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo in project kotlin by JetBrains.

the class BasicExpressionTypingVisitor method visitBooleanOperationExpression.

@NotNull
private KotlinTypeInfo visitBooleanOperationExpression(@Nullable IElementType operationType, @Nullable KtExpression left, @Nullable KtExpression right, @NotNull ExpressionTypingContext context) {
    KotlinType booleanType = components.builtIns.getBooleanType();
    KotlinTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context.replaceExpectedType(booleanType), facade);
    DataFlowInfo dataFlowInfo = leftTypeInfo.getDataFlowInfo();
    LexicalWritableScope leftScope = newWritableScopeImpl(context, LexicalScopeKind.LEFT_BOOLEAN_EXPRESSION, facade.getComponents().overloadChecker);
    // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
    boolean isAnd = operationType == KtTokens.ANDAND;
    DataFlowInfo flowInfoLeft = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(left, isAnd, context).and(dataFlowInfo);
    LexicalWritableScope rightScope = isAnd ? leftScope : newWritableScopeImpl(context, LexicalScopeKind.RIGHT_BOOLEAN_EXPRESSION, facade.getComponents().overloadChecker);
    ExpressionTypingContext contextForRightExpr = context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope).replaceExpectedType(booleanType);
    if (right != null) {
        facade.getTypeInfo(right, contextForRightExpr);
    }
    return leftTypeInfo.replaceType(booleanType);
}
Also used : LexicalWritableScope(org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope) DataFlowInfo(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo) NotNull(org.jetbrains.annotations.NotNull)

Example 9 with DataFlowInfo

use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo in project kotlin by JetBrains.

the class BasicExpressionTypingVisitor method visitElvisExpression.

@NotNull
private KotlinTypeInfo visitElvisExpression(@NotNull KtBinaryExpression expression, @NotNull ExpressionTypingContext contextWithExpectedType) {
    ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
    KtExpression left = expression.getLeft();
    KtExpression right = expression.getRight();
    if (left == null || right == null) {
        getTypeInfoOrNullType(left, context, facade);
        return TypeInfoFactoryKt.noTypeInfo(context);
    }
    Call call = createCallForSpecialConstruction(expression, expression.getOperationReference(), Lists.newArrayList(left, right));
    ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(call, ResolveConstruct.ELVIS, Lists.newArrayList("left", "right"), Lists.newArrayList(true, false), contextWithExpectedType, null);
    KotlinTypeInfo leftTypeInfo = BindingContextUtils.getRecordedTypeInfo(left, context.trace.getBindingContext());
    if (ArgumentTypeResolver.isFunctionLiteralArgument(left, context)) {
        context.trace.report(USELESS_ELVIS_ON_LAMBDA_EXPRESSION.on(expression.getOperationReference()));
        if (leftTypeInfo == null)
            return TypeInfoFactoryKt.noTypeInfo(context);
    }
    assert leftTypeInfo != null : "Left expression was not processed: " + expression;
    KotlinType leftType = leftTypeInfo.getType();
    if (leftType != null && isKnownToBeNotNull(left, leftType, context)) {
        context.trace.report(USELESS_ELVIS.on(expression, leftType));
    } else if (KtPsiUtil.isNullConstant(right) && leftType != null && !FlexibleTypesKt.isNullabilityFlexible(leftType)) {
        context.trace.report(USELESS_ELVIS_RIGHT_IS_NULL.on(expression));
    }
    KotlinTypeInfo rightTypeInfo = BindingContextUtils.getRecordedTypeInfo(right, context.trace.getBindingContext());
    if (rightTypeInfo == null && ArgumentTypeResolver.isFunctionLiteralArgument(right, context)) {
        // the type is computed later in call completer according to the '?:' semantics as a function
        return TypeInfoFactoryKt.noTypeInfo(context);
    }
    assert rightTypeInfo != null : "Right expression was not processed: " + expression;
    boolean loopBreakContinuePossible = leftTypeInfo.getJumpOutPossible() || rightTypeInfo.getJumpOutPossible();
    KotlinType rightType = rightTypeInfo.getType();
    // Only left argument DFA is taken into account here: we cannot be sure that right argument is joined
    // (we merge it with right DFA if right argument contains no jump outside)
    DataFlowInfo dataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getInfo(call.getValueArguments().get(1));
    KotlinType type = resolvedCall.getResultingDescriptor().getReturnType();
    if (type == null || rightType == null || leftType == null && KotlinBuiltIns.isNothing(rightType))
        return TypeInfoFactoryKt.noTypeInfo(dataFlowInfo);
    if (leftType != null) {
        DataFlowValue leftValue = createDataFlowValue(left, leftType, context);
        DataFlowInfo rightDataFlowInfo = resolvedCall.getDataFlowInfoForArguments().getResultInfo();
        boolean jumpInRight = KotlinBuiltIns.isNothing(rightType);
        DataFlowValue nullValue = DataFlowValue.nullValue(components.builtIns);
        // left argument is considered not-null if it's not-null also in right part or if we have jump in right part
        if (jumpInRight || !rightDataFlowInfo.getStableNullability(leftValue).canBeNull()) {
            dataFlowInfo = dataFlowInfo.disequate(leftValue, nullValue, components.languageVersionSettings);
            if (left instanceof KtBinaryExpressionWithTypeRHS) {
                dataFlowInfo = establishSubtypingForTypeRHS((KtBinaryExpressionWithTypeRHS) left, dataFlowInfo, context, components.languageVersionSettings);
            }
        }
        DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(expression, type, context);
        dataFlowInfo = dataFlowInfo.assign(resultValue, leftValue, components.languageVersionSettings).disequate(resultValue, nullValue, components.languageVersionSettings);
        if (!jumpInRight) {
            DataFlowValue rightValue = DataFlowValueFactory.createDataFlowValue(right, rightType, context);
            rightDataFlowInfo = rightDataFlowInfo.assign(resultValue, rightValue, components.languageVersionSettings);
            dataFlowInfo = dataFlowInfo.or(rightDataFlowInfo);
        }
    }
    // but result is not nullable if the right type is not nullable
    if (!TypeUtils.isNullableType(rightType) && TypeUtils.isNullableType(type)) {
        type = TypeUtils.makeNotNullable(type);
    }
    if (context.contextDependency == DEPENDENT) {
        return TypeInfoFactoryKt.createTypeInfo(type, dataFlowInfo);
    }
    // If break or continue was possible, take condition check info as the jump info
    return TypeInfoFactoryKt.createTypeInfo(components.dataFlowAnalyzer.checkType(type, expression, contextWithExpectedType), dataFlowInfo, loopBreakContinuePossible, context.dataFlowInfo);
}
Also used : ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) DataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue) DataFlowValueFactory.createDataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue) DataFlowInfo(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo) NotNull(org.jetbrains.annotations.NotNull)

Example 10 with DataFlowInfo

use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo in project kotlin by JetBrains.

the class BasicExpressionTypingVisitor method visitEquality.

private KotlinTypeInfo visitEquality(KtBinaryExpression expression, ExpressionTypingContext context, KtSimpleNameExpression operationSign, final KtExpression left, final KtExpression right) {
    if (right == null || left == null) {
        ExpressionTypingUtils.getTypeInfoOrNullType(right, context, facade);
        ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade);
        return TypeInfoFactoryKt.createTypeInfo(components.builtIns.getBooleanType(), context);
    }
    KotlinTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade);
    DataFlowInfo dataFlowInfo = leftTypeInfo.getDataFlowInfo();
    ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
    KotlinTypeInfo rightTypeInfo = facade.getTypeInfo(right, contextWithDataFlow);
    TemporaryBindingTrace traceInterpretingRightAsNullableAny = TemporaryBindingTrace.create(context.trace, "trace to resolve 'equals(Any?)' interpreting as of type Any? an expression:", right);
    traceInterpretingRightAsNullableAny.recordType(right, components.builtIns.getNullableAnyType());
    // Nothing? has no members, and `equals()` would be unresolved on it
    KotlinType leftType = leftTypeInfo.getType();
    if (leftType != null && KotlinBuiltIns.isNothingOrNullableNothing(leftType)) {
        traceInterpretingRightAsNullableAny.recordType(left, components.builtIns.getNullableAnyType());
    }
    ExpressionTypingContext newContext = context.replaceBindingTrace(traceInterpretingRightAsNullableAny);
    ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, newContext);
    Call call = CallMaker.makeCallWithExpressions(expression, receiver, // semantically, a call to `==` is a safe call
    new KtPsiFactory(expression.getProject()).createSafeCallNode(), operationSign, Collections.singletonList(right));
    OverloadResolutionResults<FunctionDescriptor> resolutionResults = components.callResolver.resolveCallWithGivenName(newContext, call, operationSign, OperatorNameConventions.EQUALS);
    traceInterpretingRightAsNullableAny.commit(new TraceEntryFilter() {

        @Override
        public boolean accept(@Nullable WritableSlice<?, ?> slice, Object key) {
            // the type of the right (and sometimes left) expression isn't 'Any?' actually
            if ((key == right || key == left) && slice == EXPRESSION_TYPE_INFO)
                return false;
            return true;
        }
    }, true);
    if (resolutionResults.isSuccess()) {
        FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor();
        if (ensureBooleanResult(operationSign, OperatorNameConventions.EQUALS, equals.getReturnType(), context)) {
            ensureNonemptyIntersectionOfOperandTypes(expression, context);
        }
    } else {
        if (resolutionResults.isAmbiguity()) {
            context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResultingCalls()));
        } else {
            context.trace.report(EQUALS_MISSING.on(operationSign));
        }
    }
    return rightTypeInfo.replaceType(components.builtIns.getBooleanType());
}
Also used : ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) ExpressionReceiver(org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver) DataFlowInfo(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo)

Aggregations

DataFlowInfo (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo)16 DataFlowValue (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue)6 NotNull (org.jetbrains.annotations.NotNull)5 ResolvedCall (org.jetbrains.kotlin.resolve.calls.model.ResolvedCall)4 LexicalWritableScope (org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope)4 DataFlowValueFactory.createDataFlowValue (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue)3 KotlinType (org.jetbrains.kotlin.types.KotlinType)3 ExpressionReceiver (org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver)2 PsiElement (com.intellij.psi.PsiElement)1 IElementType (com.intellij.psi.tree.IElementType)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 Function1 (kotlin.jvm.functions.Function1)1 SyntheticFieldDescriptor (org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor)1 ValueArgument (org.jetbrains.kotlin.psi.ValueArgument)1 BindingContext (org.jetbrains.kotlin.resolve.BindingContext)1 CallPosition (org.jetbrains.kotlin.resolve.calls.context.CallPosition)1 MutableDataFlowInfoForArguments (org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments)1 LexicalScope (org.jetbrains.kotlin.resolve.scopes.LexicalScope)1 ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall (org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall)1