K1: Support referencing class context receivers in a form of this@Name
This commit is contained in:
@@ -123,6 +123,7 @@ public interface BindingContext {
|
||||
WritableSlice<KtSuperExpression, Boolean> SUPER_EXPRESSION_FROM_ANY_MIGRATION = Slices.createSimpleSlice();
|
||||
|
||||
WritableSlice<KtReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET = new BasicWritableSlice<>(DO_NOTHING);
|
||||
WritableSlice<KtReferenceExpression, ReceiverParameterDescriptor> THIS_REFERENCE_TARGET = new BasicWritableSlice<>(DO_NOTHING);
|
||||
// if 'A' really means 'A.Companion' then this slice stores class descriptor for A, REFERENCE_TARGET stores descriptor Companion in this case
|
||||
WritableSlice<KtReferenceExpression, ClassifierDescriptorWithTypeParameters> SHORT_REFERENCE_TO_COMPANION_OBJECT =
|
||||
new BasicWritableSlice<>(DO_NOTHING);
|
||||
|
||||
+16
-2
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.lazy.descriptors;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
import kotlin.Pair;
|
||||
@@ -305,7 +306,8 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
||||
if (classOrObject == null) {
|
||||
return CollectionsKt.emptyList();
|
||||
}
|
||||
return classOrObject.getContextReceivers().stream()
|
||||
List<KtContextReceiver> contextReceivers = classOrObject.getContextReceivers();
|
||||
List<ReceiverParameterDescriptor> contextReceiverDescriptors = contextReceivers.stream()
|
||||
.map(KtContextReceiver::typeReference)
|
||||
.filter(Objects::nonNull)
|
||||
.map(typeReference -> {
|
||||
@@ -316,7 +318,19 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
||||
kotlinType,
|
||||
Annotations.Companion.getEMPTY()
|
||||
);
|
||||
}).collect(Collectors.toList());
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
if (c.getLanguageVersionSettings().supportsFeature(LanguageFeature.ContextReceivers)) {
|
||||
HashMultimap<String, ReceiverParameterDescriptor> labelNameToReceiverMap = HashMultimap.create();
|
||||
|
||||
for (int i = 0; i < contextReceivers.size(); i++) {
|
||||
labelNameToReceiverMap.put(contextReceivers.get(i).name(), contextReceiverDescriptors.get(i));
|
||||
}
|
||||
|
||||
c.getTrace().record(BindingContext.DESCRIPTOR_TO_CONTEXT_RECEIVER_MAP, this, labelNameToReceiverMap);
|
||||
}
|
||||
|
||||
return contextReceiverDescriptors;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -404,7 +404,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
context.trace.report(NO_THIS.on(expression));
|
||||
break;
|
||||
case SUCCESS:
|
||||
result = resolutionResult.getReceiverParameterDescriptor().getType();
|
||||
ReceiverParameterDescriptor descriptor = resolutionResult.getReceiverParameterDescriptor();
|
||||
context.trace.record(THIS_REFERENCE_TARGET, expression.getInstanceReference(), descriptor);
|
||||
result = descriptor.getType();
|
||||
context.trace.recordType(expression.getInstanceReference(), result);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -25,8 +25,11 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.checkReservedYield
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.DescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.getDeclarationsByLabel
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
@@ -64,6 +67,12 @@ object LabelResolver {
|
||||
is KtFunctionLiteral -> return getLabelNamesIfAny(element.parent, false)
|
||||
is KtLambdaExpression -> result.addIfNotNull(getLabelForFunctionalExpression(element))
|
||||
}
|
||||
|
||||
if (element is KtClass) {
|
||||
element.contextReceivers
|
||||
.mapNotNullTo(result) { it.name()?.let { s -> Name.identifier(s) } }
|
||||
}
|
||||
|
||||
val functionOrProperty = when (element) {
|
||||
is KtNamedFunction -> {
|
||||
result.addIfNotNull(element.nameAsName ?: getLabelForFunctionalExpression(element))
|
||||
@@ -210,14 +219,15 @@ object LabelResolver {
|
||||
trace.record(LABEL_TARGET, targetLabelExpression, it)
|
||||
}
|
||||
val declarationDescriptor = trace.bindingContext[DECLARATION_TO_DESCRIPTOR, element]
|
||||
if (declarationDescriptor is FunctionDescriptor) {
|
||||
if (declarationDescriptor is FunctionDescriptor || declarationDescriptor is ClassDescriptor) {
|
||||
val labelNameToReceiverMap = trace.bindingContext[
|
||||
DESCRIPTOR_TO_CONTEXT_RECEIVER_MAP,
|
||||
if (declarationDescriptor is PropertyAccessorDescriptor) declarationDescriptor.correspondingProperty else declarationDescriptor
|
||||
]
|
||||
val thisReceivers = labelNameToReceiverMap?.get(labelName.identifier)
|
||||
val thisReceiver = when {
|
||||
thisReceivers.isNullOrEmpty() -> declarationDescriptor.extensionReceiverParameter
|
||||
thisReceivers.isNullOrEmpty() ->
|
||||
(declarationDescriptor as? FunctionDescriptor)?.extensionReceiverParameter
|
||||
thisReceivers.size == 1 -> thisReceivers.single()
|
||||
else -> {
|
||||
BindingContextUtils.reportAmbiguousLabel(trace, targetLabelExpression, declarationsByLabel)
|
||||
@@ -294,4 +304,4 @@ object LabelResolver {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user