Support overload ambiguity resolution for callable references by expected type.
Resolve callable references taking into account expected callable types. This affects call resolution procedure (resolve 'foo' in for 'foo(::bar)') similar to the approach used for function literals: * During "shape arguments" phase of call resolution, callable references are resolved in independent context without expected type. If the callable reference is ambiguous, its shape type is a function placeholder type without parameter types and return type information. Otherwise, it is a reflection type for the resolved function or property. Upper-level call is resolved without taking into account ambiguous callable references. * During "complete call" phase of call resolution, resolve callable reference arguments to actual descriptors (if possible), and update constraint system for the given call accordingly. #KT-6982 Fixed #KT-5780 Fixed
This commit is contained in:
+276
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.callableReferences
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.CallResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.context.*
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
||||
import org.jetbrains.kotlin.utils.ThrowingList
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver
|
||||
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingComponents
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
|
||||
public fun resolveCallableReferenceReceiverType(
|
||||
callableReferenceExpression: JetCallableReferenceExpression,
|
||||
context: ResolutionContext<*>,
|
||||
typeResolver: TypeResolver
|
||||
): JetType? =
|
||||
callableReferenceExpression.getTypeReference()?.let {
|
||||
typeResolver.resolveType(context.scope, it, context.trace, false)
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor> ResolveArgumentsMode.acceptResolution(results: OverloadResolutionResults<D>, trace: TemporaryTraceAndCache) {
|
||||
when (this) {
|
||||
ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS ->
|
||||
if (results.isSingleResult()) trace.commit()
|
||||
ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS ->
|
||||
if (results.isSomething()) trace.commit()
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolvePossiblyAmbiguousCallableReference(
|
||||
reference: JetSimpleNameExpression,
|
||||
receiver: ReceiverValue,
|
||||
context: ResolutionContext<*>,
|
||||
resolutionMode: ResolveArgumentsMode,
|
||||
callResolver: CallResolver
|
||||
): OverloadResolutionResults<CallableDescriptor> {
|
||||
val call = CallMaker.makeCall(reference, receiver, null, reference, ThrowingList.instance<ValueArgument>())
|
||||
val temporaryTrace = TemporaryTraceAndCache.create(context, "trace to resolve ::${reference.getReferencedName()} as function", reference)
|
||||
val newContext = if (resolutionMode == ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS)
|
||||
context.replaceTraceAndCache(temporaryTrace).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)
|
||||
else
|
||||
context.replaceTraceAndCache(temporaryTrace)
|
||||
val callResolutionContext = BasicCallResolutionContext.create(
|
||||
newContext, call, CheckArgumentTypesMode.CHECK_CALLABLE_TYPE)
|
||||
val resolutionResults = callResolver.resolveCallForMember(reference, callResolutionContext)
|
||||
resolutionMode.acceptResolution(resolutionResults, temporaryTrace)
|
||||
return resolutionResults
|
||||
}
|
||||
|
||||
private fun OverloadResolutionResults<*>.isSomething(): Boolean = !isNothing()
|
||||
|
||||
public fun resolvePossiblyAmbiguousCallableReference(
|
||||
callableReferenceExpression: JetCallableReferenceExpression,
|
||||
lhsType: JetType?,
|
||||
context: ResolutionContext<*>,
|
||||
resolutionMode: ResolveArgumentsMode,
|
||||
callResolver: CallResolver
|
||||
): OverloadResolutionResults<CallableDescriptor>? {
|
||||
val reference = callableReferenceExpression.getCallableReference()
|
||||
|
||||
fun resolveInScope(traceTitle: String, scope: JetScope): OverloadResolutionResults<CallableDescriptor> {
|
||||
val temporaryTraceAndCache = TemporaryTraceAndCache.create(context, traceTitle, reference)
|
||||
val newContext = context.replaceTraceAndCache(temporaryTraceAndCache).replaceScope(scope)
|
||||
val results = resolvePossiblyAmbiguousCallableReference(reference, ReceiverValue.NO_RECEIVER, newContext, resolutionMode, callResolver)
|
||||
resolutionMode.acceptResolution(results, temporaryTraceAndCache)
|
||||
return results
|
||||
}
|
||||
|
||||
fun resolveWithReceiver(traceTitle: String, receiver: ReceiverValue): OverloadResolutionResults<CallableDescriptor> {
|
||||
val temporaryTraceAndCache = TemporaryTraceAndCache.create(context, traceTitle, reference)
|
||||
val newContext = context.replaceTraceAndCache(temporaryTraceAndCache)
|
||||
val results = resolvePossiblyAmbiguousCallableReference(reference, receiver, newContext, resolutionMode, callResolver)
|
||||
resolutionMode.acceptResolution(results, temporaryTraceAndCache)
|
||||
return results
|
||||
}
|
||||
|
||||
if (lhsType == null) {
|
||||
return resolvePossiblyAmbiguousCallableReference(reference, ReceiverValue.NO_RECEIVER, context, resolutionMode, callResolver)
|
||||
}
|
||||
|
||||
val classifier = lhsType.getConstructor().getDeclarationDescriptor()
|
||||
if (classifier !is ClassDescriptor) {
|
||||
context.trace.report(CALLABLE_REFERENCE_LHS_NOT_A_CLASS.on(callableReferenceExpression))
|
||||
return null
|
||||
}
|
||||
|
||||
val possibleStatic = resolveInScope("trace to resolve ::${reference.getReferencedName()} in static scope", classifier.getStaticScope())
|
||||
if (possibleStatic.isSomething()) return possibleStatic
|
||||
|
||||
val possibleNested = resolveInScope("trace to resolve ::${reference.getReferencedName()} in static nested classes scope",
|
||||
DescriptorUtils.getStaticNestedClassesScope(classifier))
|
||||
if (possibleNested.isSomething()) return possibleNested
|
||||
|
||||
val possibleWithReceiver = resolveWithReceiver("trace to resolve ::${reference.getReferencedName()} with receiver",
|
||||
TransientReceiver(lhsType))
|
||||
if (possibleWithReceiver.isSomething()) return possibleWithReceiver
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
public fun resolveCallableReferenceTarget(
|
||||
callableReferenceExpression: JetCallableReferenceExpression,
|
||||
lhsType: JetType?,
|
||||
context: ResolutionContext<*>,
|
||||
resolvedToSomething: BooleanArray,
|
||||
callResolver: CallResolver
|
||||
): CallableDescriptor? {
|
||||
val resolutionResults = resolvePossiblyAmbiguousCallableReference(
|
||||
callableReferenceExpression, lhsType, context, ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS, callResolver)
|
||||
return resolutionResults?.let { results ->
|
||||
if (results.isSomething()) {
|
||||
resolvedToSomething[0] = true
|
||||
OverloadResolutionResultsUtil.getResultingCall(results, context.contextDependency)?.let { call ->
|
||||
call.getResultingDescriptor()
|
||||
}
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createReflectionTypeForFunction(
|
||||
descriptor: FunctionDescriptor,
|
||||
receiverType: JetType?,
|
||||
reflectionTypes: ReflectionTypes
|
||||
): JetType? {
|
||||
val returnType = descriptor.getReturnType() ?: return null
|
||||
val valueParametersTypes = ExpressionTypingUtils.getValueParametersTypes(descriptor.getValueParameters())
|
||||
return reflectionTypes.getKFunctionType(Annotations.EMPTY, receiverType, valueParametersTypes, returnType)
|
||||
}
|
||||
|
||||
private fun createReflectionTypeForProperty(
|
||||
descriptor: PropertyDescriptor,
|
||||
receiverType: JetType?,
|
||||
reflectionTypes: ReflectionTypes
|
||||
): JetType {
|
||||
return reflectionTypes.getKPropertyType(Annotations.EMPTY, receiverType, descriptor.getType(), descriptor.isVar())
|
||||
}
|
||||
|
||||
private fun bindFunctionReference(expression: JetCallableReferenceExpression, referenceType: JetType, context: ResolutionContext<*>) {
|
||||
val functionDescriptor = AnonymousFunctionDescriptor(
|
||||
context.scope.getContainingDeclaration(),
|
||||
Annotations.EMPTY,
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
expression.toSourceElement())
|
||||
|
||||
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, referenceType, null, Modality.FINAL, Visibilities.PUBLIC)
|
||||
|
||||
context.trace.record(BindingContext.FUNCTION, expression, functionDescriptor)
|
||||
}
|
||||
|
||||
private fun bindPropertyReference(expression: JetCallableReferenceExpression, referenceType: JetType, context: ResolutionContext<*>) {
|
||||
val localVariable = LocalVariableDescriptor(context.scope.getContainingDeclaration(), Annotations.EMPTY, Name.special("<anonymous>"),
|
||||
referenceType, /* mutable = */ false, expression.toSourceElement())
|
||||
|
||||
context.trace.record(BindingContext.VARIABLE, expression, localVariable)
|
||||
}
|
||||
|
||||
private fun createReflectionTypeForCallableDescriptor(
|
||||
descriptor: CallableDescriptor,
|
||||
context: ResolutionContext<*>,
|
||||
reflectionTypes: ReflectionTypes,
|
||||
reportOn: JetExpression?
|
||||
): JetType? {
|
||||
val extensionReceiver = descriptor.getExtensionReceiverParameter()
|
||||
val dispatchReceiver = descriptor.getDispatchReceiverParameter()
|
||||
|
||||
if (extensionReceiver != null && dispatchReceiver != null && descriptor is CallableMemberDescriptor) {
|
||||
if (reportOn != null) {
|
||||
context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reportOn, descriptor))
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
val receiverType = extensionReceiver?.getType() ?: dispatchReceiver?.getType()
|
||||
|
||||
return when (descriptor) {
|
||||
is FunctionDescriptor ->
|
||||
createReflectionTypeForFunction(descriptor, receiverType, reflectionTypes)
|
||||
is PropertyDescriptor ->
|
||||
createReflectionTypeForProperty(descriptor, receiverType, reflectionTypes)
|
||||
is VariableDescriptor -> {
|
||||
if (reportOn != null) {
|
||||
context.trace.report(UNSUPPORTED.on(reportOn, "References to variables aren't supported yet"))
|
||||
}
|
||||
null
|
||||
}
|
||||
else ->
|
||||
throw UnsupportedOperationException("Callable reference resolved to an unsupported descriptor: $descriptor")
|
||||
}
|
||||
}
|
||||
|
||||
public fun getReflectionTypeForCandidateDescriptor(
|
||||
descriptor: CallableDescriptor,
|
||||
context: ResolutionContext<*>,
|
||||
reflectionTypes: ReflectionTypes
|
||||
): JetType? =
|
||||
createReflectionTypeForCallableDescriptor(descriptor, context, reflectionTypes, null)
|
||||
|
||||
public fun createReflectionTypeForResolvedCallableReference(
|
||||
reference: JetCallableReferenceExpression,
|
||||
descriptor: CallableDescriptor,
|
||||
context: ResolutionContext<*>,
|
||||
reflectionTypes: ReflectionTypes
|
||||
): JetType? {
|
||||
val type = createReflectionTypeForCallableDescriptor(descriptor, context, reflectionTypes, reference.getCallableReference())
|
||||
?: return null
|
||||
when (descriptor) {
|
||||
is FunctionDescriptor -> {
|
||||
bindFunctionReference(reference, type, context)
|
||||
}
|
||||
is PropertyDescriptor -> {
|
||||
bindPropertyReference(reference, type, context)
|
||||
}
|
||||
}
|
||||
return type
|
||||
}
|
||||
|
||||
public fun getResolvedCallableReferenceShapeType(
|
||||
reference: JetCallableReferenceExpression,
|
||||
overloadResolutionResults: OverloadResolutionResults<CallableDescriptor>?,
|
||||
context: ResolutionContext<*>,
|
||||
expectedTypeUnknown: Boolean,
|
||||
reflectionTypes: ReflectionTypes,
|
||||
builtIns: KotlinBuiltIns
|
||||
): JetType? =
|
||||
when {
|
||||
overloadResolutionResults == null ->
|
||||
null
|
||||
overloadResolutionResults.isSingleResult() ->
|
||||
OverloadResolutionResultsUtil.getResultingCall(overloadResolutionResults, context.contextDependency)?.let { call ->
|
||||
createReflectionTypeForCallableDescriptor(call.getResultingDescriptor(), context, reflectionTypes, reference)
|
||||
}
|
||||
expectedTypeUnknown /* && overload resolution was ambiguous */ ->
|
||||
ErrorUtils.createFunctionPlaceholderType(emptyList(), false)
|
||||
else ->
|
||||
builtIns.getFunctionType(Annotations.EMPTY, null, emptyList(), TypeUtils.DONT_CARE)
|
||||
}
|
||||
+72
-10
@@ -20,16 +20,20 @@ import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes;
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesPackage;
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments;
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory;
|
||||
@@ -60,17 +64,23 @@ import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
|
||||
public class ArgumentTypeResolver {
|
||||
@NotNull private final TypeResolver typeResolver;
|
||||
@NotNull private final CallResolver callResolver;
|
||||
@NotNull private final ExpressionTypingServices expressionTypingServices;
|
||||
@NotNull private final KotlinBuiltIns builtIns;
|
||||
@NotNull private final ReflectionTypes reflectionTypes;
|
||||
|
||||
public ArgumentTypeResolver(
|
||||
@NotNull KotlinBuiltIns builtIns,
|
||||
@NotNull TypeResolver typeResolver,
|
||||
@NotNull CallResolver callResolver,
|
||||
@NotNull ExpressionTypingServices expressionTypingServices,
|
||||
@NotNull TypeResolver typeResolver
|
||||
@NotNull KotlinBuiltIns builtIns,
|
||||
@NotNull ReflectionTypes reflectionTypes
|
||||
) {
|
||||
this.builtIns = builtIns;
|
||||
this.expressionTypingServices = expressionTypingServices;
|
||||
this.typeResolver = typeResolver;
|
||||
this.callResolver = callResolver;
|
||||
this.expressionTypingServices = expressionTypingServices;
|
||||
this.builtIns = builtIns;
|
||||
this.reflectionTypes = reflectionTypes;
|
||||
}
|
||||
|
||||
public static boolean isSubtypeOfForArgumentType(
|
||||
@@ -92,7 +102,7 @@ public class ArgumentTypeResolver {
|
||||
@NotNull CallResolutionContext<?> context,
|
||||
@NotNull ResolveArgumentsMode resolveFunctionArgumentBodies
|
||||
) {
|
||||
if (context.checkArguments == CheckValueArgumentsMode.DISABLED) return;
|
||||
if (context.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) return;
|
||||
|
||||
for (ValueArgument valueArgument : context.call.getValueArguments()) {
|
||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||
@@ -117,7 +127,7 @@ public class ArgumentTypeResolver {
|
||||
}
|
||||
|
||||
public void checkTypesForFunctionArgumentsWithNoCallee(@NotNull CallResolutionContext<?> context) {
|
||||
if (context.checkArguments == CheckValueArgumentsMode.DISABLED) return;
|
||||
if (context.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) return;
|
||||
|
||||
for (ValueArgument valueArgument : context.call.getValueArguments()) {
|
||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||
@@ -148,7 +158,7 @@ public class ArgumentTypeResolver {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JetFunction getFunctionLiteralArgumentIfAny(
|
||||
public static JetFunction getFunctionLiteralArgumentIfAny(
|
||||
@NotNull JetExpression expression, @NotNull ResolutionContext context
|
||||
) {
|
||||
JetExpression deparenthesizedExpression = getLastElementDeparenthesized(expression, context.statementFilter);
|
||||
@@ -181,6 +191,18 @@ public class ArgumentTypeResolver {
|
||||
return deparenthesizedExpression;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetCallableReferenceExpression getCallableReferenceExpressionIfAny(
|
||||
@NotNull JetExpression expression,
|
||||
@NotNull CallResolutionContext<?> context
|
||||
) {
|
||||
JetExpression deparenthesizedExpression = getLastElementDeparenthesized(expression, context.statementFilter);
|
||||
if (deparenthesizedExpression instanceof JetCallableReferenceExpression) {
|
||||
return (JetCallableReferenceExpression) deparenthesizedExpression;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetTypeInfo getArgumentTypeInfo(
|
||||
@Nullable JetExpression expression,
|
||||
@@ -190,18 +212,58 @@ public class ArgumentTypeResolver {
|
||||
if (expression == null) {
|
||||
return TypeInfoFactoryPackage.noTypeInfo(context);
|
||||
}
|
||||
if (isFunctionLiteralArgument(expression, context)) {
|
||||
return getFunctionLiteralTypeInfo(expression, getFunctionLiteralArgument(expression, context), context, resolveArgumentsMode);
|
||||
|
||||
JetFunction functionLiteralArgument = getFunctionLiteralArgumentIfAny(expression, context);
|
||||
if (functionLiteralArgument != null) {
|
||||
return getFunctionLiteralTypeInfo(expression, functionLiteralArgument, context, resolveArgumentsMode);
|
||||
}
|
||||
|
||||
JetCallableReferenceExpression callableReferenceExpression = getCallableReferenceExpressionIfAny(expression, context);
|
||||
if (callableReferenceExpression != null) {
|
||||
return getCallableReferenceTypeInfo(expression, callableReferenceExpression, context, resolveArgumentsMode);
|
||||
}
|
||||
|
||||
JetTypeInfo recordedTypeInfo = getRecordedTypeInfo(expression, context.trace.getBindingContext());
|
||||
if (recordedTypeInfo != null) {
|
||||
return recordedTypeInfo;
|
||||
}
|
||||
|
||||
ResolutionContext newContext = context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(DEPENDENT);
|
||||
|
||||
return expressionTypingServices.getTypeInfo(expression, newContext);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetTypeInfo getCallableReferenceTypeInfo(
|
||||
@NotNull JetExpression expression,
|
||||
@NotNull JetCallableReferenceExpression callableReferenceExpression,
|
||||
@NotNull CallResolutionContext<?> context,
|
||||
@NotNull ResolveArgumentsMode resolveArgumentsMode
|
||||
) {
|
||||
if (resolveArgumentsMode == SHAPE_FUNCTION_ARGUMENTS) {
|
||||
JetType type = getShapeTypeOfCallableReference(callableReferenceExpression, context, true);
|
||||
return TypeInfoFactoryPackage.createTypeInfo(type);
|
||||
}
|
||||
return expressionTypingServices.getTypeInfo(expression, context.replaceContextDependency(INDEPENDENT));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetType getShapeTypeOfCallableReference(
|
||||
@NotNull JetCallableReferenceExpression callableReferenceExpression,
|
||||
@NotNull CallResolutionContext<?> context,
|
||||
boolean expectedTypeIsUnknown
|
||||
) {
|
||||
JetType receiverType =
|
||||
CallableReferencesPackage.resolveCallableReferenceReceiverType(callableReferenceExpression, context, typeResolver);
|
||||
OverloadResolutionResults<CallableDescriptor> overloadResolutionResults =
|
||||
CallableReferencesPackage.resolvePossiblyAmbiguousCallableReference(
|
||||
callableReferenceExpression, receiverType, context, ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS,
|
||||
callResolver);
|
||||
return CallableReferencesPackage.getResolvedCallableReferenceShapeType(
|
||||
callableReferenceExpression, overloadResolutionResults, context, expectedTypeIsUnknown,
|
||||
reflectionTypes, builtIns);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetTypeInfo getFunctionLiteralTypeInfo(
|
||||
@NotNull JetExpression expression,
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedT
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallCandidateResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.*
|
||||
@@ -194,7 +194,7 @@ public class CallCompleter(
|
||||
context: BasicCallResolutionContext,
|
||||
results: OverloadResolutionResultsImpl<D>
|
||||
) {
|
||||
if (context.checkArguments == CheckValueArgumentsMode.DISABLED) return
|
||||
if (context.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) return
|
||||
|
||||
val getArgumentMapping: (ValueArgument) -> ArgumentMapping
|
||||
val getDataFlowInfoForArgument: (ValueArgument) -> DataFlowInfo
|
||||
@@ -247,10 +247,15 @@ public class CallCompleter(
|
||||
|
||||
// While the expected type is not known, the function literal arguments are not analyzed (to analyze function literal bodies once),
|
||||
// but they should be analyzed when the expected type is known (during the call completion).
|
||||
if (ArgumentTypeResolver.isFunctionLiteralArgument(expression, context)) {
|
||||
argumentTypeResolver.getFunctionLiteralTypeInfo(
|
||||
expression, ArgumentTypeResolver.getFunctionLiteralArgument(expression, context),
|
||||
context, RESOLVE_FUNCTION_ARGUMENTS)
|
||||
ArgumentTypeResolver.getFunctionLiteralArgumentIfAny(expression, context)?.let { functionLiteralArgument ->
|
||||
argumentTypeResolver.getFunctionLiteralTypeInfo(expression, functionLiteralArgument, context, RESOLVE_FUNCTION_ARGUMENTS)
|
||||
}
|
||||
|
||||
// While the expected type is not known, (possibly overloaded) callable references can have placeholder types
|
||||
// (to avoid exponential search for overloaded higher-order functions).
|
||||
// They should be analyzed now.
|
||||
ArgumentTypeResolver.getCallableReferenceExpressionIfAny(expression, context)?.let { callableReferenceArgument ->
|
||||
argumentTypeResolver.getCallableReferenceTypeInfo(expression, callableReferenceArgument, context, RESOLVE_FUNCTION_ARGUMENTS)
|
||||
}
|
||||
|
||||
DataFlowUtils.checkType(updatedType, deparenthesized, context)
|
||||
|
||||
+5
-5
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
@@ -78,7 +78,7 @@ public class CallExpressionResolver {
|
||||
@Nullable
|
||||
public ResolvedCall<FunctionDescriptor> getResolvedCallForFunction(
|
||||
@NotNull Call call, @NotNull JetExpression callExpression,
|
||||
@NotNull ResolutionContext context, @NotNull CheckValueArgumentsMode checkArguments,
|
||||
@NotNull ResolutionContext context, @NotNull CheckArgumentTypesMode checkArguments,
|
||||
@NotNull boolean[] result
|
||||
) {
|
||||
OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveFunctionCall(
|
||||
@@ -101,7 +101,7 @@ public class CallExpressionResolver {
|
||||
Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression);
|
||||
BasicCallResolutionContext contextForVariable = BasicCallResolutionContext.create(
|
||||
context.replaceTraceAndCache(temporaryForVariable),
|
||||
call, CheckValueArgumentsMode.ENABLED);
|
||||
call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
|
||||
OverloadResolutionResults<VariableDescriptor> resolutionResult = callResolver.resolveSimpleProperty(contextForVariable);
|
||||
|
||||
// if the expression is a receiver in a qualified expression, it should be resolved after the selector is resolved
|
||||
@@ -154,7 +154,7 @@ public class CallExpressionResolver {
|
||||
context, "trace to resolve as function", nameExpression);
|
||||
ResolutionContext newContext = context.replaceTraceAndCache(temporaryForFunction);
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = getResolvedCallForFunction(
|
||||
call, nameExpression, newContext, CheckValueArgumentsMode.ENABLED, result);
|
||||
call, nameExpression, newContext, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, result);
|
||||
if (result[0]) {
|
||||
FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
|
||||
temporaryForFunction.commit();
|
||||
@@ -198,7 +198,7 @@ public class CallExpressionResolver {
|
||||
call, callExpression,
|
||||
// It's possible start of a call so we should reset safe call chain
|
||||
context.replaceTraceAndCache(temporaryForFunction).replaceInsideCallChain(false),
|
||||
CheckValueArgumentsMode.ENABLED, result);
|
||||
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, result);
|
||||
if (result[0]) {
|
||||
FunctionDescriptor functionDescriptor = resolvedCall != null ? resolvedCall.getResultingDescriptor() : null;
|
||||
temporaryForFunction.commit();
|
||||
|
||||
@@ -164,7 +164,7 @@ public class CallResolver {
|
||||
@NotNull JetReferenceExpression functionReference,
|
||||
@NotNull Name name
|
||||
) {
|
||||
BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED);
|
||||
BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS);
|
||||
return computeTasksAndResolveCall(
|
||||
callResolutionContext, name, functionReference,
|
||||
CallableDescriptorCollectors.FUNCTIONS_AND_VARIABLES, CallTransformer.FUNCTION_CALL_TRANSFORMER);
|
||||
@@ -263,7 +263,7 @@ public class CallResolver {
|
||||
) {
|
||||
return resolveFunctionCall(
|
||||
BasicCallResolutionContext.create(
|
||||
trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
|
||||
trace, scope, call, expectedType, dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
additionalCheckerProvider.getCallChecker(), additionalCheckerProvider.getSymbolUsageValidator(),
|
||||
additionalCheckerProvider.getTypeChecker(), isAnnotationContext)
|
||||
);
|
||||
@@ -344,7 +344,7 @@ public class CallResolver {
|
||||
trace, scope,
|
||||
CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call),
|
||||
NO_EXPECTED_TYPE,
|
||||
dataFlowInfo, ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
|
||||
dataFlowInfo, ContextDependency.INDEPENDENT, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
callChecker, additionalCheckerProvider.getSymbolUsageValidator(), additionalCheckerProvider.getTypeChecker(), false);
|
||||
|
||||
if (call.getCalleeExpression() == null) return checkArgumentTypesAndFail(context);
|
||||
@@ -430,7 +430,7 @@ public class CallResolver {
|
||||
@Override
|
||||
public OverloadResolutionResults<FunctionDescriptor> invoke() {
|
||||
BasicCallResolutionContext basicCallResolutionContext =
|
||||
BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.ENABLED, dataFlowInfoForArguments);
|
||||
BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, dataFlowInfoForArguments);
|
||||
|
||||
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> tasks =
|
||||
taskPrioritizer.<CallableDescriptor, FunctionDescriptor>computePrioritizedTasksFromCandidates(
|
||||
@@ -484,7 +484,7 @@ public class CallResolver {
|
||||
|
||||
CallCandidateResolutionContext<D> candidateContext = CallCandidateResolutionContext.createForCallBeingAnalyzed(
|
||||
results.getResultingCall(), context, tracing);
|
||||
genericCandidateResolver.completeTypeInferenceDependentOnFunctionLiteralsForCall(candidateContext);
|
||||
genericCandidateResolver.completeTypeInferenceDependentOnFunctionArgumentsForCall(candidateContext);
|
||||
}
|
||||
|
||||
private static <F extends CallableDescriptor> void cacheResults(
|
||||
@@ -515,7 +515,7 @@ public class CallResolver {
|
||||
@NotNull CallTransformer<D, F> callTransformer,
|
||||
@NotNull TracingStrategy tracing
|
||||
) {
|
||||
if (context.checkArguments == CheckValueArgumentsMode.ENABLED) {
|
||||
if (context.checkArguments == CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) {
|
||||
argumentTypeResolver.analyzeArgumentsAndRecordTypes(context);
|
||||
}
|
||||
Collection<ResolvedCall<F>> allCandidates = Lists.newArrayList();
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.callResolverUtil
|
||||
import com.google.common.collect.Lists
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
@@ -33,6 +34,8 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
||||
import org.jetbrains.kotlin.types.typeUtil.getNestedArguments
|
||||
import java.util.*
|
||||
|
||||
public enum class ResolveArgumentsMode {
|
||||
RESOLVE_FUNCTION_ARGUMENTS,
|
||||
@@ -41,30 +44,34 @@ public enum class ResolveArgumentsMode {
|
||||
|
||||
|
||||
public fun hasUnknownFunctionParameter(type: JetType): Boolean {
|
||||
assert(KotlinBuiltIns.isFunctionOrExtensionFunctionType(type))
|
||||
val arguments = type.getArguments()
|
||||
// last argument is return type of function type
|
||||
val functionParameters = arguments.subList(0, arguments.size() - 1)
|
||||
return functionParameters.any {
|
||||
assert(ReflectionTypes.isCallableType(type), "type is not a function or property")
|
||||
return getParameterArgumentsOfCallableType(type).any {
|
||||
TypeUtils.containsSpecialType(it.getType(), DONT_CARE) || ErrorUtils.containsUninferredParameter(it.getType())
|
||||
}
|
||||
}
|
||||
|
||||
public fun hasUnknownReturnType(type: JetType): Boolean {
|
||||
assert(KotlinBuiltIns.isFunctionOrExtensionFunctionType(type))
|
||||
val returnTypeFromFunctionType = KotlinBuiltIns.getReturnTypeFromFunctionType(type)
|
||||
return ErrorUtils.containsErrorType(returnTypeFromFunctionType)
|
||||
assert(ReflectionTypes.isCallableType(type), "type is not a function or property")
|
||||
return ErrorUtils.containsErrorType(getReturnTypeForCallable(type))
|
||||
}
|
||||
|
||||
public fun replaceReturnTypeByUnknown(type: JetType): JetType {
|
||||
assert(KotlinBuiltIns.isFunctionOrExtensionFunctionType(type))
|
||||
val arguments = type.getArguments()
|
||||
assert(ReflectionTypes.isCallableType(type), "type is not a function or property")
|
||||
val newArguments = Lists.newArrayList<TypeProjection>()
|
||||
newArguments.addAll(arguments.subList(0, arguments.size() - 1))
|
||||
newArguments.addAll(getParameterArgumentsOfCallableType(type))
|
||||
newArguments.add(TypeProjectionImpl(Variance.INVARIANT, DONT_CARE))
|
||||
return JetTypeImpl(type.getAnnotations(), type.getConstructor(), type.isMarkedNullable(), newArguments, type.getMemberScope())
|
||||
return replaceTypeArguments(type, newArguments)
|
||||
}
|
||||
|
||||
private fun replaceTypeArguments(type: JetType, newArguments: List<TypeProjection>) =
|
||||
JetTypeImpl(type.getAnnotations(), type.getConstructor(), type.isMarkedNullable(), newArguments, type.getMemberScope())
|
||||
|
||||
private fun getParameterArgumentsOfCallableType(type: JetType) =
|
||||
type.getArguments().dropLast(1)
|
||||
|
||||
private fun getReturnTypeForCallable(type: JetType) =
|
||||
type.getArguments().last().getType()
|
||||
|
||||
private fun CallableDescriptor.hasReturnTypeDependentOnUninferredParams(constraintSystem: ConstraintSystem): Boolean {
|
||||
val returnType = getReturnType() ?: return false
|
||||
|
||||
|
||||
@@ -19,12 +19,14 @@ package org.jetbrains.kotlin.resolve.calls
|
||||
import com.google.common.collect.Lists
|
||||
import com.google.common.collect.Sets
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.SUPER_CANT_BE_EXTENSION_RECEIVER
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.callableReferences.getReflectionTypeForCandidateDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer.CallForImplicitInvoke
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.SHAPE_FUNCTION_ARGUMENTS
|
||||
@@ -60,11 +62,14 @@ import java.util.ArrayList
|
||||
|
||||
public class CandidateResolver(
|
||||
private val argumentTypeResolver: ArgumentTypeResolver,
|
||||
private val genericCandidateResolver: GenericCandidateResolver
|
||||
private val genericCandidateResolver: GenericCandidateResolver,
|
||||
private val reflectionTypes: ReflectionTypes
|
||||
){
|
||||
|
||||
public fun <D : CallableDescriptor, F : D> performResolutionForCandidateCall(context: CallCandidateResolutionContext<D>,
|
||||
task: ResolutionTask<D, F>): Unit = with(context) {
|
||||
public fun <D : CallableDescriptor, F : D> performResolutionForCandidateCall(
|
||||
context: CallCandidateResolutionContext<D>,
|
||||
task: ResolutionTask<D, F>
|
||||
): Unit = with(context) {
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||
|
||||
if (ErrorUtils.isError(candidateDescriptor)) {
|
||||
@@ -78,7 +83,13 @@ public class CandidateResolver(
|
||||
}
|
||||
|
||||
checkVisibility()
|
||||
mapArguments(task)
|
||||
|
||||
when (task.checkArguments) {
|
||||
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ->
|
||||
mapArguments()
|
||||
CheckArgumentTypesMode.CHECK_CALLABLE_TYPE ->
|
||||
checkExpectedCallableType()
|
||||
}
|
||||
|
||||
checkReceiverTypeError()
|
||||
checkExtensionReceiver()
|
||||
@@ -143,15 +154,27 @@ public class CandidateResolver(
|
||||
}
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor, F : D> CallCandidateResolutionContext<D>.mapArguments(task: ResolutionTask<D, F>) = check {
|
||||
if (task.checkArguments == CheckValueArgumentsMode.ENABLED) {
|
||||
val argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(
|
||||
call, tracing, candidateCall, Sets.newLinkedHashSet<ValueArgument>())
|
||||
if (!argumentMappingStatus.isSuccess()) {
|
||||
candidateCall.addStatus(OTHER_ERROR)
|
||||
private fun <D : CallableDescriptor, F : D> CallCandidateResolutionContext<D>.mapArguments()
|
||||
= check {
|
||||
val argumentMappingStatus = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(
|
||||
call, tracing, candidateCall, Sets.newLinkedHashSet<ValueArgument>())
|
||||
if (!argumentMappingStatus.isSuccess()) {
|
||||
candidateCall.addStatus(OTHER_ERROR)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor, F : D> CallCandidateResolutionContext<D>.checkExpectedCallableType()
|
||||
= check {
|
||||
if (!noExpectedType(expectedType)) {
|
||||
val candidate = candidateCall.getCandidateDescriptor()
|
||||
val candidateReflectionType = getReflectionTypeForCandidateDescriptor(candidate, this, reflectionTypes);
|
||||
if (candidateReflectionType != null) {
|
||||
if (!JetTypeChecker.DEFAULT.isSubtypeOf(candidateReflectionType, expectedType)) {
|
||||
candidateCall.addStatus(OTHER_ERROR)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun CallCandidateResolutionContext<*>.checkVisibility() = checkAndReport {
|
||||
val receiverValue = ExpressionTypingUtils.normalizeReceiverValueForVisibility(candidateCall.getDispatchReceiver(),
|
||||
|
||||
+64
-10
@@ -19,9 +19,7 @@ package org.jetbrains.kotlin.resolve.calls
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.JetExpression
|
||||
import org.jetbrains.kotlin.psi.JetPsiUtil
|
||||
import org.jetbrains.kotlin.psi.ValueArgument
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.FunctionDescriptorUtil
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver.getLastElementDeparenthesized
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.*
|
||||
@@ -39,6 +37,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.Constrain
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.EXPECTED_TYPE_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.OTHER_ERROR
|
||||
@@ -197,7 +196,7 @@ class GenericCandidateResolver(
|
||||
return TypeUtils.intersect(JetTypeChecker.DEFAULT, possibleTypes)
|
||||
}
|
||||
|
||||
public fun <D : CallableDescriptor> completeTypeInferenceDependentOnFunctionLiteralsForCall(
|
||||
public fun <D : CallableDescriptor> completeTypeInferenceDependentOnFunctionArgumentsForCall(
|
||||
context: CallCandidateResolutionContext<D>
|
||||
) {
|
||||
val resolvedCall = context.candidateCall
|
||||
@@ -210,30 +209,35 @@ class GenericCandidateResolver(
|
||||
val valueParameterDescriptor = entry.getKey()
|
||||
|
||||
for (valueArgument in resolvedValueArgument.getArguments()) {
|
||||
addConstraintForFunctionLiteral(valueArgument, valueParameterDescriptor, constraintSystem, context)
|
||||
valueArgument.getArgumentExpression()?.let { argumentExpression ->
|
||||
ArgumentTypeResolver.getFunctionLiteralArgumentIfAny(argumentExpression, context)?.let { functionLiteral ->
|
||||
addConstraintForFunctionLiteral(functionLiteral, valueArgument, valueParameterDescriptor, constraintSystem, context)
|
||||
}
|
||||
ArgumentTypeResolver.getCallableReferenceExpressionIfAny(argumentExpression, context)?.let { callableReference ->
|
||||
addConstraintForCallableReference(callableReference, valueArgument, valueParameterDescriptor, constraintSystem, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor())
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor> addConstraintForFunctionLiteral(
|
||||
functionLiteral: JetFunction,
|
||||
valueArgument: ValueArgument,
|
||||
valueParameterDescriptor: ValueParameterDescriptor,
|
||||
constraintSystem: ConstraintSystem,
|
||||
context: CallCandidateResolutionContext<D>
|
||||
) {
|
||||
val argumentExpression = valueArgument.getArgumentExpression() ?: return
|
||||
if (!ArgumentTypeResolver.isFunctionLiteralArgument(argumentExpression, context)) return
|
||||
|
||||
val functionLiteral = ArgumentTypeResolver.getFunctionLiteralArgument(argumentExpression, context)
|
||||
|
||||
val effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument)
|
||||
var expectedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT)
|
||||
if (expectedType == null || TypeUtils.isDontCarePlaceholder(expectedType)) {
|
||||
expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, false)
|
||||
}
|
||||
if (expectedType == null || !KotlinBuiltIns.isFunctionOrExtensionFunctionType(expectedType)
|
||||
|| hasUnknownFunctionParameter(expectedType)) {
|
||||
if (expectedType == null || !KotlinBuiltIns.isFunctionOrExtensionFunctionType(expectedType) ||
|
||||
hasUnknownFunctionParameter(expectedType)) {
|
||||
return
|
||||
}
|
||||
val dataFlowInfoForArguments = context.candidateCall.getDataFlowInfoForArguments()
|
||||
@@ -267,6 +271,56 @@ class GenericCandidateResolver(
|
||||
val type = argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS).type
|
||||
constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, position)
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor> addConstraintForCallableReference(
|
||||
callableReference: JetCallableReferenceExpression,
|
||||
valueArgument: ValueArgument,
|
||||
valueParameterDescriptor: ValueParameterDescriptor,
|
||||
constraintSystem: ConstraintSystem,
|
||||
context: CallCandidateResolutionContext<D>
|
||||
) {
|
||||
val effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument)
|
||||
val expectedType = getExpectedTypeForCallableReference(callableReference, constraintSystem, context, effectiveExpectedType)
|
||||
?: return
|
||||
val resolvedType = getResolvedTypeForCallableReference(callableReference, context, expectedType, valueArgument)
|
||||
val position = VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.getIndex())
|
||||
constraintSystem.addSubtypeConstraint(resolvedType, effectiveExpectedType, position)
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor> getExpectedTypeForCallableReference(
|
||||
callableReference: JetCallableReferenceExpression,
|
||||
constraintSystem: ConstraintSystem,
|
||||
context: CallCandidateResolutionContext<D>,
|
||||
effectiveExpectedType: JetType
|
||||
): JetType? {
|
||||
val substitutedType = constraintSystem.getCurrentSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT)
|
||||
if (substitutedType != null && !TypeUtils.isDontCarePlaceholder(substitutedType))
|
||||
return substitutedType
|
||||
|
||||
val shapeType = argumentTypeResolver.getShapeTypeOfCallableReference(callableReference, context, false)
|
||||
if (shapeType != null && KotlinBuiltIns.isFunctionOrExtensionFunctionType(shapeType) && !hasUnknownFunctionParameter(shapeType))
|
||||
return shapeType
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor> getResolvedTypeForCallableReference(
|
||||
callableReference: JetCallableReferenceExpression,
|
||||
context: CallCandidateResolutionContext<D>,
|
||||
expectedType: JetType,
|
||||
valueArgument: ValueArgument
|
||||
): JetType? {
|
||||
val dataFlowInfoForArgument = context.candidateCall.getDataFlowInfoForArguments().getInfo(valueArgument)
|
||||
val expectedTypeWithoutReturnType = if (!hasUnknownReturnType(expectedType)) replaceReturnTypeByUnknown(expectedType) else expectedType
|
||||
val newContext = context
|
||||
.replaceExpectedType(expectedTypeWithoutReturnType)
|
||||
.replaceDataFlowInfo(dataFlowInfoForArgument)
|
||||
.replaceContextDependency(INDEPENDENT)
|
||||
val argumentExpression = valueArgument.getArgumentExpression()!!
|
||||
val type = argumentTypeResolver.getCallableReferenceTypeInfo(
|
||||
argumentExpression, callableReference, newContext, RESOLVE_FUNCTION_ARGUMENTS).type
|
||||
return type
|
||||
}
|
||||
}
|
||||
|
||||
fun getResolutionResultsCachedData(expression: JetExpression?, context: ResolutionContext<*>): ResolutionResultsCache.CachedData? {
|
||||
|
||||
+4
-4
@@ -37,7 +37,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
@NotNull JetType expectedType,
|
||||
@NotNull DataFlowInfo dataFlowInfo,
|
||||
@NotNull ContextDependency contextDependency,
|
||||
@NotNull CheckValueArgumentsMode checkArguments,
|
||||
@NotNull CheckArgumentTypesMode checkArguments,
|
||||
@NotNull ResolutionResultsCache resolutionResultsCache,
|
||||
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments,
|
||||
@NotNull CallChecker callChecker,
|
||||
@@ -60,7 +60,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
@NotNull JetType expectedType,
|
||||
@NotNull DataFlowInfo dataFlowInfo,
|
||||
@NotNull ContextDependency contextDependency,
|
||||
@NotNull CheckValueArgumentsMode checkArguments,
|
||||
@NotNull CheckArgumentTypesMode checkArguments,
|
||||
@NotNull CallChecker callChecker,
|
||||
@NotNull SymbolUsageValidator symbolUsageValidator,
|
||||
@NotNull AdditionalTypeChecker additionalTypeChecker,
|
||||
@@ -73,7 +73,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
|
||||
@NotNull
|
||||
public static BasicCallResolutionContext create(
|
||||
@NotNull ResolutionContext context, @NotNull Call call, @NotNull CheckValueArgumentsMode checkArguments,
|
||||
@NotNull ResolutionContext context, @NotNull Call call, @NotNull CheckArgumentTypesMode checkArguments,
|
||||
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments
|
||||
) {
|
||||
return new BasicCallResolutionContext(
|
||||
@@ -85,7 +85,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
|
||||
@NotNull
|
||||
public static BasicCallResolutionContext create(
|
||||
@NotNull ResolutionContext context, @NotNull Call call, @NotNull CheckValueArgumentsMode checkArguments
|
||||
@NotNull ResolutionContext context, @NotNull Call call, @NotNull CheckArgumentTypesMode checkArguments
|
||||
) {
|
||||
return create(context, call, checkArguments, null);
|
||||
}
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
|
||||
@NotNull JetType expectedType,
|
||||
@NotNull DataFlowInfo dataFlowInfo,
|
||||
@NotNull ContextDependency contextDependency,
|
||||
@NotNull CheckValueArgumentsMode checkArguments,
|
||||
@NotNull CheckArgumentTypesMode checkArguments,
|
||||
@NotNull ResolutionResultsCache resolutionResultsCache,
|
||||
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments,
|
||||
@NotNull CallChecker callChecker,
|
||||
|
||||
+3
-3
@@ -34,7 +34,7 @@ public abstract class CallResolutionContext<Context extends CallResolutionContex
|
||||
@NotNull
|
||||
public final Call call;
|
||||
@NotNull
|
||||
public final CheckValueArgumentsMode checkArguments;
|
||||
public final CheckArgumentTypesMode checkArguments;
|
||||
@NotNull
|
||||
public final MutableDataFlowInfoForArguments dataFlowInfoForArguments;
|
||||
|
||||
@@ -45,7 +45,7 @@ public abstract class CallResolutionContext<Context extends CallResolutionContex
|
||||
@NotNull JetType expectedType,
|
||||
@NotNull DataFlowInfo dataFlowInfo,
|
||||
@NotNull ContextDependency contextDependency,
|
||||
@NotNull CheckValueArgumentsMode checkArguments,
|
||||
@NotNull CheckArgumentTypesMode checkArguments,
|
||||
@NotNull ResolutionResultsCache resolutionResultsCache,
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments,
|
||||
@@ -65,7 +65,7 @@ public abstract class CallResolutionContext<Context extends CallResolutionContex
|
||||
if (dataFlowInfoForArguments != null) {
|
||||
this.dataFlowInfoForArguments = dataFlowInfoForArguments;
|
||||
}
|
||||
else if (checkArguments == CheckValueArgumentsMode.ENABLED) {
|
||||
else if (checkArguments == CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS) {
|
||||
this.dataFlowInfoForArguments = new DataFlowInfoForArgumentsImpl(call);
|
||||
}
|
||||
else {
|
||||
|
||||
+9
-3
@@ -16,7 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.context;
|
||||
|
||||
public enum CheckValueArgumentsMode {
|
||||
ENABLED,
|
||||
DISABLED
|
||||
public enum CheckArgumentTypesMode {
|
||||
/**
|
||||
* Check value argument types for particular call.
|
||||
*/
|
||||
CHECK_VALUE_ARGUMENTS,
|
||||
/**
|
||||
* Match callable reference type against expected (callable) type.
|
||||
*/
|
||||
CHECK_CALLABLE_TYPE
|
||||
}
|
||||
+2
-2
@@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.kotlin.resolve.OverrideResolver;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionTask;
|
||||
|
||||
@@ -101,7 +101,7 @@ public class ResolutionResultsHandler {
|
||||
boolean allCandidatesIncomplete = allIncomplete(results.getResultingCalls());
|
||||
// This check is needed for the following case:
|
||||
// x.foo(unresolved) -- if there are multiple foo's, we'd report an ambiguity, and it does not make sense here
|
||||
if (task.checkArguments == CheckValueArgumentsMode.DISABLED ||
|
||||
if (task.checkArguments != CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ||
|
||||
!CallUtilPackage.hasUnresolvedArguments(task.call, task)) {
|
||||
if (allCandidatesIncomplete) {
|
||||
task.tracing.cannotCompleteResolve(task.trace, results.getResultingCalls());
|
||||
|
||||
@@ -53,7 +53,7 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
|
||||
@NotNull JetType expectedType,
|
||||
@NotNull DataFlowInfo dataFlowInfo,
|
||||
@NotNull ContextDependency contextDependency,
|
||||
@NotNull CheckValueArgumentsMode checkArguments,
|
||||
@NotNull CheckArgumentTypesMode checkArguments,
|
||||
@NotNull ResolutionResultsCache resolutionResultsCache,
|
||||
@Nullable MutableDataFlowInfoForArguments dataFlowInfoForArguments,
|
||||
@NotNull CallChecker callChecker,
|
||||
|
||||
+8
-167
@@ -30,17 +30,15 @@ import org.jetbrains.kotlin.JetNodeTypes;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesPackage;
|
||||
import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckValueArgumentsMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl;
|
||||
@@ -57,17 +55,13 @@ import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
|
||||
import org.jetbrains.kotlin.resolve.constants.*;
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
||||
import org.jetbrains.kotlin.resolve.scopes.WritableScopeImpl;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
|
||||
import org.jetbrains.kotlin.types.*;
|
||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryPackage;
|
||||
import org.jetbrains.kotlin.types.expressions.unqualifiedSuper.UnqualifiedSuperPackage;
|
||||
import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
|
||||
import org.jetbrains.kotlin.utils.ThrowingList;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -78,12 +72,10 @@ import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||
import static org.jetbrains.kotlin.lexer.JetTokens.AS_KEYWORD;
|
||||
import static org.jetbrains.kotlin.lexer.JetTokens.AS_SAFE;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getStaticNestedClassesScope;
|
||||
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.DEPENDENT;
|
||||
import static org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT;
|
||||
import static org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue;
|
||||
import static org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
|
||||
import static org.jetbrains.kotlin.resolve.source.SourcePackage.toSourceElement;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.noExpectedType;
|
||||
import static org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction;
|
||||
@@ -498,7 +490,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
trace.record(RESOLVED_CALL, call, resolvedCall);
|
||||
trace.record(CALL, expression, call);
|
||||
|
||||
BasicCallResolutionContext resolutionContext = BasicCallResolutionContext.create(context, call, CheckValueArgumentsMode.DISABLED);
|
||||
BasicCallResolutionContext resolutionContext = BasicCallResolutionContext.create(context, call, CheckArgumentTypesMode.CHECK_CALLABLE_TYPE);
|
||||
context.callChecker.check(resolvedCall, resolutionContext);
|
||||
context.symbolUsageValidator.validateCall(descriptor, trace, expression);
|
||||
}
|
||||
@@ -676,166 +668,15 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
) {
|
||||
JetSimpleNameExpression reference = expression.getCallableReference();
|
||||
|
||||
boolean[] result = new boolean[1];
|
||||
CallableDescriptor descriptor = resolveCallableReferenceTarget(
|
||||
lhsType, context.replaceContextDependency(INDEPENDENT), expression, result);
|
||||
|
||||
if (!result[0]) {
|
||||
boolean[] resolved = new boolean[1];
|
||||
CallableDescriptor descriptor = CallableReferencesPackage.resolveCallableReferenceTarget(
|
||||
expression, lhsType, context, resolved, components.callResolver);
|
||||
if (!resolved[0]) {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
|
||||
}
|
||||
if (descriptor == null) return null;
|
||||
|
||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
||||
ReceiverParameterDescriptor dispatchReceiver = descriptor.getDispatchReceiverParameter();
|
||||
if (extensionReceiver != null && dispatchReceiver != null && descriptor instanceof CallableMemberDescriptor) {
|
||||
context.trace.report(EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED.on(reference, (CallableMemberDescriptor) descriptor));
|
||||
return null;
|
||||
}
|
||||
|
||||
JetType receiverType = extensionReceiver != null ? extensionReceiver.getType() :
|
||||
dispatchReceiver != null ? dispatchReceiver.getType() :
|
||||
null;
|
||||
|
||||
if (descriptor instanceof FunctionDescriptor) {
|
||||
return createFunctionReferenceType(expression, context, (FunctionDescriptor) descriptor, receiverType);
|
||||
}
|
||||
else if (descriptor instanceof PropertyDescriptor) {
|
||||
return createPropertyReferenceType(expression, context, (PropertyDescriptor) descriptor, receiverType);
|
||||
}
|
||||
else if (descriptor instanceof VariableDescriptor) {
|
||||
context.trace.report(UNSUPPORTED.on(reference, "References to variables aren't supported yet"));
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Callable reference resolved to an unsupported descriptor: " + descriptor);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JetType createFunctionReferenceType(
|
||||
@NotNull JetCallableReferenceExpression expression,
|
||||
@NotNull ExpressionTypingContext context,
|
||||
@NotNull FunctionDescriptor descriptor,
|
||||
@Nullable JetType receiverType
|
||||
) {
|
||||
//noinspection ConstantConditions
|
||||
JetType type = components.reflectionTypes.getKFunctionType(
|
||||
Annotations.EMPTY,
|
||||
receiverType,
|
||||
getValueParametersTypes(descriptor.getValueParameters()),
|
||||
descriptor.getReturnType()
|
||||
);
|
||||
|
||||
AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
|
||||
context.scope.getContainingDeclaration(),
|
||||
Annotations.EMPTY,
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
toSourceElement(expression)
|
||||
);
|
||||
|
||||
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, type, null, Modality.FINAL, Visibilities.PUBLIC);
|
||||
|
||||
context.trace.record(FUNCTION, expression, functionDescriptor);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JetType createPropertyReferenceType(
|
||||
@NotNull JetCallableReferenceExpression expression,
|
||||
@NotNull ExpressionTypingContext context,
|
||||
@NotNull PropertyDescriptor descriptor,
|
||||
@Nullable JetType receiverType
|
||||
) {
|
||||
JetType type = components.reflectionTypes.getKPropertyType(
|
||||
Annotations.EMPTY, receiverType, descriptor.getType(), descriptor.isVar()
|
||||
);
|
||||
|
||||
LocalVariableDescriptor localVariable =
|
||||
new LocalVariableDescriptor(context.scope.getContainingDeclaration(), Annotations.EMPTY, Name.special("<anonymous>"),
|
||||
type, /* mutable = */ false, toSourceElement(expression));
|
||||
|
||||
context.trace.record(VARIABLE, expression, localVariable);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CallableDescriptor resolveCallableReferenceTarget(
|
||||
@Nullable JetType lhsType,
|
||||
@NotNull ExpressionTypingContext context,
|
||||
@NotNull JetCallableReferenceExpression expression,
|
||||
@NotNull boolean[] result
|
||||
) {
|
||||
JetSimpleNameExpression reference = expression.getCallableReference();
|
||||
|
||||
if (lhsType == null) {
|
||||
return resolveCallableNotCheckingArguments(reference, NO_RECEIVER, context, result);
|
||||
}
|
||||
|
||||
ClassifierDescriptor classifier = lhsType.getConstructor().getDeclarationDescriptor();
|
||||
if (!(classifier instanceof ClassDescriptor)) {
|
||||
context.trace.report(CALLABLE_REFERENCE_LHS_NOT_A_CLASS.on(expression));
|
||||
return null;
|
||||
}
|
||||
|
||||
JetScope staticScope = ((ClassDescriptor) classifier).getStaticScope();
|
||||
TemporaryTraceAndCache temporaryForStatic = TemporaryTraceAndCache.create(
|
||||
context, "trace to resolve callable reference in static scope", reference);
|
||||
CallableDescriptor possibleStatic = resolveCallableNotCheckingArguments(
|
||||
reference, NO_RECEIVER, context.replaceTraceAndCache(temporaryForStatic).replaceScope(staticScope), result);
|
||||
if (result[0]) {
|
||||
temporaryForStatic.commit();
|
||||
return possibleStatic;
|
||||
}
|
||||
|
||||
JetScope staticNestedClasses = getStaticNestedClassesScope((ClassDescriptor) classifier);
|
||||
TemporaryTraceAndCache temporaryForNested = TemporaryTraceAndCache.create(
|
||||
context, "trace to resolve callable reference in static nested classes scope", reference);
|
||||
CallableDescriptor possibleNestedClassConstructor = resolveCallableNotCheckingArguments(reference, NO_RECEIVER,
|
||||
context.replaceTraceAndCache(temporaryForNested).replaceScope(staticNestedClasses), result);
|
||||
if (result[0]) {
|
||||
temporaryForNested.commit();
|
||||
return possibleNestedClassConstructor;
|
||||
}
|
||||
|
||||
ReceiverValue receiver = new TransientReceiver(lhsType);
|
||||
TemporaryTraceAndCache temporaryWithReceiver = TemporaryTraceAndCache.create(
|
||||
context, "trace to resolve callable reference with receiver", reference);
|
||||
CallableDescriptor descriptor = resolveCallableNotCheckingArguments(
|
||||
reference, receiver, context.replaceTraceAndCache(temporaryWithReceiver), result);
|
||||
if (result[0]) {
|
||||
temporaryWithReceiver.commit();
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CallableDescriptor resolveCallableNotCheckingArguments(
|
||||
@NotNull JetSimpleNameExpression reference,
|
||||
@NotNull ReceiverValue receiver,
|
||||
@NotNull ExpressionTypingContext context,
|
||||
@NotNull boolean[] result
|
||||
) {
|
||||
Call call = CallMaker.makeCall(reference, receiver, null, reference, ThrowingList.<ValueArgument>instance());
|
||||
TemporaryTraceAndCache temporaryTrace = TemporaryTraceAndCache.create(context, "trace to resolve callable reference as function",
|
||||
reference);
|
||||
|
||||
BasicCallResolutionContext callResolutionContext = BasicCallResolutionContext.create(
|
||||
context.replaceTraceAndCache(temporaryTrace).replaceExpectedType(NO_EXPECTED_TYPE), call, CheckValueArgumentsMode.DISABLED);
|
||||
OverloadResolutionResults<CallableDescriptor> results =
|
||||
components.callResolver.resolveCallForMember(reference, callResolutionContext);
|
||||
if (!results.isNothing()) {
|
||||
temporaryTrace.commit();
|
||||
result[0] = true;
|
||||
ResolvedCall<CallableDescriptor> callable =
|
||||
OverloadResolutionResultsUtil.getResultingCall(results, context.contextDependency);
|
||||
if (callable != null) {
|
||||
return callable.getResultingDescriptor();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return CallableReferencesPackage.createReflectionTypeForResolvedCallableReference(expression, descriptor, context, components.reflectionTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
@@ -21,14 +21,18 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.analyzer.AnalyzerPackage;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
|
||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.callableReferences.CallableReferencesPackage;
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
||||
import org.jetbrains.kotlin.resolve.scopes.WritableScope;
|
||||
@@ -301,4 +305,5 @@ public class ExpressionTypingServices {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user