@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>(); for (KtCatchClause catchClause : catchClauses) { KtParameter catchParameter = catchClause.getCatchParameter(); KtExpression catchBody = catchClause.getCatchBody(); 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); VariableDescriptor variableDescriptor = components.descriptorResolver.resolveLocalVariableDescriptor( context.scope, catchParameter, context.trace); KotlinType throwableType = components.builtIns.getThrowable().getDefaultType(); components.dataFlowAnalyzer.checkType( variableDescriptor.getType(), catchParameter, context.replaceExpectedType(throwableType)); if (catchBody != null) { LexicalWritableScope catchScope = newWritableScopeImpl(context, "Catch scope"); catchScope.addVariableDescriptor(variableDescriptor); KotlinType type = facade.getTypeInfo(catchBody, context.replaceScope(catchScope)).getType(); if (type != null) { types.add(type); } } } } KotlinTypeInfo result = TypeInfoFactoryKt.noTypeInfo(context); if (finallyBlock != null) { result = facade.getTypeInfo( finallyBlock.getFinalExpression(), context.replaceExpectedType(NO_EXPECTED_TYPE)); } KotlinType type = facade.getTypeInfo(tryBlock, context).getType(); if (type != null) { types.add(type); } if (types.isEmpty()) { return result.clearType(); } else { return result.replaceType(CommonSupertypes.commonSupertype(types)); } }
/** * 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)); } } 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); }