diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index 288f8fc46b5..5d5558fd7c7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.impl.*; import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1; +import org.jetbrains.kotlin.diagnostics.DiagnosticUtils; import org.jetbrains.kotlin.lexer.JetKeywordToken; import org.jetbrains.kotlin.lexer.JetModifierKeywordToken; import org.jetbrains.kotlin.lexer.JetTokens; @@ -236,8 +237,20 @@ public class DescriptorResolver { @NotNull BindingTrace trace, @NotNull DataFlowInfo dataFlowInfo ) { - return resolveFunctionDescriptor(containingDescriptor, scope, function, trace, dataFlowInfo, - annotationResolver.resolveAnnotationsWithArguments(scope, function.getModifierList(), trace), false); + if (function.getName() == null) { + trace.report(FUNCTION_DECLARATION_WITH_NO_NAME.on(function)); + } + SimpleFunctionDescriptorImpl functionDescriptor = SimpleFunctionDescriptorImpl.create( + containingDescriptor, + annotationResolver.resolveAnnotationsWithArguments(scope, function.getModifierList(), trace), + function.getNameAsSafeName(), + CallableMemberDescriptor.Kind.DECLARATION, + toSourceElement(function) + ); + initializeFunctionDescriptorAndExplicitReturnType(containingDescriptor, scope, function, functionDescriptor, trace); + initializeFunctionReturnTypeBasedOnFunctionBody(scope, function, functionDescriptor, trace, dataFlowInfo); + BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, function, functionDescriptor); + return functionDescriptor; } @NotNull @@ -248,43 +261,63 @@ public class DescriptorResolver { @NotNull BindingTrace trace, @NotNull DataFlowInfo dataFlowInfo ) { - return resolveFunctionDescriptor(containingDescriptor, scope, function, trace, dataFlowInfo, - annotationResolver.resolveAnnotationsWithArguments(scope, function.getModifierList(), trace), true); + FunctionExpressionDescriptor functionDescriptor = new FunctionExpressionDescriptor( + containingDescriptor, + annotationResolver.resolveAnnotationsWithArguments(scope, function.getModifierList(), trace), + function.getNameAsSafeName(), + CallableMemberDescriptor.Kind.DECLARATION, + toSourceElement(function) + ); + initializeFunctionDescriptorAndExplicitReturnType(containingDescriptor, scope, function, functionDescriptor, trace); + initializeFunctionReturnTypeBasedOnFunctionBody(scope, function, functionDescriptor, trace, dataFlowInfo); + BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, function, functionDescriptor); + return functionDescriptor; + } + + private void initializeFunctionReturnTypeBasedOnFunctionBody( + @NotNull final JetScope scope, + @NotNull final JetNamedFunction function, + @NotNull final SimpleFunctionDescriptorImpl functionDescriptor, + @NotNull final BindingTrace trace, + @NotNull final DataFlowInfo dataFlowInfo + ) { + if (functionDescriptor.getReturnType() != null) return; + assert function.getTypeReference() == null : "Return type must be initialized early for function: " + + function.getText() + ", at: " + + DiagnosticUtils.atLocation(function); + JetType returnType; + if (function.hasBlockBody()) { + returnType = builtIns.getUnitType(); + } + else if (function.hasBody()) { + returnType = + DeferredType.createRecursionIntolerant( + storageManager, + trace, + new Function0() { + @Override + public JetType invoke() { + JetType type = expressionTypingServices + .getBodyExpressionType(trace, scope, dataFlowInfo, function, functionDescriptor); + return transformAnonymousTypeIfNeeded(functionDescriptor, function, type, trace); + } + }); + } + else { + returnType = ErrorUtils.createErrorType("No type, no body"); + } + functionDescriptor.setReturnType(returnType); } @NotNull - private SimpleFunctionDescriptor resolveFunctionDescriptor( + private void initializeFunctionDescriptorAndExplicitReturnType( @NotNull DeclarationDescriptor containingDescriptor, - @NotNull final JetScope scope, - @NotNull final JetNamedFunction function, - @NotNull final BindingTrace trace, - @NotNull final DataFlowInfo dataFlowInfo, - @NotNull Annotations annotations, - boolean nameCanBeOmitted + @NotNull JetScope scope, + @NotNull JetFunction function, + @NotNull SimpleFunctionDescriptorImpl functionDescriptor, + @NotNull BindingTrace trace ) { - if (!nameCanBeOmitted && function.getName() == null) { - trace.report(FUNCTION_DECLARATION_WITH_NO_NAME.on(function)); - } - final SimpleFunctionDescriptorImpl functionDescriptor; - if (nameCanBeOmitted) { // todo remove this hack - functionDescriptor = new FunctionExpressionDescriptor( - containingDescriptor, - annotations, - function.getNameAsSafeName(), - CallableMemberDescriptor.Kind.DECLARATION, - toSourceElement(function) - ); - } - else { - functionDescriptor = SimpleFunctionDescriptorImpl.create( - containingDescriptor, - annotations, - function.getNameAsSafeName(), - CallableMemberDescriptor.Kind.DECLARATION, - toSourceElement(function) - ); - } WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, new TraceBasedRedeclarationHandler(trace), "Function descriptor header scope"); innerScope.addLabeledDeclaration(functionDescriptor); @@ -297,11 +330,7 @@ public class DescriptorResolver { JetType receiverType = null; JetTypeReference receiverTypeRef = function.getReceiverTypeReference(); if (receiverTypeRef != null) { - JetScope scopeForReceiver = - function.hasTypeParameterListBeforeFunctionName() - ? innerScope - : scope; - receiverType = typeResolver.resolveType(scopeForReceiver, receiverTypeRef, trace, true); + receiverType = typeResolver.resolveType(innerScope, receiverTypeRef, trace, true); } List valueParameterDescriptors = @@ -310,32 +339,11 @@ public class DescriptorResolver { innerScope.changeLockLevel(WritableScope.LockLevel.READING); JetTypeReference returnTypeRef = function.getTypeReference(); - JetType returnType; + JetType returnType = null; if (returnTypeRef != null) { returnType = typeResolver.resolveType(innerScope, returnTypeRef, trace, true); } - else if (function.hasBlockBody()) { - returnType = builtIns.getUnitType(); - } - else { - if (function.hasBody()) { - returnType = - DeferredType.createRecursionIntolerant( - storageManager, - trace, - new Function0() { - @Override - public JetType invoke() { - JetType type = expressionTypingServices - .getBodyExpressionType(trace, scope, dataFlowInfo, function, functionDescriptor); - return transformAnonymousTypeIfNeeded(functionDescriptor, function, type, trace); - } - }); - } - else { - returnType = ErrorUtils.createErrorType("No type, no body"); - } - } + Modality modality = resolveModalityFromModifiers(function, getDefaultModality(containingDescriptor, function.hasBody())); Visibility visibility = resolveVisibilityFromModifiers(function, getDefaultVisibility(function, containingDescriptor)); functionDescriptor.initialize( @@ -347,11 +355,10 @@ public class DescriptorResolver { modality, visibility ); - - BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, function, functionDescriptor); - return functionDescriptor; } + + @NotNull public static SimpleFunctionDescriptor createComponentFunctionDescriptor( int parameterIndex,