@NotNull public TypeInfoForCall getQualifiedExpressionExtendedTypeInfo( @NotNull JetQualifiedExpression expression, @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode) { // TODO : functions as values JetExpression selectorExpression = expression.getSelectorExpression(); JetExpression receiverExpression = expression.getReceiverExpression(); JetTypeInfo receiverTypeInfo = expressionTypingServices.getTypeInfoWithNamespaces( receiverExpression, context.scope, NO_EXPECTED_TYPE, context.dataFlowInfo, context.trace); JetType receiverType = receiverTypeInfo.getType(); if (selectorExpression == null) return TypeInfoForCall.create(null, context.dataFlowInfo); if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText()); context = context.replaceDataFlowInfo(receiverTypeInfo.getDataFlowInfo()); if (selectorExpression instanceof JetSimpleNameExpression) { ConstantUtils.propagateConstantValues( expression, context.trace, (JetSimpleNameExpression) selectorExpression); } TypeInfoForCall selectorReturnTypeInfo = getSelectorReturnTypeInfo( new ExpressionReceiver(receiverExpression, receiverType), expression.getOperationTokenNode(), selectorExpression, context, resolveMode); JetType selectorReturnType = selectorReturnTypeInfo.getType(); // TODO move further if (!(receiverType instanceof NamespaceType) && expression.getOperationSign() == JetTokens.SAFE_ACCESS) { if (selectorReturnType != null && !selectorReturnType.isNullable() && !KotlinBuiltIns.getInstance().isUnit(selectorReturnType)) { if (receiverType.isNullable()) { selectorReturnType = TypeUtils.makeNullable(selectorReturnType); } } } // TODO : this is suspicious: remove this code? if (selectorReturnType != null) { context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, selectorReturnType); } JetTypeInfo typeInfo = JetTypeInfo.create(selectorReturnType, selectorReturnTypeInfo.getDataFlowInfo()); if (resolveMode == ResolveMode.TOP_LEVEL_CALL) { DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo()); } return TypeInfoForCall.create(typeInfo, selectorReturnTypeInfo); }
private boolean typeMustBeNullable( @NotNull JetType autoType, @NotNull List<TypeAndVariance> typesFromSuper, @NotNull TypeUsage howThisTypeIsUsed) { boolean someSupersNotCovariantNullable = false; boolean someSupersCovariantNullable = false; boolean someSupersNotNull = false; for (TypeAndVariance typeFromSuper : typesFromSuper) { if (!typeFromSuper.type.isNullable()) { someSupersNotNull = true; } else { if (typeFromSuper.varianceOfPosition == Variance.OUT_VARIANCE) { someSupersCovariantNullable = true; } else { someSupersNotCovariantNullable = true; } } } if (someSupersNotNull && someSupersNotCovariantNullable) { reportError("Incompatible types in superclasses: " + typesFromSuper); return autoType.isNullable(); } else if (someSupersNotNull) { return false; } else if (someSupersNotCovariantNullable || someSupersCovariantNullable) { boolean annotatedAsNotNull = howThisTypeIsUsed != TYPE_ARGUMENT && !autoType.isNullable(); if (annotatedAsNotNull && someSupersNotCovariantNullable) { reportError( "In superclass type is nullable: " + typesFromSuper + ", in subclass it is not: " + autoType); return true; } return !annotatedAsNotNull; } return autoType.isNullable(); }
@NotNull private String renderDefaultType(@NotNull JetType type) { StringBuilder sb = new StringBuilder(); sb.append(renderTypeName(type.getConstructor())); if (!type.getArguments().isEmpty()) { sb.append("<"); appendTypeProjections(type.getArguments(), sb); sb.append(">"); } if (type.isNullable()) { sb.append("?"); } return sb.toString(); }
@NotNull private String renderFunctionType(@NotNull JetType type) { StringBuilder sb = new StringBuilder(); JetType receiverType = KotlinBuiltIns.getInstance().getReceiverType(type); if (receiverType != null) { sb.append(renderType(receiverType)); sb.append("."); } sb.append("("); appendTypeProjections( KotlinBuiltIns.getInstance().getParameterTypeProjectionsFromFunctionType(type), sb); sb.append(") " + arrow() + " "); sb.append(renderType(KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(type))); if (type.isNullable()) { return "(" + sb + ")?"; } return sb.toString(); }