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