From b8507c0391d0a628ed284f38ae4263cbbede2a05 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Tue, 25 Dec 2012 20:25:36 +0400 Subject: [PATCH] refactoring: extracted methods createValueParameterDescriptor, computeReturnType, computeUnsafeReturnType --- .../ClosureExpressionsTypingVisitor.java | 188 ++++++++++-------- 1 file changed, 110 insertions(+), 78 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java index a6907589827..4df8f165634 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.types.expressions; import com.google.common.collect.Lists; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.*; @@ -92,59 +93,20 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { @Override public JetTypeInfo visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext context) { - JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); - JetBlockExpression bodyExpression = functionLiteral.getBodyExpression(); + JetBlockExpression bodyExpression = expression.getFunctionLiteral().getBodyExpression(); if (bodyExpression == null) return null; JetType expectedType = context.expectedType; boolean functionTypeExpected = expectedType != NO_EXPECTED_TYPE && KotlinBuiltIns.getInstance().isFunctionType(expectedType); SimpleFunctionDescriptorImpl functionDescriptor = createFunctionDescriptor(expression, context, functionTypeExpected); - - List valueParameters = functionDescriptor.getValueParameters(); - ReceiverParameterDescriptor receiverParameter = functionDescriptor.getReceiverParameter(); - JetType receiver = DescriptorUtils.getReceiverParameterType(receiverParameter); - - JetType returnType = NO_EXPECTED_TYPE; - JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace); - JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef(); - TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve function literal expression", expression); - JetType expectedReturnType = functionTypeExpected ? KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(expectedType) : null; - if (returnTypeRef != null) { - returnType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, returnTypeRef, context.trace, true); - context.expressionTypingServices.checkFunctionReturnType(expression, context.replaceScope(functionInnerScope). - replaceExpectedType(returnType).replaceBindingTrace(temporaryTrace), temporaryTrace); - if (functionTypeExpected) { - if (!JetTypeChecker.INSTANCE.isSubtypeOf(expectedReturnType, returnType)) { - temporaryTrace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(returnTypeRef, expectedReturnType)); - } - } - } - else { - if (functionTypeExpected) { - returnType = expectedReturnType; - } - returnType = context.expressionTypingServices.getBlockReturnedType(functionInnerScope, bodyExpression, CoercionStrategy.COERCION_TO_UNIT, - context.replaceExpectedType(returnType).replaceBindingTrace(temporaryTrace), temporaryTrace).getType(); - } - temporaryTrace.commit(new TraceEntryFilter() { - @Override - public boolean accept(@NotNull WritableSlice slice, Object key) { - return (slice != BindingContext.RESOLUTION_RESULTS_FOR_FUNCTION && slice != BindingContext.RESOLUTION_RESULTS_FOR_PROPERTY && - slice != BindingContext.TRACE_DELTAS_CACHE); - } - }, true); - JetType safeReturnType = returnType == null ? ErrorUtils.createErrorType("") : returnType; - - if (!functionLiteral.hasDeclaredReturnType() && functionTypeExpected) { - if (KotlinBuiltIns.getInstance().isUnit(expectedReturnType)) { - safeReturnType = KotlinBuiltIns.getInstance().getUnitType(); - } - } + JetType safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected); functionDescriptor.setReturnType(safeReturnType); + JetType receiver = DescriptorUtils.getReceiverParameterType(functionDescriptor.getReceiverParameter()); + List valueParametersTypes = DescriptorUtils.getValueParametersTypes(functionDescriptor.getValueParameters()); JetType resultType = KotlinBuiltIns.getInstance().getFunctionType( - Collections.emptyList(), receiver, DescriptorUtils.getValueParametersTypes(valueParameters), safeReturnType); + Collections.emptyList(), receiver, valueParametersTypes, safeReturnType); if (expectedType != NO_EXPECTED_TYPE && KotlinBuiltIns.getInstance().isFunctionType(expectedType)) { // all checks were done before return JetTypeInfo.create(resultType, context.dataFlowInfo); @@ -153,7 +115,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { } @NotNull - private SimpleFunctionDescriptorImpl createFunctionDescriptor( + private static SimpleFunctionDescriptorImpl createFunctionDescriptor( @NotNull JetFunctionLiteralExpression expression, @NotNull ExpressionTypingContext context, boolean functionTypeExpected @@ -192,7 +154,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { } @NotNull - private List createValueParameterDescriptors( + private static List createValueParameterDescriptors( @NotNull ExpressionTypingContext context, @NotNull JetFunctionLiteral functionLiteral, @NotNull FunctionDescriptorImpl functionDescriptor, @@ -222,41 +184,111 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { context.trace.report(EXPECTED_PARAMETERS_NUMBER_MISMATCH.on(functionLiteral, expectedParameterTypes.size(), expectedParameterTypes)); } for (int i = 0; i < declaredValueParameters.size(); i++) { - JetParameter declaredParameter = declaredValueParameters.get(i); - JetTypeReference typeReference = declaredParameter.getTypeReference(); - - JetType expectedType; - if (expectedValueParameters != null && i < expectedValueParameters.size()) { - expectedType = expectedValueParameters.get(i).getType(); - } - else { - expectedType = null; - } - JetType type; - if (typeReference != null) { - type = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, true); - if (expectedType != null) { - if (!JetTypeChecker.INSTANCE.isSubtypeOf(type, expectedType)) { - context.trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(declaredParameter, expectedType)); - } - } - } - else { - if (expectedType == null || expectedType == CallResolverUtil.DONT_CARE || expectedType == CallResolverUtil.CANT_INFER) { - context.trace.report(CANNOT_INFER_PARAMETER_TYPE.on(declaredParameter)); - } - if (expectedType != null) { - type = expectedType; - } - else { - type = ErrorUtils.createErrorType("Cannot be inferred"); - } - } - ValueParameterDescriptor valueParameterDescriptor = context.expressionTypingServices.getDescriptorResolver().resolveValueParameterDescriptor( - context.scope, functionDescriptor, declaredParameter, i, type, context.trace); + ValueParameterDescriptor valueParameterDescriptor = createValueParameterDescriptor( + context, functionDescriptor, declaredValueParameters, expectedValueParameters, i); valueParameterDescriptors.add(valueParameterDescriptor); } } return valueParameterDescriptors; } + + @NotNull + private static ValueParameterDescriptor createValueParameterDescriptor( + @NotNull ExpressionTypingContext context, + @NotNull FunctionDescriptorImpl functionDescriptor, + @NotNull List declaredValueParameters, + @Nullable List expectedValueParameters, + int index + ) { + JetParameter declaredParameter = declaredValueParameters.get(index); + JetTypeReference typeReference = declaredParameter.getTypeReference(); + + JetType expectedType; + if (expectedValueParameters != null && index < expectedValueParameters.size()) { + expectedType = expectedValueParameters.get(index).getType(); + } + else { + expectedType = null; + } + JetType type; + if (typeReference != null) { + type = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, true); + if (expectedType != null) { + if (!JetTypeChecker.INSTANCE.isSubtypeOf(type, expectedType)) { + context.trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(declaredParameter, expectedType)); + } + } + } + else { + if (expectedType == null || expectedType == CallResolverUtil.DONT_CARE || expectedType == CallResolverUtil.CANT_INFER) { + context.trace.report(CANNOT_INFER_PARAMETER_TYPE.on(declaredParameter)); + } + if (expectedType != null) { + type = expectedType; + } + else { + type = ErrorUtils.createErrorType("Cannot be inferred"); + } + } + return context.expressionTypingServices.getDescriptorResolver().resolveValueParameterDescriptor( + context.scope, functionDescriptor, declaredParameter, index, type, context.trace); + } + + @NotNull + private static JetType computeReturnType( + @NotNull JetFunctionLiteralExpression expression, + @NotNull ExpressionTypingContext context, + @NotNull SimpleFunctionDescriptorImpl functionDescriptor, + boolean functionTypeExpected + ) { + TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve function literal expression", expression); + JetType expectedReturnType = functionTypeExpected ? KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(context.expectedType) : null; + JetType returnType = computeUnsafeReturnType(expression, context, functionDescriptor, temporaryTrace, expectedReturnType); + + temporaryTrace.commit(new TraceEntryFilter() { + @Override + public boolean accept(@NotNull WritableSlice slice, Object key) { + return (slice != BindingContext.RESOLUTION_RESULTS_FOR_FUNCTION && slice != BindingContext.RESOLUTION_RESULTS_FOR_PROPERTY && + slice != BindingContext.TRACE_DELTAS_CACHE); + } + }, true); + + if (!expression.getFunctionLiteral().hasDeclaredReturnType() && functionTypeExpected) { + if (KotlinBuiltIns.getInstance().isUnit(expectedReturnType)) { + return KotlinBuiltIns.getInstance().getUnitType(); + } + } + return returnType == null ? ErrorUtils.createErrorType("") : returnType; + } + + @Nullable + private static JetType computeUnsafeReturnType( + @NotNull JetFunctionLiteralExpression expression, + @NotNull ExpressionTypingContext context, + @NotNull SimpleFunctionDescriptorImpl functionDescriptor, + @NotNull TemporaryBindingTrace temporaryTrace, + @Nullable JetType expectedReturnType + ) { + JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); + JetBlockExpression bodyExpression = functionLiteral.getBodyExpression(); + assert bodyExpression != null; + + JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace); + JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef(); + if (returnTypeRef != null) { + JetType returnType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, returnTypeRef, context.trace, true); + context.expressionTypingServices.checkFunctionReturnType(expression, context.replaceScope(functionInnerScope). + replaceExpectedType(returnType).replaceBindingTrace(temporaryTrace), temporaryTrace); + if (expectedReturnType != null) { + if (!JetTypeChecker.INSTANCE.isSubtypeOf(expectedReturnType, returnType)) { + temporaryTrace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(returnTypeRef, expectedReturnType)); + } + } + return returnType; + } + ExpressionTypingContext newContext = context.replaceExpectedType(expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE) + .replaceBindingTrace(temporaryTrace); + return context.expressionTypingServices.getBlockReturnedType(functionInnerScope, bodyExpression, CoercionStrategy.COERCION_TO_UNIT, + newContext, temporaryTrace).getType(); + } }