Search in sources :

Example 6 with DataFlowValue

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

the class BasicExpressionTypingVisitor method visitUnaryExpression.

@Override
public KotlinTypeInfo visitUnaryExpression(@NotNull KtUnaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
    ExpressionTypingContext context = isUnaryExpressionDependentOnExpectedType(expression) ? contextWithExpectedType : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
    KtExpression baseExpression = expression.getBaseExpression();
    if (baseExpression == null)
        return TypeInfoFactoryKt.noTypeInfo(context);
    KtSimpleNameExpression operationSign = expression.getOperationReference();
    IElementType operationType = operationSign.getReferencedNameElementType();
    // Special case for expr!!
    if (operationType == KtTokens.EXCLEXCL) {
        return visitExclExclExpression(expression, context);
    }
    // Type check the base expression
    KotlinTypeInfo typeInfo = facade.safeGetTypeInfo(baseExpression, context);
    KotlinType type = ExpressionTypingUtils.safeGetType(typeInfo);
    ExpressionReceiver receiver = ExpressionReceiver.Companion.create(baseExpression, type, context.trace.getBindingContext());
    Call call = CallMaker.makeCall(receiver, expression);
    // Conventions for unary operations
    Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
    if (name == null) {
        context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression"));
        return typeInfo.clearType();
    }
    // a[i]++/-- takes special treatment because it is actually let j = i, arr = a in arr.set(j, a.get(j).inc())
    if ((operationType == KtTokens.PLUSPLUS || operationType == KtTokens.MINUSMINUS) && baseExpression instanceof KtArrayAccessExpression) {
        KtExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "e", type);
        TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve array access set method for unary expression", expression);
        ExpressionTypingContext newContext = context.replaceBindingTrace(temporaryBindingTrace);
        resolveImplicitArrayAccessSetMethod((KtArrayAccessExpression) baseExpression, stubExpression, newContext, context.trace);
    }
    // Resolve the operation reference
    OverloadResolutionResults<FunctionDescriptor> resolutionResults = components.callResolver.resolveCallWithGivenName(context, call, expression.getOperationReference(), name);
    if (!resolutionResults.isSuccess()) {
        return typeInfo.clearType();
    }
    // Computing the return type
    KotlinType returnType = resolutionResults.getResultingDescriptor().getReturnType();
    KotlinType result;
    if (operationType == KtTokens.PLUSPLUS || operationType == KtTokens.MINUSMINUS) {
        assert returnType != null : "returnType is null for " + resolutionResults.getResultingDescriptor();
        if (KotlinBuiltIns.isUnit(returnType)) {
            result = ErrorUtils.createErrorType(components.builtIns.getUnit().getName().asString());
            context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign));
        } else {
            KotlinType receiverType = receiver.getType();
            if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(returnType, receiverType)) {
                context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name.asString(), receiverType, returnType));
            } else {
                context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
                KtExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "e", type);
                checkLValue(context.trace, context, baseExpression, stubExpression, expression);
            }
            // x++ type is x type, but ++x type is x.inc() type
            DataFlowValue receiverValue = DataFlowValueFactory.createDataFlowValue((ReceiverValue) call.getExplicitReceiver(), contextWithExpectedType);
            if (expression instanceof KtPrefixExpression) {
                result = returnType;
            } else {
                result = receiverType;
                // Also record data flow information for x++ value (= x)
                DataFlowValue returnValue = DataFlowValueFactory.createDataFlowValue(expression, receiverType, contextWithExpectedType);
                typeInfo = typeInfo.replaceDataFlowInfo(typeInfo.getDataFlowInfo().assign(returnValue, receiverValue, components.languageVersionSettings));
            }
        }
    } else {
        result = returnType;
    }
    CompileTimeConstant<?> value = components.constantExpressionEvaluator.evaluateExpression(expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType);
    if (value != null) {
        return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
    }
    return components.dataFlowAnalyzer.checkType(typeInfo.replaceType(result), expression, contextWithExpectedType.replaceDataFlowInfo(typeInfo.getDataFlowInfo()));
}
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) Name(org.jetbrains.kotlin.name.Name) IElementType(com.intellij.psi.tree.IElementType) ExpressionReceiver(org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver)

Example 7 with DataFlowValue

use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue 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 8 with DataFlowValue

use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue 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 9 with DataFlowValue

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

the class ControlStructureTypingVisitor method visitIfExpression.

public KotlinTypeInfo visitIfExpression(KtIfExpression ifExpression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
    components.dataFlowAnalyzer.recordExpectedType(contextWithExpectedType.trace, ifExpression, contextWithExpectedType.expectedType);
    ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
    KtExpression condition = ifExpression.getCondition();
    DataFlowInfo conditionDataFlowInfo = checkCondition(context.scope, condition, context);
    boolean loopBreakContinuePossibleInCondition = condition != null && containsJumpOutOfLoop(condition, context);
    KtExpression elseBranch = ifExpression.getElse();
    KtExpression thenBranch = ifExpression.getThen();
    LexicalWritableScope thenScope = newWritableScopeImpl(context, LexicalScopeKind.THEN, components.overloadChecker);
    LexicalWritableScope elseScope = newWritableScopeImpl(context, LexicalScopeKind.ELSE, components.overloadChecker);
    DataFlowInfo thenInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, true, context).and(conditionDataFlowInfo);
    DataFlowInfo elseInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
    if (elseBranch == null) {
        if (thenBranch != null) {
            KotlinTypeInfo result = getTypeInfoWhenOnlyOneBranchIsPresent(thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression);
            // If jump was possible, take condition check info as the jump info
            return result.getJumpOutPossible() ? result.replaceJumpOutPossible(true).replaceJumpFlowInfo(conditionDataFlowInfo) : result;
        }
        return TypeInfoFactoryKt.createTypeInfo(components.builtIns.getUnitType(), thenInfo.or(elseInfo));
    }
    if (thenBranch == null) {
        return getTypeInfoWhenOnlyOneBranchIsPresent(elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression);
    }
    KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(ifExpression);
    KtBlockExpression thenBlock = psiFactory.wrapInABlockWrapper(thenBranch);
    KtBlockExpression elseBlock = psiFactory.wrapInABlockWrapper(elseBranch);
    Call callForIf = createCallForSpecialConstruction(ifExpression, ifExpression, Lists.newArrayList(thenBlock, elseBlock));
    MutableDataFlowInfoForArguments dataFlowInfoForArguments = createDataFlowInfoForArgumentsForIfCall(callForIf, conditionDataFlowInfo, thenInfo, elseInfo);
    ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(callForIf, ResolveConstruct.IF, Lists.newArrayList("thenBranch", "elseBranch"), Lists.newArrayList(false, false), contextWithExpectedType, dataFlowInfoForArguments);
    BindingContext bindingContext = context.trace.getBindingContext();
    KotlinTypeInfo thenTypeInfo = BindingContextUtils.getRecordedTypeInfo(thenBranch, bindingContext);
    KotlinTypeInfo elseTypeInfo = BindingContextUtils.getRecordedTypeInfo(elseBranch, bindingContext);
    assert thenTypeInfo != null || elseTypeInfo != null : "Both branches of if expression were not processed: " + ifExpression.getText();
    KotlinType resultType = resolvedCall.getResultingDescriptor().getReturnType();
    boolean loopBreakContinuePossible = loopBreakContinuePossibleInCondition;
    DataFlowInfo resultDataFlowInfo;
    if (elseTypeInfo == null) {
        loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible();
        resultDataFlowInfo = thenTypeInfo.getDataFlowInfo();
    } else if (thenTypeInfo == null) {
        loopBreakContinuePossible |= elseTypeInfo.getJumpOutPossible();
        resultDataFlowInfo = elseTypeInfo.getDataFlowInfo();
    } else {
        KotlinType thenType = thenTypeInfo.getType();
        KotlinType elseType = elseTypeInfo.getType();
        DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
        DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
        if (resultType != null && thenType != null && elseType != null) {
            DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(ifExpression, resultType, context);
            DataFlowValue thenValue = DataFlowValueFactory.createDataFlowValue(thenBranch, thenType, context);
            thenDataFlowInfo = thenDataFlowInfo.assign(resultValue, thenValue, components.languageVersionSettings);
            DataFlowValue elseValue = DataFlowValueFactory.createDataFlowValue(elseBranch, elseType, context);
            elseDataFlowInfo = elseDataFlowInfo.assign(resultValue, elseValue, components.languageVersionSettings);
        }
        loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible() || elseTypeInfo.getJumpOutPossible();
        boolean jumpInThen = thenType != null && KotlinBuiltIns.isNothing(thenType);
        boolean jumpInElse = elseType != null && KotlinBuiltIns.isNothing(elseType);
        if (thenType == null && elseType == null) {
            resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
        } else if (thenType == null || (jumpInThen && !jumpInElse)) {
            resultDataFlowInfo = elseDataFlowInfo;
        } else if (elseType == null || (jumpInElse && !jumpInThen)) {
            resultDataFlowInfo = thenDataFlowInfo;
        } else {
            resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
        }
        if (thenType == null && jumpInElse || elseType == null && jumpInThen) {
            return TypeInfoFactoryKt.noTypeInfo(resultDataFlowInfo);
        }
    }
    // If break or continue was possible, take condition check info as the jump info
    return TypeInfoFactoryKt.createTypeInfo(components.dataFlowAnalyzer.checkType(resultType, ifExpression, contextWithExpectedType), resultDataFlowInfo, loopBreakContinuePossible, loopBreakContinuePossibleInCondition ? context.dataFlowInfo : conditionDataFlowInfo);
}
Also used : ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall(org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall) KotlinType(org.jetbrains.kotlin.types.KotlinType) MutableDataFlowInfoForArguments(org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments) BindingContext(org.jetbrains.kotlin.resolve.BindingContext) DataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue) LexicalWritableScope(org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope) DataFlowInfo(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo)

Example 10 with DataFlowValue

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

the class ExpressionTypingServices method getBlockReturnedTypeWithWritableScope.

/**
     * Visits block statements propagating data flow information from the first to the last.
     * Determines block returned type and data flow information at the end of the block AND
     * at the nearest jump point from the block beginning.
     */
/*package*/
KotlinTypeInfo getBlockReturnedTypeWithWritableScope(@NotNull LexicalWritableScope scope, @NotNull List<? extends KtElement> block, @NotNull CoercionStrategy coercionStrategyForLastExpression, @NotNull ExpressionTypingContext context) {
    if (block.isEmpty()) {
        return TypeInfoFactoryKt.createTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context);
    }
    ExpressionTypingInternals blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock(expressionTypingComponents, annotationChecker, scope);
    ExpressionTypingContext newContext = context.replaceScope(scope).replaceExpectedType(NO_EXPECTED_TYPE);
    KotlinTypeInfo result = TypeInfoFactoryKt.noTypeInfo(context);
    // Jump point data flow info
    DataFlowInfo beforeJumpInfo = newContext.dataFlowInfo;
    boolean jumpOutPossible = false;
    for (Iterator<? extends KtElement> iterator = block.iterator(); iterator.hasNext(); ) {
        KtElement statement = iterator.next();
        if (!(statement instanceof KtExpression)) {
            continue;
        }
        KtExpression statementExpression = (KtExpression) statement;
        if (!iterator.hasNext()) {
            result = getTypeOfLastExpressionInBlock(statementExpression, newContext.replaceExpectedType(context.expectedType), coercionStrategyForLastExpression, blockLevelVisitor);
            if (result.getType() != null && statementExpression.getParent() instanceof KtBlockExpression) {
                DataFlowValue lastExpressionValue = DataFlowValueFactory.createDataFlowValue(statementExpression, result.getType(), context);
                DataFlowValue blockExpressionValue = DataFlowValueFactory.createDataFlowValue((KtBlockExpression) statementExpression.getParent(), result.getType(), context);
                result = result.replaceDataFlowInfo(result.getDataFlowInfo().assign(blockExpressionValue, lastExpressionValue, expressionTypingComponents.languageVersionSettings));
            }
        } else {
            result = blockLevelVisitor.getTypeInfo(statementExpression, newContext.replaceContextDependency(ContextDependency.INDEPENDENT), true);
        }
        DataFlowInfo newDataFlowInfo = result.getDataFlowInfo();
        // If jump is not possible, we take new data flow info before jump
        if (!jumpOutPossible) {
            beforeJumpInfo = result.getJumpFlowInfo();
            jumpOutPossible = result.getJumpOutPossible();
        }
        if (newDataFlowInfo != context.dataFlowInfo) {
            newContext = newContext.replaceDataFlowInfo(newDataFlowInfo);
        // We take current data flow info if jump there is not possible
        }
        blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock(expressionTypingComponents, annotationChecker, scope);
    }
    return result.replaceJumpOutPossible(jumpOutPossible).replaceJumpFlowInfo(beforeJumpInfo);
}
Also used : DataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue) DataFlowInfo(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo)

Aggregations

DataFlowValue (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue)10 DataFlowValueFactory.createDataFlowValue (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue)7 DataFlowInfo (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo)6 ResolvedCall (org.jetbrains.kotlin.resolve.calls.model.ResolvedCall)4 IElementType (com.intellij.psi.tree.IElementType)3 NotNull (org.jetbrains.annotations.NotNull)3 KotlinType (org.jetbrains.kotlin.types.KotlinType)2 Name (org.jetbrains.kotlin.name.Name)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 Nullability (org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability)1 LexicalWritableScope (org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope)1 ExpressionReceiver (org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver)1 ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall (org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall)1