Convert ClosureExpressionsTypingVisitor to kotlin
This commit is contained in:
+210
-287
@@ -14,418 +14,341 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.types.expressions;
|
package org.jetbrains.kotlin.types.expressions
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists
|
||||||
import com.intellij.psi.PsiElement;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import com.intellij.util.Function;
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import kotlin.Function1;
|
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.*;
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.resolve.BindingContext.AUTO_CREATED_IT
|
||||||
import org.jetbrains.kotlin.resolve.*;
|
import org.jetbrains.kotlin.resolve.BindingContext.EXPECTED_RETURN_TYPE
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
import org.jetbrains.kotlin.resolve.BindingContext.EXPRESSION_TYPE
|
||||||
import org.jetbrains.kotlin.resolve.scopes.WritableScope;
|
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||||
import org.jetbrains.kotlin.types.*;
|
import org.jetbrains.kotlin.resolve.scopes.WritableScope
|
||||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker;
|
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
||||||
|
import org.jetbrains.kotlin.types.*
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils.CANT_INFER_LAMBDA_PARAM_TYPE
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils.noExpectedType
|
||||||
|
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||||
|
import org.jetbrains.kotlin.types.expressions.CoercionStrategy.COERCION_TO_UNIT
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
import java.util.Collection;
|
public class ClosureExpressionsTypingVisitor protected(facade: ExpressionTypingInternals) : ExpressionTypingVisitor(facade) {
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
override fun visitNamedFunction(function: JetNamedFunction, data: ExpressionTypingContext): JetTypeInfo {
|
||||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
return visitNamedFunction(function, data, false, null)
|
||||||
import static org.jetbrains.kotlin.resolve.source.SourcePackage.toSourceElement;
|
|
||||||
import static org.jetbrains.kotlin.types.TypeUtils.*;
|
|
||||||
import static org.jetbrains.kotlin.types.expressions.CoercionStrategy.COERCION_TO_UNIT;
|
|
||||||
|
|
||||||
public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
|
|
||||||
|
|
||||||
protected ClosureExpressionsTypingVisitor(@NotNull ExpressionTypingInternals facade) {
|
|
||||||
super(facade);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public fun visitNamedFunction(
|
||||||
public JetTypeInfo visitNamedFunction(
|
function: JetNamedFunction,
|
||||||
@NotNull JetNamedFunction function, ExpressionTypingContext data
|
context: ExpressionTypingContext,
|
||||||
) {
|
isStatement: Boolean,
|
||||||
return visitNamedFunction(function, data, false, null);
|
statementScope: WritableScope? // must be not null if isStatement
|
||||||
}
|
): JetTypeInfo {
|
||||||
|
if (!isStatement) {
|
||||||
public JetTypeInfo visitNamedFunction(
|
// function expression
|
||||||
@NotNull JetNamedFunction function,
|
|
||||||
@NotNull ExpressionTypingContext context,
|
|
||||||
boolean isStatement,
|
|
||||||
@Nullable WritableScope statementScope // must be not null if isStatement
|
|
||||||
) {
|
|
||||||
if (!isStatement) { // function expression
|
|
||||||
if (!function.getTypeParameters().isEmpty()) {
|
if (!function.getTypeParameters().isEmpty()) {
|
||||||
context.trace.report(TYPE_PARAMETERS_NOT_ALLOWED.on(function));
|
context.trace.report(TYPE_PARAMETERS_NOT_ALLOWED.on(function))
|
||||||
}
|
}
|
||||||
for (JetParameter parameter : function.getValueParameters()) {
|
for (parameter in function.getValueParameters()) {
|
||||||
if (parameter.hasDefaultValue()) {
|
if (parameter.hasDefaultValue()) {
|
||||||
context.trace.report(FUNCTION_EXPRESSION_PARAMETER_WITH_DEFAULT_VALUE.on(parameter));
|
context.trace.report(FUNCTION_EXPRESSION_PARAMETER_WITH_DEFAULT_VALUE.on(parameter))
|
||||||
}
|
}
|
||||||
if (parameter.isVarArg()) {
|
if (parameter.isVarArg()) {
|
||||||
context.trace.report(USELESS_VARARG_ON_PARAMETER.on(parameter));
|
context.trace.report(USELESS_VARARG_ON_PARAMETER.on(parameter))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionTypingServices services = components.expressionTypingServices;
|
val services = components.expressionTypingServices
|
||||||
|
|
||||||
SimpleFunctionDescriptor functionDescriptor;
|
val functionDescriptor: SimpleFunctionDescriptor
|
||||||
if (isStatement) {
|
if (isStatement) {
|
||||||
functionDescriptor = services.getDescriptorResolver().
|
functionDescriptor = services.getDescriptorResolver().resolveFunctionDescriptorWithAnnotationArguments(
|
||||||
resolveFunctionDescriptorWithAnnotationArguments(
|
context.scope.getContainingDeclaration(), context.scope, function, context.trace, context.dataFlowInfo)
|
||||||
context.scope.getContainingDeclaration(), context.scope, function, context.trace, context.dataFlowInfo);
|
assert(statementScope != null) {
|
||||||
assert statementScope != null : "statementScope must be not null for function: " +
|
"statementScope must be not null for function: " + function.getName() + " at location " + DiagnosticUtils.atLocation(function)
|
||||||
function.getName() +
|
}
|
||||||
" at location " +
|
statementScope!!.addFunctionDescriptor(functionDescriptor)
|
||||||
DiagnosticUtils.atLocation(function);
|
|
||||||
statementScope.addFunctionDescriptor(functionDescriptor);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
functionDescriptor = services.getDescriptorResolver().resolveFunctionExpressionDescriptor(
|
functionDescriptor = services.getDescriptorResolver().resolveFunctionExpressionDescriptor(
|
||||||
context.scope.getContainingDeclaration(), context.scope, function, context.trace, context.dataFlowInfo);
|
context.scope.getContainingDeclaration(), context.scope, function, context.trace, context.dataFlowInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace);
|
val functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace)
|
||||||
services.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo, null, context.trace);
|
services.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo, null, context.trace)
|
||||||
|
|
||||||
services.resolveValueParameters(function.getValueParameters(), functionDescriptor.getValueParameters(), context.scope,
|
services.resolveValueParameters(function.getValueParameters(), functionDescriptor.getValueParameters(), context.scope,
|
||||||
context.dataFlowInfo, context.trace);
|
context.dataFlowInfo, context.trace);
|
||||||
|
|
||||||
ModifiersChecker.create(context.trace, components.additionalCheckerProvider).checkModifiersForLocalDeclaration(function,
|
ModifiersChecker.create(context.trace, components.additionalCheckerProvider)
|
||||||
functionDescriptor);
|
.checkModifiersForLocalDeclaration(function, functionDescriptor)
|
||||||
if (!function.hasBody()) {
|
if (!function.hasBody()) {
|
||||||
context.trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor));
|
context.trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isStatement) {
|
if (isStatement) {
|
||||||
return DataFlowUtils.checkStatementType(function, context, context.dataFlowInfo);
|
return DataFlowUtils.checkStatementType(function, context as ResolutionContext<*>, context.dataFlowInfo)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return DataFlowUtils.checkType(createFunctionType(functionDescriptor), function, context, context.dataFlowInfo);
|
return DataFlowUtils.checkType(createFunctionType(functionDescriptor), function, context as ResolutionContext<*>, context.dataFlowInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private fun createFunctionType(functionDescriptor: SimpleFunctionDescriptor): JetType? {
|
||||||
private JetType createFunctionType(@NotNull SimpleFunctionDescriptor functionDescriptor) {
|
val receiverType = functionDescriptor.getExtensionReceiverParameter()?.getType()
|
||||||
JetType receiverType = functionDescriptor.getExtensionReceiverParameter() != null
|
|
||||||
? functionDescriptor.getExtensionReceiverParameter().getType()
|
|
||||||
: null;
|
|
||||||
|
|
||||||
JetType returnType = functionDescriptor.getReturnType();
|
val returnType = functionDescriptor.getReturnType()
|
||||||
if (returnType == null) {
|
if (returnType == null) {
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
List<JetType> parameters =
|
val parameters = functionDescriptor.getValueParameters().map {
|
||||||
ContainerUtil.map(functionDescriptor.getValueParameters(), new Function<ValueParameterDescriptor, JetType>() {
|
it.getType()
|
||||||
@Override
|
}
|
||||||
public JetType fun(ValueParameterDescriptor descriptor) {
|
|
||||||
return descriptor.getType();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return components.builtIns.getFunctionType(Annotations.EMPTY, receiverType, parameters, returnType);
|
return components.builtIns.getFunctionType(Annotations.EMPTY, receiverType, parameters, returnType)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun visitFunctionLiteralExpression(expression: JetFunctionLiteralExpression, context: ExpressionTypingContext): JetTypeInfo? {
|
||||||
public JetTypeInfo visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression, ExpressionTypingContext context) {
|
if (!expression.getFunctionLiteral().hasBody()) return null
|
||||||
if (!expression.getFunctionLiteral().hasBody()) return null;
|
|
||||||
|
|
||||||
JetType expectedType = context.expectedType;
|
val expectedType = context.expectedType
|
||||||
boolean functionTypeExpected = !noExpectedType(expectedType) && KotlinBuiltIns.isFunctionOrExtensionFunctionType(
|
val functionTypeExpected = !noExpectedType(expectedType) && KotlinBuiltIns.isFunctionOrExtensionFunctionType(expectedType)
|
||||||
expectedType);
|
|
||||||
|
|
||||||
AnonymousFunctionDescriptor functionDescriptor = createFunctionDescriptor(expression, context, functionTypeExpected);
|
val functionDescriptor = createFunctionDescriptor(expression, context, functionTypeExpected)
|
||||||
JetType safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected);
|
val safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected)
|
||||||
functionDescriptor.setReturnType(safeReturnType);
|
functionDescriptor.setReturnType(safeReturnType)
|
||||||
|
|
||||||
JetType receiver = DescriptorUtils.getReceiverParameterType(functionDescriptor.getExtensionReceiverParameter());
|
val receiver = DescriptorUtils.getReceiverParameterType(functionDescriptor.getExtensionReceiverParameter())
|
||||||
List<JetType> valueParametersTypes = ExpressionTypingUtils.getValueParametersTypes(functionDescriptor.getValueParameters());
|
val valueParametersTypes = ExpressionTypingUtils.getValueParametersTypes(functionDescriptor.getValueParameters())
|
||||||
JetType resultType = components.builtIns.getFunctionType(
|
val resultType = components.builtIns.getFunctionType(Annotations.EMPTY, receiver, valueParametersTypes, safeReturnType)
|
||||||
Annotations.EMPTY, receiver, valueParametersTypes, safeReturnType);
|
|
||||||
if (!noExpectedType(expectedType) && KotlinBuiltIns.isFunctionOrExtensionFunctionType(expectedType)) {
|
if (!noExpectedType(expectedType) && KotlinBuiltIns.isFunctionOrExtensionFunctionType(expectedType)) {
|
||||||
// all checks were done before
|
// all checks were done before
|
||||||
return JetTypeInfo.create(resultType, context.dataFlowInfo);
|
return JetTypeInfo.create(resultType, context.dataFlowInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataFlowUtils.checkType(resultType, expression, context, context.dataFlowInfo);
|
return DataFlowUtils.checkType(resultType, expression, context as ResolutionContext<*>, context.dataFlowInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
private fun createFunctionDescriptor(
|
||||||
private AnonymousFunctionDescriptor createFunctionDescriptor(
|
expression: JetFunctionLiteralExpression,
|
||||||
@NotNull JetFunctionLiteralExpression expression,
|
context: ExpressionTypingContext,
|
||||||
@NotNull ExpressionTypingContext context,
|
functionTypeExpected: Boolean
|
||||||
boolean functionTypeExpected
|
): AnonymousFunctionDescriptor {
|
||||||
) {
|
val functionLiteral = expression.getFunctionLiteral()
|
||||||
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
|
val receiverTypeRef = functionLiteral.getReceiverTypeReference()
|
||||||
JetTypeReference receiverTypeRef = functionLiteral.getReceiverTypeReference();
|
val functionDescriptor = AnonymousFunctionDescriptor(context.scope.getContainingDeclaration(), Annotations.EMPTY,
|
||||||
AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
|
CallableMemberDescriptor.Kind.DECLARATION, functionLiteral.toSourceElement())
|
||||||
context.scope.getContainingDeclaration(), Annotations.EMPTY, CallableMemberDescriptor.Kind.DECLARATION,
|
|
||||||
toSourceElement(functionLiteral)
|
|
||||||
);
|
|
||||||
|
|
||||||
List<ValueParameterDescriptor> valueParameterDescriptors = createValueParameterDescriptors(context, functionLiteral,
|
val valueParameterDescriptors = createValueParameterDescriptors(context, functionLiteral, functionDescriptor, functionTypeExpected)
|
||||||
functionDescriptor, functionTypeExpected);
|
|
||||||
|
|
||||||
JetType effectiveReceiverType;
|
val effectiveReceiverType: JetType?
|
||||||
if (receiverTypeRef == null) {
|
if (receiverTypeRef == null) {
|
||||||
if (functionTypeExpected) {
|
if (functionTypeExpected) {
|
||||||
effectiveReceiverType = KotlinBuiltIns.getReceiverType(context.expectedType);
|
effectiveReceiverType = KotlinBuiltIns.getReceiverType(context.expectedType)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
effectiveReceiverType = null;
|
effectiveReceiverType = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
effectiveReceiverType = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, receiverTypeRef, context.trace, true);
|
effectiveReceiverType = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, receiverTypeRef,
|
||||||
|
context.trace, true)
|
||||||
}
|
}
|
||||||
functionDescriptor.initialize(effectiveReceiverType,
|
functionDescriptor.initialize(effectiveReceiverType, ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER, listOf(),
|
||||||
ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER,
|
valueParameterDescriptors, /*unsubstitutedReturnType = */ null, Modality.FINAL, Visibilities.LOCAL)
|
||||||
Collections.<TypeParameterDescriptorImpl>emptyList(),
|
BindingContextUtils.recordFunctionDeclarationToDescriptor(context.trace, functionLiteral, functionDescriptor)
|
||||||
valueParameterDescriptors,
|
return functionDescriptor
|
||||||
/*unsubstitutedReturnType = */ null,
|
|
||||||
Modality.FINAL,
|
|
||||||
Visibilities.LOCAL
|
|
||||||
);
|
|
||||||
BindingContextUtils.recordFunctionDeclarationToDescriptor(context.trace, functionLiteral, functionDescriptor);
|
|
||||||
return functionDescriptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
private fun createValueParameterDescriptors(
|
||||||
private List<ValueParameterDescriptor> createValueParameterDescriptors(
|
context: ExpressionTypingContext,
|
||||||
@NotNull ExpressionTypingContext context,
|
functionLiteral: JetFunctionLiteral,
|
||||||
@NotNull JetFunctionLiteral functionLiteral,
|
functionDescriptor: FunctionDescriptorImpl,
|
||||||
@NotNull FunctionDescriptorImpl functionDescriptor,
|
functionTypeExpected: Boolean
|
||||||
boolean functionTypeExpected
|
): List<ValueParameterDescriptor> {
|
||||||
) {
|
val valueParameterDescriptors = Lists.newArrayList<ValueParameterDescriptor>()
|
||||||
List<ValueParameterDescriptor> valueParameterDescriptors = Lists.newArrayList();
|
val declaredValueParameters = functionLiteral.getValueParameters()
|
||||||
List<JetParameter> declaredValueParameters = functionLiteral.getValueParameters();
|
|
||||||
|
|
||||||
List<ValueParameterDescriptor> expectedValueParameters = (functionTypeExpected)
|
val expectedValueParameters = if (functionTypeExpected) KotlinBuiltIns.getValueParameters(functionDescriptor, context.expectedType)
|
||||||
? KotlinBuiltIns.getValueParameters(functionDescriptor, context.expectedType)
|
else null
|
||||||
: null;
|
|
||||||
|
|
||||||
JetParameterList valueParameterList = functionLiteral.getValueParameterList();
|
val valueParameterList = functionLiteral.getValueParameterList()
|
||||||
boolean hasDeclaredValueParameters = valueParameterList != null;
|
val hasDeclaredValueParameters = valueParameterList != null
|
||||||
if (functionTypeExpected && !hasDeclaredValueParameters && expectedValueParameters.size() == 1) {
|
if (functionTypeExpected && !hasDeclaredValueParameters && expectedValueParameters!!.size() == 1) {
|
||||||
ValueParameterDescriptor valueParameterDescriptor = expectedValueParameters.get(0);
|
val valueParameterDescriptor = expectedValueParameters!!.get(0)
|
||||||
ValueParameterDescriptor it = new ValueParameterDescriptorImpl(
|
val it = ValueParameterDescriptorImpl(functionDescriptor, null, 0, Annotations.EMPTY, Name.identifier("it"),
|
||||||
functionDescriptor, null, 0, Annotations.EMPTY, Name.identifier("it"),
|
valueParameterDescriptor.getType(), valueParameterDescriptor.hasDefaultValue(),
|
||||||
valueParameterDescriptor.getType(), valueParameterDescriptor.hasDefaultValue(), valueParameterDescriptor.getVarargElementType(),
|
valueParameterDescriptor.getVarargElementType(), SourceElement.NO_SOURCE)
|
||||||
SourceElement.NO_SOURCE
|
valueParameterDescriptors.add(it)
|
||||||
);
|
context.trace.record<ValueParameterDescriptor>(AUTO_CREATED_IT, it)
|
||||||
valueParameterDescriptors.add(it);
|
|
||||||
context.trace.record(AUTO_CREATED_IT, it);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (expectedValueParameters != null && declaredValueParameters.size() != expectedValueParameters.size()) {
|
if (expectedValueParameters != null && declaredValueParameters.size() != expectedValueParameters.size()) {
|
||||||
List<JetType> expectedParameterTypes = ExpressionTypingUtils.getValueParametersTypes(expectedValueParameters);
|
val expectedParameterTypes = ExpressionTypingUtils.getValueParametersTypes(expectedValueParameters)
|
||||||
context.trace.report(EXPECTED_PARAMETERS_NUMBER_MISMATCH.on(functionLiteral, expectedParameterTypes.size(), expectedParameterTypes));
|
context.trace.report(EXPECTED_PARAMETERS_NUMBER_MISMATCH.on(functionLiteral, expectedParameterTypes.size(), expectedParameterTypes))
|
||||||
}
|
}
|
||||||
for (int i = 0; i < declaredValueParameters.size(); i++) {
|
for (i in declaredValueParameters.indices) {
|
||||||
ValueParameterDescriptor valueParameterDescriptor = createValueParameterDescriptor(
|
val valueParameterDescriptor = createValueParameterDescriptor(context, functionDescriptor, declaredValueParameters, expectedValueParameters, i)
|
||||||
context, functionDescriptor, declaredValueParameters, expectedValueParameters, i);
|
valueParameterDescriptors.add(valueParameterDescriptor)
|
||||||
valueParameterDescriptors.add(valueParameterDescriptor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return valueParameterDescriptors;
|
return valueParameterDescriptors
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
private fun createValueParameterDescriptor(
|
||||||
private ValueParameterDescriptor createValueParameterDescriptor(
|
context: ExpressionTypingContext,
|
||||||
@NotNull ExpressionTypingContext context,
|
functionDescriptor: FunctionDescriptorImpl,
|
||||||
@NotNull FunctionDescriptorImpl functionDescriptor,
|
declaredValueParameters: List<JetParameter>,
|
||||||
@NotNull List<JetParameter> declaredValueParameters,
|
expectedValueParameters: List<ValueParameterDescriptor>?,
|
||||||
@Nullable List<ValueParameterDescriptor> expectedValueParameters,
|
index: Int
|
||||||
int index
|
): ValueParameterDescriptor {
|
||||||
) {
|
val declaredParameter = declaredValueParameters.get(index)
|
||||||
JetParameter declaredParameter = declaredValueParameters.get(index);
|
val typeReference = declaredParameter.getTypeReference()
|
||||||
JetTypeReference typeReference = declaredParameter.getTypeReference();
|
|
||||||
|
|
||||||
JetType expectedType;
|
val expectedType: JetType?
|
||||||
if (expectedValueParameters != null && index < expectedValueParameters.size()) {
|
if (expectedValueParameters != null && index < expectedValueParameters.size()) {
|
||||||
expectedType = expectedValueParameters.get(index).getType();
|
expectedType = expectedValueParameters.get(index).getType()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
expectedType = null;
|
expectedType = null
|
||||||
}
|
}
|
||||||
JetType type;
|
val type: JetType
|
||||||
if (typeReference != null) {
|
if (typeReference != null) {
|
||||||
type = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, true);
|
type = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, true)
|
||||||
if (expectedType != null) {
|
if (expectedType != null) {
|
||||||
if (!JetTypeChecker.DEFAULT.isSubtypeOf(expectedType, type)) {
|
if (!JetTypeChecker.DEFAULT.isSubtypeOf(expectedType, type)) {
|
||||||
context.trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(declaredParameter, expectedType));
|
context.trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(declaredParameter, expectedType))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
boolean containsUninferredParameter = TypeUtils.containsSpecialType(expectedType, new Function1<JetType, Boolean>() {
|
val containsUninferredParameter = TypeUtils.containsSpecialType(expectedType) {
|
||||||
@Override
|
TypeUtils.isDontCarePlaceholder(it) || ErrorUtils.isUninferredParameter(it)
|
||||||
public Boolean invoke(JetType type) {
|
|
||||||
return TypeUtils.isDontCarePlaceholder(type) || ErrorUtils.isUninferredParameter(type);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
if (expectedType == null || containsUninferredParameter) {
|
if (expectedType == null || containsUninferredParameter) {
|
||||||
context.trace.report(CANNOT_INFER_PARAMETER_TYPE.on(declaredParameter));
|
context.trace.report(CANNOT_INFER_PARAMETER_TYPE.on(declaredParameter))
|
||||||
}
|
}
|
||||||
if (expectedType != null) {
|
if (expectedType != null) {
|
||||||
type = expectedType;
|
type = expectedType
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
type = CANT_INFER_LAMBDA_PARAM_TYPE;
|
type = CANT_INFER_LAMBDA_PARAM_TYPE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return components.expressionTypingServices.getDescriptorResolver().resolveValueParameterDescriptorWithAnnotationArguments(
|
return components.expressionTypingServices.getDescriptorResolver()
|
||||||
context.scope, functionDescriptor, declaredParameter, index, type, context.trace);
|
.resolveValueParameterDescriptorWithAnnotationArguments(context.scope, functionDescriptor, declaredParameter,
|
||||||
|
index, type, context.trace)
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
private fun computeReturnType(
|
||||||
private JetType computeReturnType(
|
expression: JetFunctionLiteralExpression,
|
||||||
@NotNull JetFunctionLiteralExpression expression,
|
context: ExpressionTypingContext,
|
||||||
@NotNull ExpressionTypingContext context,
|
functionDescriptor: SimpleFunctionDescriptorImpl,
|
||||||
@NotNull SimpleFunctionDescriptorImpl functionDescriptor,
|
functionTypeExpected: Boolean
|
||||||
boolean functionTypeExpected
|
): JetType {
|
||||||
) {
|
val expectedReturnType = if (functionTypeExpected) KotlinBuiltIns.getReturnTypeFromFunctionType(context.expectedType) else null
|
||||||
JetType expectedReturnType = functionTypeExpected ? KotlinBuiltIns.getReturnTypeFromFunctionType(context.expectedType) : null;
|
val returnType = computeUnsafeReturnType(expression, context, functionDescriptor, expectedReturnType);
|
||||||
JetType returnType = computeUnsafeReturnType(expression, context, functionDescriptor, expectedReturnType);
|
|
||||||
|
|
||||||
if (!expression.getFunctionLiteral().hasDeclaredReturnType() && functionTypeExpected) {
|
if (!expression.getFunctionLiteral().hasDeclaredReturnType() && functionTypeExpected) {
|
||||||
if (KotlinBuiltIns.isUnit(expectedReturnType)) {
|
if (KotlinBuiltIns.isUnit(expectedReturnType!!)) {
|
||||||
return components.builtIns.getUnitType();
|
return components.builtIns.getUnitType()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return returnType == null ? CANT_INFER_LAMBDA_PARAM_TYPE : returnType;
|
return returnType ?: CANT_INFER_LAMBDA_PARAM_TYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private JetType computeUnsafeReturnType(
|
|
||||||
@NotNull JetFunctionLiteralExpression expression,
|
|
||||||
@NotNull ExpressionTypingContext context,
|
|
||||||
@NotNull SimpleFunctionDescriptorImpl functionDescriptor,
|
|
||||||
@Nullable JetType expectedReturnType
|
|
||||||
) {
|
|
||||||
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
|
|
||||||
JetBlockExpression bodyExpression = functionLiteral.getBodyExpression();
|
|
||||||
assert bodyExpression != null;
|
|
||||||
|
|
||||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace);
|
private fun computeUnsafeReturnType(
|
||||||
JetTypeReference returnTypeRef = functionLiteral.getTypeReference();
|
expression: JetFunctionLiteralExpression,
|
||||||
JetType declaredReturnType = null;
|
context: ExpressionTypingContext,
|
||||||
if (returnTypeRef != null) {
|
functionDescriptor: SimpleFunctionDescriptorImpl,
|
||||||
declaredReturnType = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, returnTypeRef, context.trace, true);
|
expectedReturnType: JetType?
|
||||||
// This is needed for ControlStructureTypingVisitor#visitReturnExpression() to properly type-check returned expressions
|
): JetType? {
|
||||||
functionDescriptor.setReturnType(declaredReturnType);
|
val functionLiteral = expression.getFunctionLiteral()
|
||||||
if (expectedReturnType != null) {
|
val declaredReturnType = functionLiteral.getTypeReference()?.let {
|
||||||
if (!JetTypeChecker.DEFAULT.isSubtypeOf(declaredReturnType, expectedReturnType)) {
|
val type = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, it, context.trace, true)
|
||||||
context.trace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(returnTypeRef, expectedReturnType));
|
if (expectedReturnType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(type, expectedReturnType)) {
|
||||||
}
|
context.trace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(it, expectedReturnType))
|
||||||
}
|
}
|
||||||
|
type
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type-check the body
|
val expectedType = declaredReturnType ?: (expectedReturnType ?: NO_EXPECTED_TYPE)
|
||||||
JetType expectedType = declaredReturnType != null
|
val functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace)
|
||||||
? declaredReturnType
|
val newContext = context.replaceScope(functionInnerScope).replaceExpectedType(expectedType)
|
||||||
: (expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE);
|
|
||||||
ExpressionTypingContext newContext = context.replaceScope(functionInnerScope).replaceExpectedType(expectedType);
|
|
||||||
context.trace.record(EXPECTED_RETURN_TYPE, functionLiteral, expectedType);
|
|
||||||
JetType typeOfBodyExpression = // needed for error reporting
|
|
||||||
components.expressionTypingServices.getBlockReturnedType(bodyExpression, COERCION_TO_UNIT, newContext).getType();
|
|
||||||
|
|
||||||
if (declaredReturnType != null) {
|
// This is needed for ControlStructureTypingVisitor#visitReturnExpression() to properly type-check returned expressions
|
||||||
return declaredReturnType;
|
context.trace.record(EXPECTED_RETURN_TYPE, functionLiteral, expectedType)
|
||||||
}
|
val typeOfBodyExpression = // Type-check the body
|
||||||
else {
|
components.expressionTypingServices.getBlockReturnedType(functionLiteral.getBodyExpression(), COERCION_TO_UNIT, newContext).getType()
|
||||||
return computeReturnTypeBasedOnReturnExpressions(functionLiteral, context, typeOfBodyExpression);
|
|
||||||
}
|
return declaredReturnType ?: computeReturnTypeBasedOnReturnExpressions(functionLiteral, context, typeOfBodyExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private fun computeReturnTypeBasedOnReturnExpressions(
|
||||||
private JetType computeReturnTypeBasedOnReturnExpressions(
|
functionLiteral: JetFunctionLiteral,
|
||||||
@NotNull JetFunctionLiteral functionLiteral,
|
context: ExpressionTypingContext,
|
||||||
@NotNull ExpressionTypingContext context,
|
typeOfBodyExpression: JetType?
|
||||||
@Nullable JetType typeOfBodyExpression
|
): JetType? {
|
||||||
) {
|
val returnedExpressionTypes = Lists.newArrayList<JetType>()
|
||||||
List<JetType> returnedExpressionTypes = Lists.newArrayList();
|
|
||||||
|
|
||||||
boolean hasEmptyReturn = false;
|
var hasEmptyReturn = false
|
||||||
Collection<JetReturnExpression> returnExpressions = collectReturns(functionLiteral, context.trace);
|
val returnExpressions = collectReturns(functionLiteral, context.trace)
|
||||||
for (JetReturnExpression returnExpression : returnExpressions) {
|
for (returnExpression in returnExpressions) {
|
||||||
JetExpression returnedExpression = returnExpression.getReturnedExpression();
|
val returnedExpression = returnExpression.getReturnedExpression()
|
||||||
if (returnedExpression == null) {
|
if (returnedExpression == null) {
|
||||||
hasEmptyReturn = true;
|
hasEmptyReturn = true
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// the type should have been computed by getBlockReturnedType() above, but can be null, if returnExpression contains some error
|
// the type should have been computed by getBlockReturnedType() above, but can be null, if returnExpression contains some error
|
||||||
ContainerUtil.addIfNotNull(returnedExpressionTypes, context.trace.get(EXPRESSION_TYPE, returnedExpression));
|
returnedExpressionTypes.addIfNotNull(context.trace.get<JetExpression, JetType>(EXPRESSION_TYPE, returnedExpression))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasEmptyReturn) {
|
if (hasEmptyReturn) {
|
||||||
for (JetReturnExpression returnExpression : returnExpressions) {
|
for (returnExpression in returnExpressions) {
|
||||||
JetExpression returnedExpression = returnExpression.getReturnedExpression();
|
val returnedExpression = returnExpression.getReturnedExpression()
|
||||||
if (returnedExpression != null) {
|
if (returnedExpression != null) {
|
||||||
JetType type = context.trace.get(EXPRESSION_TYPE, returnedExpression);
|
val type = context.trace.get<JetExpression, JetType>(EXPRESSION_TYPE, returnedExpression)
|
||||||
if (type == null || !KotlinBuiltIns.isUnit(type)) {
|
if (type == null || !KotlinBuiltIns.isUnit(type)) {
|
||||||
context.trace.report(RETURN_TYPE_MISMATCH.on(returnedExpression, components.builtIns.getUnitType()));
|
context.trace.report(RETURN_TYPE_MISMATCH.on(returnedExpression, components.builtIns.getUnitType()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return components.builtIns.getUnitType();
|
return components.builtIns.getUnitType()
|
||||||
}
|
}
|
||||||
|
returnedExpressionTypes.addIfNotNull(typeOfBodyExpression)
|
||||||
|
|
||||||
ContainerUtil.addIfNotNull(returnedExpressionTypes, typeOfBodyExpression);
|
if (returnedExpressionTypes.isEmpty()) return null
|
||||||
|
return CommonSupertypes.commonSupertype(returnedExpressionTypes)
|
||||||
if (returnedExpressionTypes.isEmpty()) return null;
|
|
||||||
return CommonSupertypes.commonSupertype(returnedExpressionTypes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Collection<JetReturnExpression> collectReturns(
|
private fun collectReturns(functionLiteral: JetFunctionLiteral, trace: BindingTrace): Collection<JetReturnExpression> {
|
||||||
@NotNull final JetFunctionLiteral functionLiteral,
|
val result = Lists.newArrayList<JetReturnExpression>()
|
||||||
@NotNull final BindingTrace trace
|
val bodyExpression = functionLiteral.getBodyExpression()
|
||||||
) {
|
bodyExpression?.accept(object : JetTreeVisitor<MutableList<JetReturnExpression>>() {
|
||||||
Collection<JetReturnExpression> result = Lists.newArrayList();
|
override fun visitReturnExpression(expression: JetReturnExpression, data: MutableList<JetReturnExpression>): Void? {
|
||||||
JetBlockExpression bodyExpression = functionLiteral.getBodyExpression();
|
data.add(expression)
|
||||||
assert bodyExpression != null;
|
return null
|
||||||
bodyExpression.accept(
|
|
||||||
new JetTreeVisitor<Collection<JetReturnExpression>>() {
|
|
||||||
@Override
|
|
||||||
public Void visitReturnExpression(
|
|
||||||
@NotNull JetReturnExpression expression, Collection<JetReturnExpression> data
|
|
||||||
) {
|
|
||||||
data.add(expression);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
result
|
|
||||||
);
|
|
||||||
return ContainerUtil.mapNotNull(result, new Function<JetReturnExpression, JetReturnExpression>() {
|
|
||||||
@Override
|
|
||||||
public JetReturnExpression fun(@NotNull JetReturnExpression returnExpression) {
|
|
||||||
JetSimpleNameExpression label = returnExpression.getTargetLabel();
|
|
||||||
if (label == null) {
|
|
||||||
// No label => non-local return
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
PsiElement labelTarget = trace.get(BindingContext.LABEL_TARGET, label);
|
|
||||||
if (labelTarget != functionLiteral) {
|
|
||||||
// Either a local return of inner lambda/function or a non-local return
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return returnExpression;
|
|
||||||
}
|
}
|
||||||
});
|
}, result)
|
||||||
|
return result.filter {
|
||||||
|
// No label => non-local return
|
||||||
|
// Either a local return of inner lambda/function or a non-local return
|
||||||
|
it.getTargetLabel()?.let { trace.get(BindingContext.LABEL_TARGET, it) } == functionLiteral
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user