@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 List<ValueParameterDescriptor> createValueParameterDescriptors( ExpressionTypingContext context, JetFunctionLiteral functionLiteral, FunctionDescriptorImpl functionDescriptor, boolean functionTypeExpected) { List<ValueParameterDescriptor> valueParameterDescriptors = Lists.newArrayList(); List<JetParameter> declaredValueParameters = functionLiteral.getValueParameters(); List<ValueParameterDescriptor> expectedValueParameters = (functionTypeExpected) ? JetStandardClasses.getValueParameters(functionDescriptor, context.expectedType) : null; boolean hasDeclaredValueParameters = functionLiteral.getValueParameterList() != null; if (functionTypeExpected && !hasDeclaredValueParameters && expectedValueParameters.size() == 1) { ValueParameterDescriptor valueParameterDescriptor = expectedValueParameters.get(0); ValueParameterDescriptor it = new ValueParameterDescriptorImpl( functionDescriptor, 0, Collections.<AnnotationDescriptor>emptyList(), "it", false, valueParameterDescriptor.getOutType(), valueParameterDescriptor.hasDefaultValue(), valueParameterDescriptor.getVarargElementType()); valueParameterDescriptors.add(it); context.trace.record(AUTO_CREATED_IT, it); } else { for (int i = 0; i < declaredValueParameters.size(); i++) { JetParameter declaredParameter = declaredValueParameters.get(i); JetTypeReference typeReference = declaredParameter.getTypeReference(); JetType type; if (typeReference != null) { type = context.getTypeResolver().resolveType(context.scope, typeReference); } else { if (expectedValueParameters != null && i < expectedValueParameters.size()) { type = expectedValueParameters.get(i).getOutType(); } else { context.trace.report(CANNOT_INFER_PARAMETER_TYPE.on(declaredParameter)); type = ErrorUtils.createErrorType("Cannot be inferred"); } } ValueParameterDescriptor valueParameterDescriptor = context .getDescriptorResolver() .resolveValueParameterDescriptor(functionDescriptor, declaredParameter, i, type); valueParameterDescriptors.add(valueParameterDescriptor); } } return valueParameterDescriptors; }
private boolean furtherNameLookup( @NotNull JetSimpleNameExpression expression, @NotNull JetType[] result, @NotNull ResolutionContext context) { NamespaceType namespaceType = lookupNamespaceType(expression, context); if (namespaceType == null) { return false; } if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT) { result[0] = namespaceType; return true; } context.trace.report(EXPRESSION_EXPECTED_NAMESPACE_FOUND.on(expression)); result[0] = ErrorUtils.createErrorType("Type for " + expression.getReferencedNameAsName()); return false; }
@NotNull public TypeInfoForCall getCallExpressionTypeInfoForCallWithoutFinalTypeCheck( @NotNull JetCallExpression callExpression, @NotNull ReceiverValue receiver, @Nullable ASTNode callOperationNode, @NotNull ResolutionContext context, @NotNull ResolveMode resolveMode) { boolean[] result = new boolean[1]; Call call = CallMaker.makeCall(receiver, callOperationNode, callExpression); TemporaryBindingTrace traceForFunction = TemporaryBindingTrace.create( context.trace, "trace to resolve as function call", callExpression); ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction( call, callExpression, receiver, context.replaceBindingTrace(traceForFunction), resolveMode, result); if (result[0]) { FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null; traceForFunction.commit(); if (callExpression.getValueArgumentList() == null && callExpression.getFunctionLiteralArguments().isEmpty()) { // there are only type arguments boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0; context.trace.report( FUNCTION_CALL_EXPECTED.on(callExpression, callExpression, hasValueParameters)); } if (functionDescriptor == null) { return TypeInfoForCall.create(null, context.dataFlowInfo); } JetType type = functionDescriptor.getReturnType(); return TypeInfoForCall.create( type, resolvedCall.getDataFlowInfo(), resolvedCall, call, context, resolveMode); } JetExpression calleeExpression = callExpression.getCalleeExpression(); if (calleeExpression instanceof JetSimpleNameExpression && callExpression.getTypeArgumentList() == null) { TemporaryBindingTrace traceForVariable = TemporaryBindingTrace.create( context.trace, "trace to resolve as variable with 'invoke' call", callExpression); JetType type = getVariableType( (JetSimpleNameExpression) calleeExpression, receiver, callOperationNode, context.replaceBindingTrace(traceForVariable), result); if (result[0]) { traceForVariable.commit(); context.trace.report( FUNCTION_EXPECTED.on( (JetReferenceExpression) calleeExpression, calleeExpression, type != null ? type : ErrorUtils.createErrorType(""))); return TypeInfoForCall.create(null, context.dataFlowInfo); } } traceForFunction.commit(); return TypeInfoForCall.create(null, context.dataFlowInfo); }
@Override public JetType visitFunctionLiteralExpression( JetFunctionLiteralExpression expression, ExpressionTypingContext context) { JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); JetBlockExpression bodyExpression = functionLiteral.getBodyExpression(); if (bodyExpression == null) return null; JetType expectedType = context.expectedType; boolean functionTypeExpected = expectedType != TypeUtils.NO_EXPECTED_TYPE && JetStandardClasses.isFunctionType(expectedType); NamedFunctionDescriptorImpl functionDescriptor = createFunctionDescriptor(expression, context, functionTypeExpected); List<JetType> parameterTypes = Lists.newArrayList(); List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters(); for (ValueParameterDescriptor valueParameter : valueParameters) { parameterTypes.add(valueParameter.getOutType()); } ReceiverDescriptor receiverParameter = functionDescriptor.getReceiverParameter(); JetType receiver = receiverParameter != NO_RECEIVER ? receiverParameter.getType() : null; JetType returnType = TypeUtils.NO_EXPECTED_TYPE; JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope( context.scope, functionDescriptor, context.trace); JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef(); if (returnTypeRef != null) { returnType = context.getTypeResolver().resolveType(context.scope, returnTypeRef); context .getServices() .checkFunctionReturnType( expression, context .replaceScope(functionInnerScope) .replaceExpectedType(returnType) .replaceExpectedReturnType(returnType) .replaceDataFlowInfo(context.dataFlowInfo)); } else { if (functionTypeExpected) { returnType = JetStandardClasses.getReturnTypeFromFunctionType(expectedType); } returnType = context .getServices() .getBlockReturnedType( functionInnerScope, bodyExpression, CoercionStrategy.COERCION_TO_UNIT, context.replaceExpectedType(returnType).replaceExpectedReturnType(returnType)); } JetType safeReturnType = returnType == null ? ErrorUtils.createErrorType("<return type>") : returnType; functionDescriptor.setReturnType(safeReturnType); boolean hasDeclaredValueParameters = functionLiteral.getValueParameterList() != null; if (!hasDeclaredValueParameters && functionTypeExpected) { JetType expectedReturnType = JetStandardClasses.getReturnTypeFromFunctionType(expectedType); if (JetStandardClasses.isUnit(expectedReturnType)) { functionDescriptor.setReturnType(JetStandardClasses.getUnitType()); return DataFlowUtils.checkType( JetStandardClasses.getFunctionType( Collections.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, JetStandardClasses.getUnitType()), expression, context); } } return DataFlowUtils.checkType( JetStandardClasses.getFunctionType( Collections.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, safeReturnType), expression, context); }