Search in sources :

Example 1 with LexicalWritableScope

use of org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope in project kotlin by JetBrains.

the class ControlStructureTypingVisitor method visitTryExpression.

@Override
public KotlinTypeInfo visitTryExpression(@NotNull KtTryExpression expression, ExpressionTypingContext typingContext) {
    ExpressionTypingContext context = typingContext.replaceContextDependency(INDEPENDENT);
    KtExpression tryBlock = expression.getTryBlock();
    List<KtCatchClause> catchClauses = expression.getCatchClauses();
    KtFinallySection finallyBlock = expression.getFinallyBlock();
    List<KotlinType> types = new ArrayList<KotlinType>();
    boolean nothingInAllCatchBranches = true;
    for (KtCatchClause catchClause : catchClauses) {
        KtParameter catchParameter = catchClause.getCatchParameter();
        KtExpression catchBody = catchClause.getCatchBody();
        boolean nothingInCatchBranch = false;
        if (catchParameter != null) {
            components.identifierChecker.checkDeclaration(catchParameter, context.trace);
            ModifiersChecker.ModifiersCheckingProcedure modifiersChecking = components.modifiersChecker.withTrace(context.trace);
            modifiersChecking.checkParameterHasNoValOrVar(catchParameter, VAL_OR_VAR_ON_CATCH_PARAMETER);
            ModifierCheckerCore.INSTANCE.check(catchParameter, context.trace, null, components.languageVersionSettings);
            VariableDescriptor variableDescriptor = components.descriptorResolver.resolveLocalVariableDescriptor(context.scope, catchParameter, context.trace);
            KotlinType catchParameterType = variableDescriptor.getType();
            if (TypeUtils.isReifiedTypeParameter(catchParameterType)) {
                context.trace.report(REIFIED_TYPE_IN_CATCH_CLAUSE.on(catchParameter));
            }
            KotlinType throwableType = components.builtIns.getThrowable().getDefaultType();
            components.dataFlowAnalyzer.checkType(catchParameterType, catchParameter, context.replaceExpectedType(throwableType));
            if (catchBody != null) {
                LexicalWritableScope catchScope = newWritableScopeImpl(context, LexicalScopeKind.CATCH, components.overloadChecker);
                catchScope.addVariableDescriptor(variableDescriptor);
                KotlinType type = facade.getTypeInfo(catchBody, context.replaceScope(catchScope)).getType();
                if (type != null) {
                    types.add(type);
                    if (KotlinBuiltIns.isNothing(type)) {
                        nothingInCatchBranch = true;
                    }
                }
            }
        }
        if (!nothingInCatchBranch) {
            nothingInAllCatchBranches = false;
        }
    }
    KotlinTypeInfo result = TypeInfoFactoryKt.noTypeInfo(context);
    KotlinTypeInfo tryResult = facade.getTypeInfo(tryBlock, context);
    if (finallyBlock != null) {
        result = facade.getTypeInfo(finallyBlock.getFinalExpression(), context.replaceExpectedType(NO_EXPECTED_TYPE));
    } else if (nothingInAllCatchBranches) {
        result = tryResult;
    }
    KotlinType type = tryResult.getType();
    if (type != null) {
        types.add(type);
    }
    if (types.isEmpty()) {
        return result.clearType();
    } else {
        return result.replaceType(CommonSupertypes.commonSupertype(types));
    }
}
Also used : KotlinType(org.jetbrains.kotlin.types.KotlinType) ArrayList(java.util.ArrayList) LexicalWritableScope(org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope) ModifiersChecker(org.jetbrains.kotlin.resolve.ModifiersChecker)

Example 2 with LexicalWritableScope

use of org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope in project kotlin by JetBrains.

the class ExpressionTypingServices method getBlockReturnedType.

@NotNull
public KotlinTypeInfo getBlockReturnedType(@NotNull KtBlockExpression expression, @NotNull CoercionStrategy coercionStrategyForLastExpression, @NotNull ExpressionTypingContext context) {
    List<KtExpression> block = StatementFilterKt.filterStatements(statementFilter, expression);
    DeclarationDescriptor containingDescriptor = context.scope.getOwnerDescriptor();
    TraceBasedLocalRedeclarationChecker redeclarationChecker = new TraceBasedLocalRedeclarationChecker(context.trace, expressionTypingComponents.overloadChecker);
    LexicalWritableScope scope = new LexicalWritableScope(context.scope, containingDescriptor, false, redeclarationChecker, LexicalScopeKind.CODE_BLOCK);
    KotlinTypeInfo r;
    if (block.isEmpty()) {
        r = expressionTypingComponents.dataFlowAnalyzer.createCheckedTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context, expression);
    } else {
        r = getBlockReturnedTypeWithWritableScope(scope, block, coercionStrategyForLastExpression, context.replaceStatementFilter(statementFilter));
    }
    scope.freeze();
    if (containingDescriptor instanceof ScriptDescriptor) {
        context.trace.record(BindingContext.SCRIPT_SCOPE, (ScriptDescriptor) containingDescriptor, scope);
    }
    return r;
}
Also used : LexicalWritableScope(org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope) TraceBasedLocalRedeclarationChecker(org.jetbrains.kotlin.resolve.scopes.TraceBasedLocalRedeclarationChecker) DeclarationDescriptor(org.jetbrains.kotlin.descriptors.DeclarationDescriptor) ScriptDescriptor(org.jetbrains.kotlin.descriptors.ScriptDescriptor) NotNull(org.jetbrains.annotations.NotNull)

Example 3 with LexicalWritableScope

use of org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope 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 4 with LexicalWritableScope

use of org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope 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 5 with LexicalWritableScope

use of org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope in project kotlin by JetBrains.

the class ControlStructureTypingVisitor method visitWhileExpression.

public KotlinTypeInfo visitWhileExpression(KtWhileExpression 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 condition = expression.getCondition();
    // Extract data flow info from condition itself without taking value into account
    DataFlowInfo dataFlowInfo = checkCondition(context.scope, condition, context);
    KtExpression body = expression.getBody();
    KotlinTypeInfo bodyTypeInfo;
    DataFlowInfo conditionInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, true, context).and(dataFlowInfo);
    if (body != null) {
        LexicalWritableScope scopeToExtend = newWritableScopeImpl(context, LexicalScopeKind.WHILE_BODY, components.overloadChecker);
        bodyTypeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(body), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(conditionInfo));
    } else {
        bodyTypeInfo = TypeInfoFactoryKt.noTypeInfo(conditionInfo);
    }
    // Condition is false at this point only if there is no jumps outside
    if (!containsJumpOutOfLoop(expression, context)) {
        dataFlowInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, false, context).and(dataFlowInfo);
    }
    // See KT-6284
    if (body != null && KtPsiUtil.isTrueConstant(condition)) {
        // We should take data flow info from the first jump point,
        // but without affecting changing variables
        dataFlowInfo = dataFlowInfo.and(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(bodyTypeInfo.getJumpFlowInfo(), components.languageVersionSettings));
    }
    return components.dataFlowAnalyzer.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType).replaceDataFlowInfo(dataFlowInfo);
}
Also used : LexicalWritableScope(org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope) DataFlowInfo(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo)

Aggregations

LexicalWritableScope (org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope)7 DataFlowInfo (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo)4 KotlinType (org.jetbrains.kotlin.types.KotlinType)3 ArrayList (java.util.ArrayList)2 NotNull (org.jetbrains.annotations.NotNull)2 ModifiersChecker (org.jetbrains.kotlin.resolve.ModifiersChecker)2 List (java.util.List)1 DeclarationDescriptor (org.jetbrains.kotlin.descriptors.DeclarationDescriptor)1 ScriptDescriptor (org.jetbrains.kotlin.descriptors.ScriptDescriptor)1 BindingContext (org.jetbrains.kotlin.resolve.BindingContext)1 MutableDataFlowInfoForArguments (org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments)1 ResolvedCall (org.jetbrains.kotlin.resolve.calls.model.ResolvedCall)1 DataFlowValue (org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue)1 LexicalScope (org.jetbrains.kotlin.resolve.scopes.LexicalScope)1 TraceBasedLocalRedeclarationChecker (org.jetbrains.kotlin.resolve.scopes.TraceBasedLocalRedeclarationChecker)1 ExpressionReceiver (org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver)1 TransientReceiver (org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver)1 ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall (org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall)1