Search in sources :

Example 1 with DataFlowValueFactory.createDataFlowValue

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

the class BasicExpressionTypingVisitor method visitParenthesizedExpression.

@Override
public KotlinTypeInfo visitParenthesizedExpression(@NotNull KtParenthesizedExpression expression, ExpressionTypingContext context) {
    KtExpression innerExpression = expression.getExpression();
    if (innerExpression == null) {
        return TypeInfoFactoryKt.noTypeInfo(context);
    }
    KotlinTypeInfo result = facade.getTypeInfo(innerExpression, context.replaceScope(context.scope));
    KotlinType resultType = result.getType();
    if (resultType != null) {
        DataFlowValue innerValue = DataFlowValueFactory.createDataFlowValue(innerExpression, resultType, context);
        DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(expression, resultType, context);
        result = result.replaceDataFlowInfo(result.getDataFlowInfo().assign(resultValue, innerValue, components.languageVersionSettings));
    }
    return result;
}
Also used : DataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue) DataFlowValueFactory.createDataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue)

Example 2 with DataFlowValueFactory.createDataFlowValue

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

the class BasicExpressionTypingVisitor method checkNull.

private static void checkNull(@NotNull KtSimpleNameExpression expression, @NotNull ExpressionTypingContext context, @Nullable KotlinType type) {
    // Receivers are normally analyzed at resolve, with an exception of KT-10175
    if (type != null && !type.isError() && !isLValueOrUnsafeReceiver(expression)) {
        DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, type, context);
        Nullability nullability = context.dataFlowInfo.getStableNullability(dataFlowValue);
        if (!nullability.canBeNonNull() && nullability.canBeNull()) {
            if (isDangerousWithNull(expression, context)) {
                context.trace.report(ALWAYS_NULL.on(expression));
            } else {
                context.trace.record(SMARTCAST_NULL, expression);
            }
        }
    }
}
Also used : DataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue) DataFlowValueFactory.createDataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue) Nullability(org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability)

Example 3 with DataFlowValueFactory.createDataFlowValue

use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue 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 4 with DataFlowValueFactory.createDataFlowValue

use of org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue 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)

Aggregations

DataFlowValue (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue)4 DataFlowValueFactory.createDataFlowValue (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue)4 ResolvedCall (org.jetbrains.kotlin.resolve.calls.model.ResolvedCall)2 IElementType (com.intellij.psi.tree.IElementType)1 NotNull (org.jetbrains.annotations.NotNull)1 Name (org.jetbrains.kotlin.name.Name)1 DataFlowInfo (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo)1 Nullability (org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability)1 ExpressionReceiver (org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver)1