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));
}
}
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;
}
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);
}
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);
}
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);
}
Aggregations