DelegatedPropertyResolver: convert to Kotlin & cleanup.
This commit is contained in:
committed by
Stanislav Erokhin
parent
85276c27f0
commit
558e8aaebb
@@ -14,461 +14,395 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.resolve;
|
package org.jetbrains.kotlin.resolve
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import com.intellij.psi.PsiElement;
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import com.intellij.util.Function;
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import kotlin.Pair;
|
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.resolve.BindingContext.*
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.resolve.calls.checkers.OperatorCallChecker
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter
|
||||||
import org.jetbrains.kotlin.resolve.calls.checkers.OperatorCallChecker;
|
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.FROM_COMPLETER
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
|
import org.jetbrains.kotlin.resolve.calls.inference.toHandle
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.TypeVariableKt;
|
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
import org.jetbrains.kotlin.resolve.scopes.ScopeUtils
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||||
import org.jetbrains.kotlin.resolve.scopes.ScopeUtils;
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
|
||||||
import org.jetbrains.kotlin.types.*;
|
import org.jetbrains.kotlin.types.TypeUtils.noExpectedType
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
||||||
import org.jetbrains.kotlin.types.expressions.FakeCallResolver;
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.createFakeExpressionOfType
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
import org.jetbrains.kotlin.types.expressions.FakeCallResolver
|
||||||
import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
|
||||||
import static org.jetbrains.kotlin.psi.KtPsiFactoryKt.KtPsiFactory;
|
|
||||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
|
||||||
import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.FROM_COMPLETER;
|
|
||||||
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.ExpressionTypingUtils.createFakeExpressionOfType;
|
|
||||||
|
|
||||||
//TODO: check for 'operator' modifier!
|
//TODO: check for 'operator' modifier!
|
||||||
public class DelegatedPropertyResolver {
|
class DelegatedPropertyResolver(
|
||||||
private final KotlinBuiltIns builtIns;
|
private val builtIns: KotlinBuiltIns,
|
||||||
private final FakeCallResolver fakeCallResolver;
|
private val fakeCallResolver: FakeCallResolver,
|
||||||
private final ExpressionTypingServices expressionTypingServices;
|
private val expressionTypingServices: ExpressionTypingServices
|
||||||
|
) {
|
||||||
|
|
||||||
public DelegatedPropertyResolver(
|
fun resolvePropertyDelegate(
|
||||||
@NotNull KotlinBuiltIns builtIns,
|
outerDataFlowInfo: DataFlowInfo,
|
||||||
@NotNull FakeCallResolver fakeCallResolver,
|
property: KtProperty,
|
||||||
@NotNull ExpressionTypingServices expressionTypingServices
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
|
delegateExpression: KtExpression,
|
||||||
|
propertyHeaderScope: LexicalScope,
|
||||||
|
trace: BindingTrace
|
||||||
) {
|
) {
|
||||||
this.builtIns = builtIns;
|
property.getter?.let { getter ->
|
||||||
this.fakeCallResolver = fakeCallResolver;
|
if (getter.hasBody()) trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(getter))
|
||||||
this.expressionTypingServices = expressionTypingServices;
|
}
|
||||||
}
|
property.setter?.let { setter ->
|
||||||
|
if (setter.hasBody()) trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(setter))
|
||||||
public void resolvePropertyDelegate(
|
|
||||||
@NotNull DataFlowInfo outerDataFlowInfo,
|
|
||||||
@NotNull KtProperty property,
|
|
||||||
@NotNull VariableDescriptorWithAccessors variableDescriptor,
|
|
||||||
@NotNull KtExpression delegateExpression,
|
|
||||||
@NotNull LexicalScope propertyHeaderScope,
|
|
||||||
@NotNull BindingTrace trace
|
|
||||||
) {
|
|
||||||
KtPropertyAccessor getter = property.getGetter();
|
|
||||||
if (getter != null && getter.hasBody()) {
|
|
||||||
trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(getter));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KtPropertyAccessor setter = property.getSetter();
|
val delegateFunctionsScope: LexicalScope
|
||||||
if (setter != null && setter.hasBody()) {
|
val initializerScope: LexicalScope
|
||||||
trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(setter));
|
|
||||||
}
|
|
||||||
|
|
||||||
LexicalScope delegateFunctionsScope;
|
if (variableDescriptor is PropertyDescriptor) {
|
||||||
LexicalScope initializerScope;
|
delegateFunctionsScope = ScopeUtils.makeScopeForDelegateConventionFunctions(propertyHeaderScope, variableDescriptor)
|
||||||
|
initializerScope = ScopeUtils.makeScopeForPropertyInitializer(propertyHeaderScope, variableDescriptor)
|
||||||
if (variableDescriptor instanceof PropertyDescriptor) {
|
|
||||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variableDescriptor;
|
|
||||||
delegateFunctionsScope = ScopeUtils.makeScopeForDelegateConventionFunctions(propertyHeaderScope, propertyDescriptor);
|
|
||||||
initializerScope = ScopeUtils.makeScopeForPropertyInitializer(propertyHeaderScope, propertyDescriptor);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
delegateFunctionsScope = initializerScope = propertyHeaderScope;
|
initializerScope = propertyHeaderScope
|
||||||
|
delegateFunctionsScope = initializerScope
|
||||||
}
|
}
|
||||||
|
|
||||||
KotlinType delegateType = resolveDelegateExpression(
|
val delegateType = resolveDelegateExpression(delegateExpression, property, variableDescriptor, initializerScope, trace, outerDataFlowInfo)
|
||||||
delegateExpression, property, variableDescriptor, initializerScope, trace, outerDataFlowInfo
|
resolveDelegatedPropertyGetMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, outerDataFlowInfo)
|
||||||
);
|
if (property.isVar) {
|
||||||
|
resolveDelegatedPropertySetMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, outerDataFlowInfo)
|
||||||
resolveDelegatedPropertyGetMethod(
|
|
||||||
variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, outerDataFlowInfo
|
|
||||||
);
|
|
||||||
if (property.isVar()) {
|
|
||||||
resolveDelegatedPropertySetMethod(
|
|
||||||
variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, outerDataFlowInfo
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveDelegatedPropertyPDMethod(
|
resolveDelegatedPropertyPDMethod(variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, outerDataFlowInfo)
|
||||||
variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, outerDataFlowInfo
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
fun getDelegatedPropertyGetMethodReturnType(
|
||||||
public KotlinType getDelegatedPropertyGetMethodReturnType(
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
@NotNull VariableDescriptorWithAccessors variableDescriptor,
|
delegateExpression: KtExpression,
|
||||||
@NotNull KtExpression delegateExpression,
|
delegateType: KotlinType,
|
||||||
@NotNull KotlinType delegateType,
|
trace: BindingTrace,
|
||||||
@NotNull BindingTrace trace,
|
delegateFunctionsScope: LexicalScope,
|
||||||
@NotNull LexicalScope delegateFunctionsScope,
|
dataFlowInfo: DataFlowInfo
|
||||||
@NotNull DataFlowInfo dataFlowInfo
|
): KotlinType? {
|
||||||
) {
|
|
||||||
resolveDelegatedPropertyConventionMethod(
|
resolveDelegatedPropertyConventionMethod(
|
||||||
variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, dataFlowInfo, true
|
variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, dataFlowInfo, true
|
||||||
);
|
)
|
||||||
ResolvedCall<FunctionDescriptor> resolvedCall =
|
val resolvedCall = trace.bindingContext.get(DELEGATED_PROPERTY_RESOLVED_CALL, variableDescriptor.getter)
|
||||||
trace.getBindingContext().get(DELEGATED_PROPERTY_RESOLVED_CALL, variableDescriptor.getGetter());
|
return if (resolvedCall != null) resolvedCall.resultingDescriptor.returnType else null
|
||||||
return resolvedCall != null ? resolvedCall.getResultingDescriptor().getReturnType() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolveDelegatedPropertyGetMethod(
|
private fun resolveDelegatedPropertyGetMethod(
|
||||||
@NotNull VariableDescriptorWithAccessors variableDescriptor,
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
@NotNull KtExpression delegateExpression,
|
delegateExpression: KtExpression,
|
||||||
@NotNull KotlinType delegateType,
|
delegateType: KotlinType,
|
||||||
@NotNull BindingTrace trace,
|
trace: BindingTrace,
|
||||||
@NotNull LexicalScope delegateFunctionsScope,
|
delegateFunctionsScope: LexicalScope,
|
||||||
@NotNull DataFlowInfo dataFlowInfo
|
dataFlowInfo: DataFlowInfo
|
||||||
) {
|
) {
|
||||||
KotlinType returnType = getDelegatedPropertyGetMethodReturnType(
|
val returnType = getDelegatedPropertyGetMethodReturnType(
|
||||||
variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, dataFlowInfo
|
variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, dataFlowInfo
|
||||||
);
|
)
|
||||||
KotlinType propertyType = variableDescriptor.getType();
|
val propertyType = variableDescriptor.type
|
||||||
|
|
||||||
/* Do not check return type of get() method of delegate for properties with DeferredType because property type is taken from it */
|
/* Do not check return type of get() method of delegate for properties with DeferredType because property type is taken from it */
|
||||||
if (!(propertyType instanceof DeferredType) && returnType != null && !KotlinTypeChecker.DEFAULT.isSubtypeOf(returnType, propertyType)) {
|
if (propertyType !is DeferredType && returnType != null && !KotlinTypeChecker.DEFAULT.isSubtypeOf(returnType, propertyType)) {
|
||||||
Call call = trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, variableDescriptor.getGetter());
|
val call = trace.bindingContext.get(DELEGATED_PROPERTY_CALL, variableDescriptor.getter)
|
||||||
assert call != null : "Call should exists for " + variableDescriptor.getGetter();
|
?: throw AssertionError("Call should exists for ${variableDescriptor.getter}")
|
||||||
trace.report(DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH
|
trace.report(DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH.on(
|
||||||
.on(delegateExpression, renderCall(call, trace.getBindingContext()), variableDescriptor.getType(), returnType));
|
delegateExpression, renderCall(call, trace.bindingContext), variableDescriptor.type, returnType))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolveDelegatedPropertySetMethod(
|
private fun resolveDelegatedPropertySetMethod(
|
||||||
@NotNull VariableDescriptorWithAccessors variableDescriptor,
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
@NotNull KtExpression delegateExpression,
|
delegateExpression: KtExpression,
|
||||||
@NotNull KotlinType delegateType,
|
delegateType: KotlinType,
|
||||||
@NotNull BindingTrace trace,
|
trace: BindingTrace,
|
||||||
@NotNull LexicalScope delegateFunctionsScope,
|
delegateFunctionsScope: LexicalScope,
|
||||||
@NotNull DataFlowInfo dataFlowInfo
|
dataFlowInfo: DataFlowInfo
|
||||||
) {
|
) {
|
||||||
resolveDelegatedPropertyConventionMethod(
|
resolveDelegatedPropertyConventionMethod(variableDescriptor, delegateExpression, delegateType, trace,
|
||||||
variableDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, dataFlowInfo, false
|
delegateFunctionsScope, dataFlowInfo, false)
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
private fun createExpressionForProperty(psiFactory: KtPsiFactory): KtExpression {
|
||||||
private static KtExpression createExpressionForProperty(@NotNull KtPsiFactory psiFactory) {
|
return psiFactory.createExpression("null as ${KotlinBuiltIns.FQ_NAMES.kProperty.asSingleFqName().asString()}<*>")
|
||||||
return psiFactory.createExpression("null as " + KotlinBuiltIns.FQ_NAMES.kProperty.asSingleFqName().asString() + "<*>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolveDelegatedPropertyPDMethod(
|
private fun resolveDelegatedPropertyPDMethod(
|
||||||
@NotNull VariableDescriptorWithAccessors variableDescriptor,
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
@NotNull KtExpression delegateExpression,
|
delegateExpression: KtExpression,
|
||||||
@NotNull KotlinType delegateType,
|
delegateType: KotlinType,
|
||||||
@NotNull BindingTrace trace,
|
trace: BindingTrace,
|
||||||
@NotNull LexicalScope delegateFunctionsScope,
|
delegateFunctionsScope: LexicalScope,
|
||||||
@NotNull DataFlowInfo dataFlowInfo
|
dataFlowInfo: DataFlowInfo
|
||||||
) {
|
) {
|
||||||
TemporaryBindingTrace traceToResolvePDMethod = TemporaryBindingTrace.create(trace, "Trace to resolve propertyDelegated method in delegated property");
|
val traceToResolvePDMethod = TemporaryBindingTrace.create(trace, "Trace to resolve propertyDelegated method in delegated property")
|
||||||
ExpressionTypingContext context = ExpressionTypingContext.newContext(
|
val context = ExpressionTypingContext.newContext(traceToResolvePDMethod, delegateFunctionsScope, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE)
|
||||||
traceToResolvePDMethod, delegateFunctionsScope, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE
|
|
||||||
);
|
|
||||||
|
|
||||||
KtPsiFactory psiFactory = KtPsiFactory(delegateExpression);
|
val psiFactory = KtPsiFactory(delegateExpression)
|
||||||
List<KtExpression> arguments = Collections.singletonList(createExpressionForProperty(psiFactory));
|
val arguments = listOf(createExpressionForProperty(psiFactory))
|
||||||
ExpressionReceiver receiver = ExpressionReceiver.Companion.create(delegateExpression, delegateType, trace.getBindingContext());
|
val receiver = ExpressionReceiver.create(delegateExpression, delegateType, trace.bindingContext)
|
||||||
|
|
||||||
Pair<Call, OverloadResolutionResults<FunctionDescriptor>> resolutionResult =
|
val resolutionResult = fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments,
|
||||||
fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, OperatorNameConventions.PROPERTY_DELEGATED, delegateExpression);
|
OperatorNameConventions.PROPERTY_DELEGATED, delegateExpression)
|
||||||
|
|
||||||
Call call = resolutionResult.getFirst();
|
val call = resolutionResult.first
|
||||||
OverloadResolutionResults<FunctionDescriptor> functionResults = resolutionResult.getSecond();
|
val functionResults = resolutionResult.second
|
||||||
|
|
||||||
if (!functionResults.isSuccess()) {
|
if (!functionResults.isSuccess) {
|
||||||
String expectedFunction = renderCall(call, traceToResolvePDMethod.getBindingContext());
|
val expectedFunction = renderCall(call, traceToResolvePDMethod.bindingContext)
|
||||||
if (functionResults.isIncomplete() || functionResults.isSingleResult() ||
|
if (functionResults.isIncomplete || functionResults.isSingleResult ||
|
||||||
functionResults.getResultCode() == OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES) {
|
functionResults.resultCode == OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES) {
|
||||||
trace.report(DELEGATE_PD_METHOD_NONE_APPLICABLE.on(delegateExpression, expectedFunction, functionResults.getResultingCalls()));
|
trace.report(DELEGATE_PD_METHOD_NONE_APPLICABLE.on(delegateExpression, expectedFunction, functionResults.resultingCalls))
|
||||||
} else if (functionResults.isAmbiguity()) {
|
|
||||||
trace.report(DELEGATE_SPECIAL_FUNCTION_AMBIGUITY
|
|
||||||
.on(delegateExpression, expectedFunction, functionResults.getResultingCalls()));
|
|
||||||
}
|
}
|
||||||
return;
|
else if (functionResults.isAmbiguity) {
|
||||||
|
trace.report(DELEGATE_SPECIAL_FUNCTION_AMBIGUITY.on(delegateExpression, expectedFunction, functionResults.resultingCalls))
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
trace.record(DELEGATED_PROPERTY_PD_RESOLVED_CALL, variableDescriptor, functionResults.getResultingCall());
|
trace.record(DELEGATED_PROPERTY_PD_RESOLVED_CALL, variableDescriptor, functionResults.resultingCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resolve getValue() or setValue() methods from delegate */
|
/* Resolve getValue() or setValue() methods from delegate */
|
||||||
private void resolveDelegatedPropertyConventionMethod(
|
private fun resolveDelegatedPropertyConventionMethod(
|
||||||
@NotNull VariableDescriptorWithAccessors propertyDescriptor,
|
propertyDescriptor: VariableDescriptorWithAccessors,
|
||||||
@NotNull KtExpression delegateExpression,
|
delegateExpression: KtExpression,
|
||||||
@NotNull KotlinType delegateType,
|
delegateType: KotlinType,
|
||||||
@NotNull BindingTrace trace,
|
trace: BindingTrace,
|
||||||
@NotNull LexicalScope delegateFunctionsScope,
|
delegateFunctionsScope: LexicalScope,
|
||||||
@NotNull DataFlowInfo dataFlowInfo,
|
dataFlowInfo: DataFlowInfo,
|
||||||
boolean isGet
|
isGet: Boolean
|
||||||
) {
|
) {
|
||||||
VariableAccessorDescriptor accessor = isGet ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
|
val accessor = (if (isGet) propertyDescriptor.getter else propertyDescriptor.setter)
|
||||||
assert accessor != null : "Delegated property should have getter/setter " + propertyDescriptor + " " + delegateExpression.getText();
|
?: throw AssertionError("Delegated property should have getter/setter $propertyDescriptor ${delegateExpression.text}")
|
||||||
|
|
||||||
if (trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, accessor) != null) return;
|
if (trace.bindingContext.get(DELEGATED_PROPERTY_CALL, accessor) != null) return
|
||||||
|
|
||||||
OverloadResolutionResults<FunctionDescriptor> functionResults = getDelegatedPropertyConventionMethod(
|
val functionResults = getDelegatedPropertyConventionMethod(propertyDescriptor, delegateExpression, delegateType, trace,
|
||||||
propertyDescriptor, delegateExpression, delegateType, trace, delegateFunctionsScope, dataFlowInfo, isGet, true
|
delegateFunctionsScope, dataFlowInfo, isGet, true)
|
||||||
);
|
val call = trace.bindingContext.get(DELEGATED_PROPERTY_CALL, accessor)
|
||||||
Call call = trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, accessor);
|
?: throw AssertionError("'getDelegatedPropertyConventionMethod' didn't record a call")
|
||||||
assert call != null : "'getDelegatedPropertyConventionMethod' didn't record a call";
|
|
||||||
|
|
||||||
if (!functionResults.isSuccess()) {
|
if (!functionResults.isSuccess) {
|
||||||
String expectedFunction = renderCall(call, trace.getBindingContext());
|
val expectedFunction = renderCall(call, trace.bindingContext)
|
||||||
if (functionResults.isSingleResult() || functionResults.isIncomplete() ||
|
when {
|
||||||
functionResults.getResultCode() == OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES) {
|
functionResults.isSingleResult ||
|
||||||
trace.report(DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE
|
functionResults.isIncomplete ||
|
||||||
.on(delegateExpression, expectedFunction, functionResults.getResultingCalls()));
|
functionResults.resultCode == OverloadResolutionResults.Code.MANY_FAILED_CANDIDATES ->
|
||||||
|
trace.report(DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE.on(delegateExpression, expectedFunction, functionResults.resultingCalls))
|
||||||
|
functionResults.isAmbiguity ->
|
||||||
|
trace.report(DELEGATE_SPECIAL_FUNCTION_AMBIGUITY.on(delegateExpression, expectedFunction, functionResults.resultingCalls))
|
||||||
|
else ->
|
||||||
|
trace.report(DELEGATE_SPECIAL_FUNCTION_MISSING.on(delegateExpression, expectedFunction, delegateType))
|
||||||
}
|
}
|
||||||
else if (functionResults.isAmbiguity()) {
|
return
|
||||||
trace.report(DELEGATE_SPECIAL_FUNCTION_AMBIGUITY
|
|
||||||
.on(delegateExpression, expectedFunction, functionResults.getResultingCalls()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
trace.report(DELEGATE_SPECIAL_FUNCTION_MISSING.on(delegateExpression, expectedFunction, delegateType));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionDescriptor resultingDescriptor = functionResults.getResultingDescriptor();
|
val resultingDescriptor = functionResults.resultingDescriptor
|
||||||
|
|
||||||
ResolvedCall<FunctionDescriptor> resultingCall = functionResults.getResultingCall();
|
val resultingCall = functionResults.resultingCall
|
||||||
PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor);
|
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor)
|
||||||
if (declaration instanceof KtProperty) {
|
if (declaration is KtProperty) {
|
||||||
KtProperty property = (KtProperty) declaration;
|
val delegate = declaration.delegate
|
||||||
KtPropertyDelegate delegate = property.getDelegate();
|
|
||||||
if (delegate != null) {
|
if (delegate != null) {
|
||||||
PsiElement byKeyword = delegate.getByKeywordNode().getPsi();
|
if (!resultingDescriptor.isOperator) {
|
||||||
|
val byKeyword = delegate.byKeywordNode.psi
|
||||||
if (!resultingDescriptor.isOperator()) {
|
OperatorCallChecker.report(byKeyword, resultingDescriptor, trace)
|
||||||
OperatorCallChecker.Companion.report(byKeyword, resultingDescriptor, trace);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trace.record(DELEGATED_PROPERTY_RESOLVED_CALL, accessor, resultingCall);
|
|
||||||
|
trace.record(DELEGATED_PROPERTY_RESOLVED_CALL, accessor, resultingCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resolve getValue() or setValue() methods from delegate */
|
/* Resolve getValue() or setValue() methods from delegate */
|
||||||
private OverloadResolutionResults<FunctionDescriptor> getDelegatedPropertyConventionMethod(
|
private fun getDelegatedPropertyConventionMethod(
|
||||||
@NotNull VariableDescriptorWithAccessors propertyDescriptor,
|
propertyDescriptor: VariableDescriptorWithAccessors,
|
||||||
@NotNull KtExpression delegateExpression,
|
delegateExpression: KtExpression,
|
||||||
@NotNull KotlinType delegateType,
|
delegateType: KotlinType,
|
||||||
@NotNull BindingTrace trace,
|
trace: BindingTrace,
|
||||||
@NotNull LexicalScope delegateFunctionsScope,
|
delegateFunctionsScope: LexicalScope,
|
||||||
@NotNull DataFlowInfo dataFlowInfo,
|
dataFlowInfo: DataFlowInfo,
|
||||||
boolean isGet,
|
isGet: Boolean,
|
||||||
boolean isComplete
|
isComplete: Boolean
|
||||||
) {
|
): OverloadResolutionResults<FunctionDescriptor> {
|
||||||
VariableAccessorDescriptor accessor = isGet ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
|
val accessor = (if (isGet) propertyDescriptor.getter else propertyDescriptor.setter)
|
||||||
assert accessor != null : "Delegated property should have getter/setter " + propertyDescriptor + " " + delegateExpression.getText();
|
?: throw AssertionError("Delegated property should have getter/setter $propertyDescriptor ${delegateExpression.text}")
|
||||||
|
|
||||||
KotlinType expectedType = isComplete && isGet && !(propertyDescriptor.getType() instanceof DeferredType)
|
val expectedType = if (isComplete && isGet && propertyDescriptor.type !is DeferredType)
|
||||||
? propertyDescriptor.getType() : TypeUtils.NO_EXPECTED_TYPE;
|
propertyDescriptor.type
|
||||||
|
else
|
||||||
|
TypeUtils.NO_EXPECTED_TYPE
|
||||||
|
|
||||||
ExpressionTypingContext context = ExpressionTypingContext.newContext(trace, delegateFunctionsScope, dataFlowInfo, expectedType);
|
val context = ExpressionTypingContext.newContext(trace, delegateFunctionsScope, dataFlowInfo, expectedType)
|
||||||
|
|
||||||
boolean hasThis = propertyDescriptor.getExtensionReceiverParameter() != null || propertyDescriptor.getDispatchReceiverParameter() != null;
|
val hasThis = propertyDescriptor.extensionReceiverParameter != null || propertyDescriptor.dispatchReceiverParameter != null
|
||||||
|
|
||||||
List<KtExpression> arguments = Lists.newArrayList();
|
val arguments = Lists.newArrayList<KtExpression>()
|
||||||
KtPsiFactory psiFactory = KtPsiFactory(delegateExpression);
|
val psiFactory = KtPsiFactory(delegateExpression)
|
||||||
arguments.add(psiFactory.createExpression(hasThis ? "this" : "null"));
|
arguments.add(psiFactory.createExpression(if (hasThis) "this" else "null"))
|
||||||
arguments.add(createExpressionForProperty(psiFactory));
|
arguments.add(createExpressionForProperty(psiFactory))
|
||||||
|
|
||||||
if (!isGet) {
|
if (!isGet) {
|
||||||
KtReferenceExpression fakeArgument = (KtReferenceExpression) createFakeExpressionOfType(delegateExpression.getProject(), trace,
|
val fakeArgument = createFakeExpressionOfType(delegateExpression.project, trace,
|
||||||
"fakeArgument" + arguments.size(),
|
"fakeArgument${arguments.size}",
|
||||||
propertyDescriptor.getType());
|
propertyDescriptor.type) as KtReferenceExpression
|
||||||
arguments.add(fakeArgument);
|
arguments.add(fakeArgument)
|
||||||
List<ValueParameterDescriptor> valueParameters = accessor.getValueParameters();
|
val valueParameters = accessor.valueParameters
|
||||||
trace.record(REFERENCE_TARGET, fakeArgument, valueParameters.get(0));
|
trace.record(REFERENCE_TARGET, fakeArgument, valueParameters[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
Name functionName = isGet ? OperatorNameConventions.GET_VALUE : OperatorNameConventions.SET_VALUE;
|
val functionName = if (isGet) OperatorNameConventions.GET_VALUE else OperatorNameConventions.SET_VALUE
|
||||||
ExpressionReceiver receiver = ExpressionReceiver.Companion.create(delegateExpression, delegateType, trace.getBindingContext());
|
val receiver = ExpressionReceiver.create(delegateExpression, delegateType, trace.bindingContext)
|
||||||
|
|
||||||
Pair<Call, OverloadResolutionResults<FunctionDescriptor>> resolutionResult =
|
val resolutionResult = fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, functionName, delegateExpression)
|
||||||
fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, functionName, delegateExpression);
|
|
||||||
|
|
||||||
trace.record(BindingContext.DELEGATED_PROPERTY_CALL, accessor, resolutionResult.getFirst());
|
trace.record(BindingContext.DELEGATED_PROPERTY_CALL, accessor, resolutionResult.first)
|
||||||
return resolutionResult.getSecond();
|
return resolutionResult.second
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: diagnostics rendering does not belong here
|
//TODO: diagnostics rendering does not belong here
|
||||||
private static String renderCall(@NotNull Call call, @NotNull BindingContext context) {
|
private fun renderCall(call: Call, context: BindingContext): String {
|
||||||
KtExpression calleeExpression = call.getCalleeExpression();
|
val calleeExpression = call.calleeExpression
|
||||||
assert calleeExpression != null : "CalleeExpression should exists for fake call of convention method";
|
?: throw AssertionError("CalleeExpression should exists for fake call of convention method")
|
||||||
StringBuilder builder = new StringBuilder(calleeExpression.getText());
|
|
||||||
builder.append("(");
|
|
||||||
List<KotlinType> argumentTypes = Lists.newArrayList();
|
|
||||||
for (ValueArgument argument : call.getValueArguments()) {
|
|
||||||
argumentTypes.add(context.getType(argument.getArgumentExpression()));
|
|
||||||
|
|
||||||
}
|
return call.valueArguments.joinToString(
|
||||||
String arguments = StringUtil.join(argumentTypes, new Function<KotlinType, String>() {
|
prefix = "${calleeExpression.text}(",
|
||||||
@Override
|
postfix = ")",
|
||||||
public String fun(KotlinType type) {
|
separator = ", ",
|
||||||
return DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(type);
|
transform = { argument ->
|
||||||
}
|
val type = context.getType(argument.getArgumentExpression()!!)!!
|
||||||
}, ", ");
|
DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(type)
|
||||||
builder.append(arguments);
|
}
|
||||||
builder.append(")");
|
)
|
||||||
return builder.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
fun resolveDelegateExpression(
|
||||||
public KotlinType resolveDelegateExpression(
|
delegateExpression: KtExpression,
|
||||||
@NotNull KtExpression delegateExpression,
|
property: KtProperty,
|
||||||
@NotNull KtProperty property,
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
@NotNull VariableDescriptorWithAccessors variableDescriptor,
|
scopeForDelegate: LexicalScope,
|
||||||
@NotNull LexicalScope scopeForDelegate,
|
trace: BindingTrace,
|
||||||
@NotNull BindingTrace trace,
|
dataFlowInfo: DataFlowInfo
|
||||||
@NotNull DataFlowInfo dataFlowInfo
|
): KotlinType {
|
||||||
) {
|
val traceToResolveDelegatedProperty = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property")
|
||||||
TemporaryBindingTrace traceToResolveDelegatedProperty = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property");
|
val calleeExpression = delegateExpression.getCalleeExpressionIfAny()
|
||||||
KtExpression calleeExpression = CallUtilKt.getCalleeExpressionIfAny(delegateExpression);
|
val completer = createConstraintSystemCompleter(
|
||||||
ConstraintSystemCompleter completer = createConstraintSystemCompleter(
|
|
||||||
property, variableDescriptor, delegateExpression, scopeForDelegate, trace, dataFlowInfo
|
property, variableDescriptor, delegateExpression, scopeForDelegate, trace, dataFlowInfo
|
||||||
);
|
)
|
||||||
if (calleeExpression != null) {
|
if (calleeExpression != null) {
|
||||||
traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, calleeExpression, completer);
|
traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, calleeExpression, completer)
|
||||||
}
|
}
|
||||||
KotlinType delegateType = expressionTypingServices.safeGetType(scopeForDelegate, delegateExpression, NO_EXPECTED_TYPE,
|
val delegateType = expressionTypingServices.safeGetType(scopeForDelegate, delegateExpression, NO_EXPECTED_TYPE,
|
||||||
dataFlowInfo, traceToResolveDelegatedProperty);
|
dataFlowInfo, traceToResolveDelegatedProperty)
|
||||||
traceToResolveDelegatedProperty.commit(new TraceEntryFilter() {
|
traceToResolveDelegatedProperty.commit({ slice, key -> slice !== CONSTRAINT_SYSTEM_COMPLETER }, true)
|
||||||
@Override
|
return delegateType
|
||||||
public boolean accept(@Nullable WritableSlice<?, ?> slice, Object key) {
|
|
||||||
return slice != CONSTRAINT_SYSTEM_COMPLETER;
|
|
||||||
}
|
|
||||||
}, true);
|
|
||||||
return delegateType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
private fun createConstraintSystemCompleter(
|
||||||
private ConstraintSystemCompleter createConstraintSystemCompleter(
|
property: KtProperty,
|
||||||
@NotNull KtProperty property,
|
variableDescriptor: VariableDescriptorWithAccessors,
|
||||||
@NotNull final VariableDescriptorWithAccessors variableDescriptor,
|
delegateExpression: KtExpression,
|
||||||
@NotNull final KtExpression delegateExpression,
|
scopeForDelegate: LexicalScope,
|
||||||
@NotNull LexicalScope scopeForDelegate,
|
trace: BindingTrace,
|
||||||
@NotNull final BindingTrace trace,
|
dataFlowInfo: DataFlowInfo
|
||||||
@NotNull final DataFlowInfo dataFlowInfo
|
): ConstraintSystemCompleter {
|
||||||
) {
|
val delegateFunctionsScope = ScopeUtils.makeScopeForDelegateConventionFunctions(scopeForDelegate, variableDescriptor)
|
||||||
final LexicalScope delegateFunctionsScope = ScopeUtils.makeScopeForDelegateConventionFunctions(scopeForDelegate, variableDescriptor);
|
val expectedType = if (property.typeReference != null) variableDescriptor.type else NO_EXPECTED_TYPE
|
||||||
final KotlinType expectedType = property.getTypeReference() != null ? variableDescriptor.getType() : NO_EXPECTED_TYPE;
|
|
||||||
return new ConstraintSystemCompleter() {
|
|
||||||
@Override
|
|
||||||
public void completeConstraintSystem(
|
|
||||||
@NotNull ConstraintSystem.Builder constraintSystem, @NotNull ResolvedCall<?> resolvedCall
|
|
||||||
) {
|
|
||||||
KotlinType returnType = resolvedCall.getCandidateDescriptor().getReturnType();
|
|
||||||
if (returnType == null) return;
|
|
||||||
|
|
||||||
TypeSubstitutor typeVariableSubstitutor =
|
return object : ConstraintSystemCompleter {
|
||||||
constraintSystem.getTypeVariableSubstitutors().get(TypeVariableKt.toHandle(resolvedCall.getCall()));
|
override fun completeConstraintSystem(constraintSystem: ConstraintSystem.Builder, resolvedCall: ResolvedCall<*>) {
|
||||||
assert typeVariableSubstitutor != null : "No substitutor in the system for call: " + resolvedCall.getCall();
|
val returnType = resolvedCall.candidateDescriptor.returnType ?: return
|
||||||
|
|
||||||
TemporaryBindingTrace traceToResolveConventionMethods =
|
val typeVariableSubstitutor = constraintSystem.typeVariableSubstitutors[resolvedCall.call.toHandle()]
|
||||||
TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods");
|
?: throw AssertionError("No substitutor in the system for call: " + resolvedCall.call)
|
||||||
OverloadResolutionResults<FunctionDescriptor>
|
|
||||||
getMethodResults = getDelegatedPropertyConventionMethod(
|
val traceToResolveConventionMethods = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods")
|
||||||
variableDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope,
|
val getMethodResults = getDelegatedPropertyConventionMethod(
|
||||||
dataFlowInfo, true, false
|
variableDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope,
|
||||||
);
|
dataFlowInfo, true, false
|
||||||
|
)
|
||||||
|
|
||||||
if (conventionMethodFound(getMethodResults)) {
|
if (conventionMethodFound(getMethodResults)) {
|
||||||
FunctionDescriptor descriptor = getMethodResults.getResultingDescriptor();
|
val descriptor = getMethodResults.resultingDescriptor
|
||||||
KotlinType returnTypeOfGetMethod = descriptor.getReturnType();
|
val returnTypeOfGetMethod = descriptor.returnType
|
||||||
if (returnTypeOfGetMethod != null && !TypeUtils.noExpectedType(expectedType)) {
|
if (returnTypeOfGetMethod != null && !TypeUtils.noExpectedType(expectedType)) {
|
||||||
KotlinType returnTypeInSystem = typeVariableSubstitutor.substitute(returnTypeOfGetMethod, Variance.INVARIANT);
|
val returnTypeInSystem = typeVariableSubstitutor.substitute(returnTypeOfGetMethod, Variance.INVARIANT)
|
||||||
if (returnTypeInSystem != null) {
|
if (returnTypeInSystem != null) {
|
||||||
constraintSystem.addSubtypeConstraint(returnTypeInSystem, expectedType, FROM_COMPLETER.position());
|
constraintSystem.addSubtypeConstraint(returnTypeInSystem, expectedType, FROM_COMPLETER.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor);
|
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor)
|
||||||
}
|
}
|
||||||
if (!variableDescriptor.isVar()) return;
|
if (!variableDescriptor.isVar) return
|
||||||
|
|
||||||
// For the case: 'val v by d' (no declared type).
|
// For the case: 'val v by d' (no declared type).
|
||||||
// When we add a constraint for 'set' method for delegated expression 'd' we use a type of the declared variable 'v'.
|
// When we add a constraint for 'set' method for delegated expression 'd' we use a type of the declared variable 'v'.
|
||||||
// But if the type isn't known yet, the constraint shouldn't be added (we try to infer the type of 'v' here as well).
|
// But if the type isn't known yet, the constraint shouldn't be added (we try to infer the type of 'v' here as well).
|
||||||
if (variableDescriptor.getReturnType() instanceof DeferredType) return;
|
if (variableDescriptor.returnType is DeferredType) return
|
||||||
|
|
||||||
OverloadResolutionResults<FunctionDescriptor>
|
val setMethodResults = getDelegatedPropertyConventionMethod(
|
||||||
setMethodResults = getDelegatedPropertyConventionMethod(
|
variableDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope,
|
||||||
variableDescriptor, delegateExpression, returnType, traceToResolveConventionMethods, delegateFunctionsScope,
|
dataFlowInfo, false, false
|
||||||
dataFlowInfo, false, false
|
)
|
||||||
);
|
|
||||||
|
|
||||||
if (conventionMethodFound(setMethodResults)) {
|
if (conventionMethodFound(setMethodResults)) {
|
||||||
FunctionDescriptor descriptor = setMethodResults.getResultingDescriptor();
|
val descriptor = setMethodResults.resultingDescriptor
|
||||||
List<ValueParameterDescriptor> valueParameters = descriptor.getValueParameters();
|
val valueParameters = descriptor.valueParameters
|
||||||
if (valueParameters.size() == 3) {
|
if (valueParameters.size == 3) {
|
||||||
ValueParameterDescriptor valueParameterForThis = valueParameters.get(2);
|
val valueParameterForThis = valueParameters[2]
|
||||||
|
|
||||||
if (!noExpectedType(expectedType)) {
|
if (!noExpectedType(expectedType)) {
|
||||||
constraintSystem.addSubtypeConstraint(
|
constraintSystem.addSubtypeConstraint(
|
||||||
expectedType,
|
expectedType,
|
||||||
typeVariableSubstitutor.substitute(valueParameterForThis.getType(), Variance.INVARIANT),
|
typeVariableSubstitutor.substitute(valueParameterForThis.type, Variance.INVARIANT),
|
||||||
FROM_COMPLETER.position()
|
FROM_COMPLETER.position()
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor);
|
addConstraintForThisValue(constraintSystem, typeVariableSubstitutor, descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean conventionMethodFound(@NotNull OverloadResolutionResults<FunctionDescriptor> results) {
|
private fun conventionMethodFound(results: OverloadResolutionResults<FunctionDescriptor>): Boolean =
|
||||||
return results.isSuccess() ||
|
results.isSuccess ||
|
||||||
(results.isSingleResult() &&
|
results.isSingleResult && results.resultCode == OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH
|
||||||
results.getResultCode() == OverloadResolutionResults.Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addConstraintForThisValue(
|
private fun addConstraintForThisValue(
|
||||||
ConstraintSystem.Builder constraintSystem,
|
constraintSystem: ConstraintSystem.Builder,
|
||||||
TypeSubstitutor typeVariableSubstitutor,
|
typeVariableSubstitutor: TypeSubstitutor,
|
||||||
FunctionDescriptor resultingDescriptor
|
resultingDescriptor: FunctionDescriptor
|
||||||
) {
|
) {
|
||||||
ReceiverParameterDescriptor extensionReceiver = variableDescriptor.getExtensionReceiverParameter();
|
val extensionReceiver = variableDescriptor.extensionReceiverParameter
|
||||||
ReceiverParameterDescriptor dispatchReceiver = variableDescriptor.getDispatchReceiverParameter();
|
val dispatchReceiver = variableDescriptor.dispatchReceiverParameter
|
||||||
KotlinType typeOfThis =
|
val typeOfThis = extensionReceiver?.type ?: dispatchReceiver?.type ?: builtIns.nullableNothingType
|
||||||
extensionReceiver != null ? extensionReceiver.getType() :
|
|
||||||
dispatchReceiver != null ? dispatchReceiver.getType() :
|
|
||||||
builtIns.getNullableNothingType();
|
|
||||||
|
|
||||||
List<ValueParameterDescriptor> valueParameters = resultingDescriptor.getValueParameters();
|
val valueParameters = resultingDescriptor.valueParameters
|
||||||
if (valueParameters.isEmpty()) return;
|
if (valueParameters.isEmpty()) return
|
||||||
ValueParameterDescriptor valueParameterForThis = valueParameters.get(0);
|
val valueParameterForThis = valueParameters[0]
|
||||||
|
|
||||||
constraintSystem.addSubtypeConstraint(
|
constraintSystem.addSubtypeConstraint(
|
||||||
typeOfThis,
|
typeOfThis,
|
||||||
typeVariableSubstitutor.substitute(valueParameterForThis.getType(), Variance.INVARIANT),
|
typeVariableSubstitutor.substitute(valueParameterForThis.type, Variance.INVARIANT),
|
||||||
FROM_COMPLETER.position()
|
FROM_COMPLETER.position()
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user