Search in sources :

Example 66 with KotlinType

use of org.jetbrains.kotlin.types.KotlinType 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 67 with KotlinType

use of org.jetbrains.kotlin.types.KotlinType in project kotlin by JetBrains.

the class ControlStructureTypingVisitor method getTypeInfoWhenOnlyOneBranchIsPresent.

@NotNull
private KotlinTypeInfo getTypeInfoWhenOnlyOneBranchIsPresent(@NotNull KtExpression presentBranch, @NotNull LexicalWritableScope presentScope, @NotNull DataFlowInfo presentInfo, @NotNull DataFlowInfo otherInfo, @NotNull ExpressionTypingContext context, @NotNull KtIfExpression ifExpression) {
    ExpressionTypingContext newContext = context.replaceDataFlowInfo(presentInfo).replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
    KotlinTypeInfo typeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(presentScope, Collections.singletonList(presentBranch), CoercionStrategy.NO_COERCION, newContext);
    KotlinType type = typeInfo.getType();
    DataFlowInfo dataFlowInfo;
    if (type != null && KotlinBuiltIns.isNothing(type)) {
        dataFlowInfo = otherInfo;
    } else {
        dataFlowInfo = typeInfo.getDataFlowInfo().or(otherInfo);
    }
    return components.dataFlowAnalyzer.checkType(typeInfo.replaceType(components.builtIns.getUnitType()), ifExpression, context).replaceDataFlowInfo(dataFlowInfo);
}
Also used : KotlinType(org.jetbrains.kotlin.types.KotlinType) DataFlowInfo(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo) NotNull(org.jetbrains.annotations.NotNull)

Example 68 with KotlinType

use of org.jetbrains.kotlin.types.KotlinType in project kotlin by JetBrains.

the class ControlStructureTypingVisitor method visitForExpression.

public KotlinTypeInfo visitForExpression(KtForExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
    if (!isStatement)
        return components.dataFlowAnalyzer.illegalStatementType(expression, contextWithExpectedType, facade);
    ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
    // Preliminary analysis
    PreliminaryLoopVisitor loopVisitor = PreliminaryLoopVisitor.visitLoop(expression);
    context = context.replaceDataFlowInfo(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(context.dataFlowInfo, components.languageVersionSettings));
    KtExpression loopRange = expression.getLoopRange();
    KotlinType expectedParameterType = null;
    KotlinTypeInfo loopRangeInfo;
    if (loopRange != null) {
        ExpressionReceiver loopRangeReceiver = getExpressionReceiver(facade, loopRange, context.replaceScope(context.scope));
        loopRangeInfo = facade.getTypeInfo(loopRange, context);
        if (loopRangeReceiver != null) {
            expectedParameterType = components.forLoopConventionsChecker.checkIterableConvention(loopRangeReceiver, context);
        }
    } else {
        loopRangeInfo = TypeInfoFactoryKt.noTypeInfo(context);
    }
    LexicalWritableScope loopScope = newWritableScopeImpl(context, LexicalScopeKind.FOR, components.overloadChecker);
    KtParameter loopParameter = expression.getLoopParameter();
    if (loopParameter != null) {
        VariableDescriptor variableDescriptor = createLoopParameterDescriptor(loopParameter, expectedParameterType, context);
        ModifiersChecker.ModifiersCheckingProcedure modifiersCheckingProcedure = components.modifiersChecker.withTrace(context.trace);
        modifiersCheckingProcedure.checkModifiersForLocalDeclaration(loopParameter, variableDescriptor);
        components.identifierChecker.checkDeclaration(loopParameter, context.trace);
        loopScope.addVariableDescriptor(variableDescriptor);
        KtDestructuringDeclaration multiParameter = loopParameter.getDestructuringDeclaration();
        if (multiParameter != null) {
            KotlinType elementType = expectedParameterType == null ? ErrorUtils.createErrorType("Loop range has no type") : expectedParameterType;
            TransientReceiver iteratorNextAsReceiver = new TransientReceiver(elementType);
            components.annotationResolver.resolveAnnotationsWithArguments(loopScope, loopParameter.getModifierList(), context.trace);
            components.destructuringDeclarationResolver.defineLocalVariablesFromDestructuringDeclaration(loopScope, multiParameter, iteratorNextAsReceiver, loopRange, context);
            modifiersCheckingProcedure.checkModifiersForDestructuringDeclaration(multiParameter);
            components.identifierChecker.checkDeclaration(multiParameter, context.trace);
        }
    }
    KtExpression body = expression.getBody();
    KotlinTypeInfo bodyTypeInfo;
    if (body != null) {
        bodyTypeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(loopScope, Collections.singletonList(body), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(loopRangeInfo.getDataFlowInfo()));
    } else {
        bodyTypeInfo = loopRangeInfo;
    }
    return components.dataFlowAnalyzer.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType).replaceDataFlowInfo(loopRangeInfo.getDataFlowInfo());
}
Also used : KotlinType(org.jetbrains.kotlin.types.KotlinType) ExpressionReceiver(org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver) LexicalWritableScope(org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope) ModifiersChecker(org.jetbrains.kotlin.resolve.ModifiersChecker) TransientReceiver(org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver)

Example 69 with KotlinType

use of org.jetbrains.kotlin.types.KotlinType in project kotlin by JetBrains.

the class DataFlowAnalyzer method checkType.

@Nullable
public KotlinType checkType(@Nullable KotlinType expressionType, @NotNull KtExpression expressionToCheck, @NotNull ResolutionContext c, @Nullable Ref<Boolean> hasError) {
    if (hasError == null) {
        hasError = Ref.create(false);
    } else {
        hasError.set(false);
    }
    KtExpression expression = KtPsiUtil.safeDeparenthesize(expressionToCheck);
    recordExpectedType(c.trace, expression, c.expectedType);
    if (expressionType == null)
        return null;
    KotlinType result = checkTypeInternal(expressionType, expression, c, hasError);
    if (Boolean.FALSE.equals(hasError.get())) {
        for (AdditionalTypeChecker checker : additionalTypeCheckers) {
            checker.checkType(expression, expressionType, result, c);
        }
    }
    return result;
}
Also used : AdditionalTypeChecker(org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker) KotlinType(org.jetbrains.kotlin.types.KotlinType) Nullable(org.jetbrains.annotations.Nullable)

Example 70 with KotlinType

use of org.jetbrains.kotlin.types.KotlinType in project kotlin by JetBrains.

the class DataFlowAnalyzer method createCompileTimeConstantTypeInfo.

@NotNull
public KotlinTypeInfo createCompileTimeConstantTypeInfo(@NotNull CompileTimeConstant<?> value, @NotNull KtExpression expression, @NotNull ExpressionTypingContext context) {
    KotlinType expressionType;
    if (value instanceof IntegerValueTypeConstant) {
        IntegerValueTypeConstant integerValueTypeConstant = (IntegerValueTypeConstant) value;
        if (context.contextDependency == INDEPENDENT) {
            expressionType = integerValueTypeConstant.getType(context.expectedType);
            constantExpressionEvaluator.updateNumberType(expressionType, expression, context.statementFilter, context.trace);
        } else {
            expressionType = integerValueTypeConstant.getUnknownIntegerType();
        }
    } else {
        expressionType = ((TypedCompileTimeConstant<?>) value).getType();
    }
    return createCheckedTypeInfo(expressionType, context, expression);
}
Also used : KotlinType(org.jetbrains.kotlin.types.KotlinType) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

KotlinType (org.jetbrains.kotlin.types.KotlinType)110 NotNull (org.jetbrains.annotations.NotNull)34 IElementType (com.intellij.psi.tree.IElementType)16 Type (org.jetbrains.org.objectweb.asm.Type)16 Nullable (org.jetbrains.annotations.Nullable)10 JsExpression (org.jetbrains.kotlin.js.backend.ast.JsExpression)7 PsiElement (com.intellij.psi.PsiElement)6 Name (org.jetbrains.kotlin.name.Name)6 ArrayList (java.util.ArrayList)4 KtExpression (org.jetbrains.kotlin.psi.KtExpression)4 Map (java.util.Map)3 BothSignatureWriter (org.jetbrains.kotlin.codegen.signature.BothSignatureWriter)3 JvmSignatureWriter (org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter)3 VariableDescriptor (org.jetbrains.kotlin.descriptors.VariableDescriptor)3 LocalVariableDescriptor (org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor)3 DataFlowInfo (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo)3 ExpressionReceiver (org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver)3 PrimitiveType (org.jetbrains.kotlin.builtins.PrimitiveType)2 CallableDescriptor (org.jetbrains.kotlin.descriptors.CallableDescriptor)2 DeclarationDescriptor (org.jetbrains.kotlin.descriptors.DeclarationDescriptor)2