diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiSourceCompilerForInline.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiSourceCompilerForInline.kt index 36535636c9f..958610cd83e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiSourceCompilerForInline.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/PsiSourceCompilerForInline.kt @@ -437,9 +437,9 @@ fun getDeclarationLabels(lambdaOrFun: PsiElement?, descriptor: DeclarationDescri val result = HashSet() if (lambdaOrFun != null) { - val label = LabelResolver.getLabelNameIfAny(lambdaOrFun) - if (label != null) { - result.add(label.asString()) + val label = LabelResolver.getLabelNamesIfAny(lambdaOrFun, addContextReceiverNames = false) + if (label.isNotEmpty()) { + result.add(label.single().asString()) } } diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index e3e4268da0d..8117b030370 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -10624,6 +10624,42 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/plusMatrix.kt"); } + @Test + @TestMetadata("superWithContext.kt") + public void testSuperWithContext() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/superWithContext.kt"); + } + + @Test + @TestMetadata("thisIdentifierInfo.kt") + public void testThisIdentifierInfo() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/thisIdentifierInfo.kt"); + } + + @Test + @TestMetadata("thisWithCustomLabel.kt") + public void testThisWithCustomLabel() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.kt"); + } + + @Test + @TestMetadata("thisWithReceiverLabelsClasses.kt") + public void testThisWithReceiverLabelsClasses() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsClasses.kt"); + } + + @Test + @TestMetadata("thisWithReceiverLabelsFunctions.kt") + public void testThisWithReceiverLabelsFunctions() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.kt"); + } + + @Test + @TestMetadata("thisWithReceiverLabelsProperties.kt") + public void testThisWithReceiverLabelsProperties() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.kt"); + } + @Test @TestMetadata("typeParameterized.kt") public void testTypeParameterized() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 937b2fce9d1..e153bfcba8c 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -16168,6 +16168,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT public void testSimpleCall() throws Exception { runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/simpleCall.kt"); } + + @Test + @TestMetadata("this.kt") + public void testThis() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/this.kt"); + } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/synthetics/SyntheticClassOrObjectDescriptor.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/synthetics/SyntheticClassOrObjectDescriptor.kt index 41fe7e6366c..9225f59e26b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/synthetics/SyntheticClassOrObjectDescriptor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/synthetics/SyntheticClassOrObjectDescriptor.kt @@ -167,7 +167,7 @@ class SyntheticClassOrObjectDescriptor( override fun getPrimaryConstructorModifierList(): KtModifierList? = null override fun getPrimaryConstructorParameters(): List = emptyList() override fun getSecondaryConstructors(): List = emptyList() - override fun getContextReceiverTypeReferences(): List = emptyList() + override fun getContextReceivers(): List = emptyList() override fun getPsiOrParent() = _parent.psiOrParent override fun getParent() = _parent.psiOrParent diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index a3251f5159c..ac4065a71ba 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -48,6 +48,8 @@ import org.jetbrains.kotlin.util.slicedMap.*; import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; import static org.jetbrains.kotlin.util.slicedMap.RewritePolicy.DO_NOTHING; import static org.jetbrains.kotlin.util.slicedMap.Slices.COMPILE_TIME_VALUE_REWRITE_POLICY; @@ -262,6 +264,7 @@ public interface BindingContext { .setFurtherLookupSlices(DECLARATIONS_TO_DESCRIPTORS) .build(); + WritableSlice> DESCRIPTOR_TO_NAMED_RECEIVERS = Slices.createSimpleSlice(); WritableSlice LABEL_TARGET = Slices.createSimpleSlice(); WritableSlice> AMBIGUOUS_LABEL_TARGET = Slices.createSimpleSlice(); WritableSlice VALUE_PARAMETER_AS_PROPERTY = Slices.createSimpleSlice(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java index b80da074e26..eddd2c9e6c8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java @@ -1023,7 +1023,8 @@ public class BodyResolver { ); // Synthetic "field" creation - if (functionDescriptor instanceof PropertyAccessorDescriptor && functionDescriptor.getExtensionReceiverParameter() == null) { + if (functionDescriptor instanceof PropertyAccessorDescriptor && functionDescriptor.getExtensionReceiverParameter() == null + && functionDescriptor.getContextReceiverParameters().isEmpty()) { PropertyAccessorDescriptor accessorDescriptor = (PropertyAccessorDescriptor) functionDescriptor; KtProperty property = (KtProperty) function.getParent(); SourceElement propertySourceElement = KotlinSourceElementKt.toSourceElement(property); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index ece57c12c68..d71abb81618 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -64,13 +64,11 @@ import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt; import java.util.*; import java.util.stream.Collectors; -import java.util.stream.Stream; import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*; import static org.jetbrains.kotlin.diagnostics.Errors.*; import static org.jetbrains.kotlin.lexer.KtTokens.*; -import static org.jetbrains.kotlin.resolve.BindingContext.CONSTRUCTOR; -import static org.jetbrains.kotlin.resolve.BindingContext.TYPE_ALIAS; +import static org.jetbrains.kotlin.resolve.BindingContext.*; import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; import static org.jetbrains.kotlin.resolve.ModifiersChecker.resolveMemberModalityFromModifiers; import static org.jetbrains.kotlin.resolve.ModifiersChecker.resolveVisibilityFromModifiers; @@ -929,7 +927,6 @@ public class DescriptorResolver { LexicalScope scopeForDeclarationResolutionWithTypeParameters; LexicalScope scopeForInitializerResolutionWithTypeParameters; KotlinType receiverType = null; - Stream contextReceiverTypes; { List typeParameters = variableDeclaration.getTypeParameters(); @@ -958,37 +955,25 @@ public class DescriptorResolver { scopeForDeclarationResolutionWithTypeParameters = writableScopeForDeclarationResolution; scopeForInitializerResolutionWithTypeParameters = writableScopeForInitializerResolution; } - - KtTypeReference receiverTypeRef = variableDeclaration.getReceiverTypeReference(); - if (receiverTypeRef != null) { - receiverType = typeResolver.resolveType(scopeForDeclarationResolutionWithTypeParameters, receiverTypeRef, trace, true); - } - - List contextReceiverTypeRefs = variableDeclaration.getContextReceiverTypeReferences(); - for (KtTypeReference contextReceiverTypeRef: contextReceiverTypeRefs) { - typeResolver.resolveType(scopeForDeclarationResolutionWithTypeParameters, contextReceiverTypeRef, trace, true); - } - contextReceiverTypes = contextReceiverTypeRefs.stream() - .map((typeRef) -> typeResolver.resolveType(scopeForDeclarationResolutionWithTypeParameters, typeRef, trace, true)); } - ReceiverParameterDescriptor receiverDescriptor; - if (receiverType != null) { + LinkedHashMap receiverToLabelMap = new LinkedHashMap<>(); + + KtTypeReference receiverTypeRef = variableDeclaration.getReceiverTypeReference(); + ReceiverParameterDescriptor receiverDescriptor = null; + if (receiverTypeRef != null) { + receiverType = typeResolver.resolveType(scopeForDeclarationResolutionWithTypeParameters, receiverTypeRef, trace, true); AnnotationSplitter splitter = new AnnotationSplitter(storageManager, receiverType.getAnnotations(), EnumSet.of(RECEIVER)); receiverDescriptor = DescriptorFactory.createExtensionReceiverParameterForCallable( - propertyDescriptor, receiverType, splitter.getAnnotationsForTarget(RECEIVER) - ); - } - else { - receiverDescriptor = null; + propertyDescriptor, receiverType, splitter.getAnnotationsForTarget(RECEIVER), + false); + receiverToLabelMap.put(receiverDescriptor, receiverTypeRef.nameForReceiverLabel()); } - List contextReceiverDescriptors = contextReceiverTypes.map((type) -> { - AnnotationSplitter splitter = new AnnotationSplitter(storageManager, type.getAnnotations(), EnumSet.of(RECEIVER)); - return DescriptorFactory.createExtensionReceiverParameterForCallable( - propertyDescriptor, type, splitter.getAnnotationsForTarget(RECEIVER) - ); - }).collect(Collectors.toList()); + List contextReceivers = variableDeclaration.getContextReceivers(); + List contextReceiverDescriptors = + createReceiverDescriptorsForProperty(propertyDescriptor, scopeForDeclarationResolutionWithTypeParameters, trace, + contextReceivers, receiverToLabelMap); LexicalScope scopeForInitializer = ScopeUtils.makeScopeForPropertyInitializer(scopeForInitializerResolutionWithTypeParameters, propertyDescriptor); KotlinType propertyType = propertyInfo.getVariableType(); @@ -1037,11 +1022,41 @@ public class DescriptorResolver { new FieldDescriptorImpl(annotationSplitter.getAnnotationsForTarget(FIELD), propertyDescriptor), new FieldDescriptorImpl(annotationSplitter.getAnnotationsForTarget(PROPERTY_DELEGATE_FIELD), propertyDescriptor) ); - + trace.record(DESCRIPTOR_TO_NAMED_RECEIVERS, propertyDescriptor, receiverToLabelMap); trace.record(BindingContext.VARIABLE, variableDeclaration, propertyDescriptor); return propertyDescriptor; } + private List createReceiverDescriptorsForProperty( + @NotNull PropertyDescriptor propertyDescriptor, + @NotNull LexicalScope scopeForResolution, + @NotNull BindingTrace trace, + @NotNull List contextReceivers, + @NotNull Map receiverToLabelMap + ) { + Map contextReceiversToTypes = new LinkedHashMap<>(); + for (KtContextReceiver contextReceiver: contextReceivers) { + KtTypeReference typeReference = contextReceiver.typeReference(); + if (typeReference == null) { + continue; + } + KotlinType kotlinType = typeResolver.resolveType(scopeForResolution, typeReference, trace, true); + contextReceiversToTypes.put(contextReceiver, kotlinType); + } + return Lists.reverse(contextReceivers).stream().map(contextReceiver -> { + KotlinType receiverType = contextReceiversToTypes.get(contextReceiver); + AnnotationSplitter splitter = new AnnotationSplitter(storageManager, receiverType.getAnnotations(), EnumSet.of(RECEIVER)); + ReceiverParameterDescriptor receiverDescriptor = DescriptorFactory.createExtensionReceiverParameterForCallable( + propertyDescriptor, receiverType, splitter.getAnnotationsForTarget(RECEIVER), + true); + String contextReceiverName = contextReceiver.name(); + if (contextReceiverName != null) { + receiverToLabelMap.put(receiverDescriptor, contextReceiverName); + } + return receiverDescriptor; + }).collect(Collectors.toList()); + } + @NotNull /*package*/ static KotlinType transformAnonymousTypeIfNeeded( @NotNull DeclarationDescriptorWithVisibility descriptor, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt index f4e0fc48f2a..82e86505165 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorResolver.kt @@ -197,7 +197,8 @@ class FunctionDescriptorResolver( if (function is KtFunctionLiteral) expectedFunctionType.getReceiverType() else null } - val contextReceiverTypes = function.contextReceiverTypeReferences.map { + val contextReceivers = function.contextReceivers + val contextReceiverTypes = contextReceivers.mapNotNull { it.typeReference() }.map { typeResolver.resolveType(headerScope, it, trace, true) } @@ -225,23 +226,35 @@ class FunctionDescriptorResolver( } } + val receiverToLabelMap = linkedMapOf() val extensionReceiver = receiverType?.let { val splitter = AnnotationSplitter(storageManager, receiverType.annotations, EnumSet.of(AnnotationUseSiteTarget.RECEIVER)) DescriptorFactory.createExtensionReceiverParameterForCallable( - functionDescriptor, it, splitter.getAnnotationsForTarget(AnnotationUseSiteTarget.RECEIVER) - ) - } - val contextReceivers = contextReceiverTypes.map { - val splitter = AnnotationSplitter(storageManager, it.annotations, EnumSet.of(AnnotationUseSiteTarget.RECEIVER)) - DescriptorFactory.createExtensionReceiverParameterForCallable( - functionDescriptor, it, splitter.getAnnotationsForTarget(AnnotationUseSiteTarget.RECEIVER) + functionDescriptor, it, splitter.getAnnotationsForTarget(AnnotationUseSiteTarget.RECEIVER), false ) + }?.apply { + val extensionReceiverName = receiverTypeRef?.nameForReceiverLabel() + if (extensionReceiverName != null) { + receiverToLabelMap[this] = extensionReceiverName + } } + val contextReceiverDescriptors = contextReceiverTypes.mapNotNull { type -> + val splitter = AnnotationSplitter(storageManager, type.annotations, EnumSet.of(AnnotationUseSiteTarget.RECEIVER)) + DescriptorFactory.createExtensionReceiverParameterForCallable( + functionDescriptor, type, splitter.getAnnotationsForTarget(AnnotationUseSiteTarget.RECEIVER), true + ) + } + contextReceiverDescriptors.reversed().zip(contextReceivers.lastIndex downTo 0).forEach { (contextReceiverDescriptor, i) -> + contextReceivers[i].name()?.let { + receiverToLabelMap[contextReceiverDescriptor] = it + } + } + trace.record(BindingContext.DESCRIPTOR_TO_NAMED_RECEIVERS, functionDescriptor, receiverToLabelMap) functionDescriptor.initialize( extensionReceiver, getDispatchReceiverParameterIfNeeded(container), - contextReceivers, + contextReceiverDescriptors, typeParameterDescriptors, valueParameterDescriptors, returnType, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java index b9d363cf568..47e47dc53fd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/FunctionDescriptorUtil.java @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.resolve; +import com.google.common.collect.Lists; import kotlin.Unit; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.descriptors.*; @@ -73,7 +74,9 @@ public class FunctionDescriptorUtil { } List contextReceiverParameters = descriptor.getContextReceiverParameters(); if (!contextReceiverParameters.isEmpty()) { - implicitReceivers.addAll(contextReceiverParameters); + implicitReceivers.addAll( + Lists.reverse(contextReceiverParameters) + ); } return new LexicalScopeImpl( outerScope, descriptor, true, implicitReceivers, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/IdentifierInfo.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/IdentifierInfo.kt index 3eeba4f439f..ab01f6198f2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/IdentifierInfo.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/IdentifierInfo.kt @@ -180,7 +180,7 @@ internal fun getIdForStableIdentifier( is KtThisExpression -> { val declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.instanceReference) - getIdForThisReceiver(declarationDescriptor) + getIdForThisReceiver(declarationDescriptor, bindingContext, expression.getLabelName()) } is KtPostfixExpression -> { @@ -229,7 +229,7 @@ private fun getIdForSimpleNameExpression( if (implicitReceiver == null) { selectorInfo } else { - val receiverInfo = getIdForImplicitReceiver(implicitReceiver, simpleNameExpression) + val receiverInfo = getIdForImplicitReceiver(implicitReceiver, simpleNameExpression, bindingContext) if (receiverInfo == null) { selectorInfo @@ -255,9 +255,9 @@ private fun getIdForSimpleNameExpression( } } -private fun getIdForImplicitReceiver(receiverValue: ReceiverValue?, expression: KtExpression?) = +private fun getIdForImplicitReceiver(receiverValue: ReceiverValue?, expression: KtExpression?, bindingContext: BindingContext) = when (receiverValue) { - is ImplicitReceiver -> getIdForThisReceiver(receiverValue.declarationDescriptor) + is ImplicitReceiver -> getIdForThisReceiver(receiverValue.declarationDescriptor, bindingContext) is TransientReceiver -> throw AssertionError("Transient receiver is implicit for an explicit expression: $expression. Receiver: $receiverValue") @@ -265,16 +265,48 @@ private fun getIdForImplicitReceiver(receiverValue: ReceiverValue?, expression: else -> null } -private fun getIdForThisReceiver(descriptorOfThisReceiver: DeclarationDescriptor?) = when (descriptorOfThisReceiver) { - is CallableDescriptor -> { - val receiverParameter = descriptorOfThisReceiver.extensionReceiverParameter - ?: error("'This' refers to the callable member without a receiver parameter: $descriptorOfThisReceiver") - IdentifierInfo.Receiver(receiverParameter.value) +private fun getIdForThisReceiver( + descriptorOfThisReceiver: DeclarationDescriptor?, + bindingContext: BindingContext, + labelName: String? = null +) = + when (descriptorOfThisReceiver) { + is CallableDescriptor -> { + val receiverParameter = findReceiverByLabelOrGetDefault( + descriptorOfThisReceiver, + descriptorOfThisReceiver.extensionReceiverParameter, + bindingContext, + labelName + ) + IdentifierInfo.Receiver(receiverParameter.value) + } + + is ClassDescriptor -> { + val receiverParameter = findReceiverByLabelOrGetDefault( + descriptorOfThisReceiver, + descriptorOfThisReceiver.thisAsReceiverParameter, + bindingContext, + labelName + ) + IdentifierInfo.Receiver(receiverParameter.value) + } + + else -> IdentifierInfo.NO } - is ClassDescriptor -> IdentifierInfo.Receiver(descriptorOfThisReceiver.thisAsReceiverParameter.value) - - else -> IdentifierInfo.NO +private fun findReceiverByLabelOrGetDefault( + descriptorOfThisReceiver: DeclarationDescriptor, + default: ReceiverParameterDescriptor?, + bindingContext: BindingContext, + labelName: String? = null +): ReceiverParameterDescriptor { + val receiverToLabelMap = bindingContext.get( + BindingContext.DESCRIPTOR_TO_NAMED_RECEIVERS, + if (descriptorOfThisReceiver is PropertyAccessorDescriptor) descriptorOfThisReceiver.correspondingProperty else descriptorOfThisReceiver + ) + return receiverToLabelMap?.entries?.find { + it.value == labelName + }?.key ?: default ?: error("'This' refers to the callable member without a receiver parameter: $descriptorOfThisReceiver") } private fun postfix(argumentInfo: IdentifierInfo, op: KtToken): IdentifierInfo = diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java index 969633d2ebf..6dc3c3d10cc 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java @@ -49,10 +49,7 @@ import org.jetbrains.kotlin.storage.StorageManager; import org.jetbrains.kotlin.types.*; import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; import static kotlin.collections.CollectionsKt.firstOrNull; @@ -308,13 +305,17 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes if (classOrObject == null) { return CollectionsKt.emptyList(); } - return classOrObject.getContextReceiverTypeReferences().stream().map(typeReference -> { - KotlinType kotlinType = c.getTypeResolver().resolveType(getScopeForClassHeaderResolution(), typeReference, c.getTrace(), true); - return new ReceiverParameterDescriptorImpl( - this, - new ExtensionClassReceiver(this, kotlinType, null), - Annotations.Companion.getEMPTY() - ); + return classOrObject.getContextReceivers().stream() + .map(KtContextReceiver::typeReference) + .filter(Objects::nonNull) + .map(typeReference -> { + KotlinType kotlinType = + c.getTypeResolver().resolveType(getScopeForClassHeaderResolution(), typeReference, c.getTrace(), true); + return new ReceiverParameterDescriptorImpl( + this, + new ExtensionClassReceiver(this, kotlinType, null), + Annotations.Companion.getEMPTY() + ); }).collect(Collectors.toList()); }); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index fb981af99a9..d2319286559 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -67,6 +67,7 @@ import org.jetbrains.kotlin.resolve.constants.*; import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind; import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope; import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver; +import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver; import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt; import org.jetbrains.kotlin.types.*; @@ -596,7 +597,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } } else if (!receivers.isEmpty()) { - result = receivers.get(0); + // `this` cannot point to context receiver + for (ReceiverParameterDescriptor receiver : receivers) { + if (!(receiver.getValue() instanceof ExtensionReceiver) || !((ExtensionReceiver) receiver.getValue()).isContextReceiver()) { + result = receiver; + break; + } + } } if (result != null) { context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), result.getContainingDeclaration()); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt index 5dd51afad92..de22a258a0b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/LabelResolver.kt @@ -17,28 +17,29 @@ package org.jetbrains.kotlin.types.expressions import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.diagnostics.Errors.LABEL_NAME_CLASH import org.jetbrains.kotlin.diagnostics.Errors.UNRESOLVED_REFERENCE import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.checkReservedYield import org.jetbrains.kotlin.resolve.* -import org.jetbrains.kotlin.resolve.BindingContext.LABEL_TARGET -import org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET +import org.jetbrains.kotlin.resolve.BindingContext.* import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext import org.jetbrains.kotlin.resolve.scopes.utils.getDeclarationsByLabel +import org.jetbrains.kotlin.utils.addIfNotNull object LabelResolver { - private fun getElementsByLabelName(labelName: Name, labelExpression: KtSimpleNameExpression): Set { + private fun getElementsByLabelName( + labelName: Name, + labelExpression: KtSimpleNameExpression, + isThisExpression: Boolean + ): Set { val elements = linkedSetOf() var parent: PsiElement? = labelExpression.parent while (parent != null) { - val name = getLabelNameIfAny(parent) - if (name != null && name == labelName) { + val names = getLabelNamesIfAny(parent, isThisExpression) + if (names.contains(labelName)) { elements.add(getExpressionUnderLabel(parent as KtExpression)) } parent = if (parent is KtCodeFragment) parent.context else parent.parent @@ -46,20 +47,33 @@ object LabelResolver { return elements } - fun getLabelNameIfAny(element: PsiElement): Name? { - return when (element) { - is KtLabeledExpression -> element.getLabelNameAsName() - is KtFunctionLiteral -> getLabelNameIfAny(element.parent) - is KtLambdaExpression -> getLabelForFunctionalExpression(element) - is KtNamedFunction -> element.nameAsName ?: getLabelForFunctionalExpression(element) - else -> null + fun getLabelNamesIfAny(element: PsiElement, addContextReceiverNames: Boolean): List { + val result = mutableListOf() + when (element) { + is KtLabeledExpression -> result.addIfNotNull(element.getLabelNameAsName()) + // TODO: Support context receivers in function literals + is KtFunctionLiteral -> return getLabelNamesIfAny(element.parent, false) + is KtLambdaExpression -> result.addIfNotNull(getLabelForFunctionalExpression(element)) } + val functionOrProperty = when (element) { + is KtNamedFunction -> element + is KtPropertyAccessor -> element.property + else -> return result + } + if (addContextReceiverNames) { + functionOrProperty.contextReceivers + .mapNotNullTo(result) { it.name()?.let { s -> Name.identifier(s) } } + functionOrProperty.receiverTypeReference?.nameForReceiverLabel()?.let { result.add(Name.identifier(it)) } + } + val name = functionOrProperty.nameAsName ?: getLabelForFunctionalExpression(functionOrProperty) + result.addIfNotNull(name) + return result } private fun getLabelForFunctionalExpression(element: KtExpression): Name? { val parent = element.parent return when (parent) { - is KtLabeledExpression -> getLabelNameIfAny(parent) + is KtLabeledExpression -> getLabelNamesIfAny(parent, false).singleOrNull() is KtBinaryExpression -> parent.operationReference.getReferencedNameAsName() else -> getCallerName(element) } @@ -105,7 +119,7 @@ object LabelResolver { val labelName = expression.getLabelNameAsName() if (labelElement == null || labelName == null) return null - return resolveNamedLabel(labelName, labelElement, context.trace) ?: run { + return resolveNamedLabel(labelName, labelElement, context.trace, false) ?: run { context.trace.report(UNRESOLVED_REFERENCE.on(labelElement, labelElement)) null } @@ -114,9 +128,10 @@ object LabelResolver { private fun resolveNamedLabel( labelName: Name, labelExpression: KtSimpleNameExpression, - trace: BindingTrace + trace: BindingTrace, + isThisExpression: Boolean ): KtElement? { - val list = getElementsByLabelName(labelName, labelExpression) + val list = getElementsByLabelName(labelName, labelExpression, isThisExpression) if (list.isEmpty()) return null if (list.size > 1) { @@ -160,10 +175,14 @@ object LabelResolver { return LabeledReceiverResolutionResult.labelResolutionSuccess(thisReceiver) } 0 -> { - val element = resolveNamedLabel(labelName, targetLabel, context.trace) - val declarationDescriptor = context.trace.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, element] + val element = resolveNamedLabel(labelName, targetLabel, context.trace, expression is KtThisExpression) + val declarationDescriptor = context.trace.bindingContext[DECLARATION_TO_DESCRIPTOR, element] if (declarationDescriptor is FunctionDescriptor) { - val thisReceiver = declarationDescriptor.extensionReceiverParameter + val receiverToLabelMap = + context.trace.bindingContext[DESCRIPTOR_TO_NAMED_RECEIVERS, if (declarationDescriptor is PropertyAccessorDescriptor) declarationDescriptor.correspondingProperty else declarationDescriptor] + val thisReceiver = receiverToLabelMap?.entries?.find { + it.value == labelName.identifier + }?.key ?: declarationDescriptor.extensionReceiverParameter if (thisReceiver != null) { context.trace.record(LABEL_TARGET, targetLabel, element) context.trace.record(REFERENCE_TARGET, referenceExpression, declarationDescriptor) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt index c1516db6e24..4d19818b5cf 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionGenerator.kt @@ -50,7 +50,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio declareSimpleFunction( ktFunction, ktFunction.receiverTypeReference, - ktFunction.contextReceiverTypeReferences, + ktFunction.contextReceivers.mapNotNull { it.typeReference() }, origin, getOrFail(BindingContext.FUNCTION, ktFunction) ) { @@ -127,7 +127,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio irAccessor.returnType = irAccessor.descriptor.returnType!!.toIrType() generateValueParameterDeclarations( irAccessor, ktAccessor ?: ktProperty, ktProperty.receiverTypeReference, - ktProperty.contextReceiverTypeReferences + ktProperty.contextReceivers.mapNotNull { it.typeReference() } ) val ktBodyExpression = ktAccessor?.bodyExpression irAccessor.body = @@ -237,7 +237,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio declareConstructor( ktClassOrObject, ktClassOrObject.primaryConstructor ?: ktClassOrObject, - ktClassOrObject.contextReceiverTypeReferences, + ktClassOrObject.contextReceivers.mapNotNull { it.typeReference() }, primaryConstructorDescriptor ) { irConstructor -> if ( @@ -254,7 +254,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio return declareConstructor( ktConstructor, ktConstructor, - ktClassOrObject.contextReceiverTypeReferences, + ktClassOrObject.contextReceivers.mapNotNull { it.typeReference() }, constructorDescriptor ) { when { diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt index 3721b1fc44e..f55b11e935a 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt @@ -422,12 +422,16 @@ class StatementGenerator( generateThisReceiver(startOffset, endOffset, referenceTarget.thisAsReceiverParameter.type, referenceTarget) is CallableDescriptor -> { - val extensionReceiver = referenceTarget.extensionReceiverParameter ?: TODO("No extension receiver: $referenceTarget") - val extensionReceiverType = extensionReceiver.type.toIrType() + val resolvedCall = getResolvedCall(expression) + val receivers = listOfNotNull(referenceTarget.extensionReceiverParameter) + referenceTarget.contextReceiverParameters + val receiver = receivers.find { + it == resolvedCall?.candidateDescriptor + } ?: referenceTarget.extensionReceiverParameter ?: TODO("No receiver: $referenceTarget") + val receiverType = receiver.type.toIrType() IrGetValueImpl( startOffset, endOffset, - extensionReceiverType, - context.symbolTable.referenceValueParameter(extensionReceiver) + receiverType, + context.symbolTable.referenceValueParameter(receiver) ) } diff --git a/compiler/psi/src/org/jetbrains/kotlin/KtNodeTypes.java b/compiler/psi/src/org/jetbrains/kotlin/KtNodeTypes.java index 5f8a8f1f0f8..3705c99c883 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/KtNodeTypes.java +++ b/compiler/psi/src/org/jetbrains/kotlin/KtNodeTypes.java @@ -40,6 +40,7 @@ public interface KtNodeTypes { IElementType SECONDARY_CONSTRUCTOR = KtStubElementTypes.SECONDARY_CONSTRUCTOR; IElementType PRIMARY_CONSTRUCTOR = KtStubElementTypes.PRIMARY_CONSTRUCTOR; IElementType CONTEXT_RECEIVER = KtStubElementTypes.CONTEXT_RECEIVER; + IElementType CONTEXT_RECEIVER_LIST = KtStubElementTypes.CONTEXT_RECEIVER_LIST; IElementType TYPE_PARAMETER_LIST = KtStubElementTypes.TYPE_PARAMETER_LIST; IElementType TYPE_PARAMETER = KtStubElementTypes.TYPE_PARAMETER; diff --git a/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java b/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java index 48639b9a9e0..0206ffe9bb5 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java +++ b/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java @@ -597,7 +597,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing { } } - private boolean isAtLabelDefinitionOrMissingIdentifier() { + boolean isAtLabelDefinitionOrMissingIdentifier() { return (at(IDENTIFIER) && myBuilder.rawLookup(1) == AT) || at(AT); } @@ -1690,7 +1690,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing { /* * IDENTIFIER "@" */ - private void parseLabelDefinition() { + void parseLabelDefinition() { PsiBuilder.Marker labelWrap = mark(); PsiBuilder.Marker mark = mark(); diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtCallableDeclaration.java b/compiler/psi/src/org/jetbrains/kotlin/psi/KtCallableDeclaration.java index b4d1875c76b..2da5450f324 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtCallableDeclaration.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtCallableDeclaration.java @@ -33,7 +33,7 @@ public interface KtCallableDeclaration extends KtNamedDeclaration, KtTypeParamet KtTypeReference getReceiverTypeReference(); @NotNull - List getContextReceiverTypeReferences(); + List getContextReceivers(); @Nullable KtTypeReference getTypeReference(); diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt index 43baefd9fc5..f2847dfceb3 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtClassOrObject.kt @@ -188,17 +188,17 @@ abstract class KtClassOrObject : return parts.joinToString(separator = ".") } - override fun getContextReceiverTypeReferences(): List { + override fun getContextReceivers(): List { val stub = stub if (stub != null) { - return getStubOrPsiChildrenAsList(KtStubElementTypes.TYPE_REFERENCE) + return getStubOrPsiChildrenAsList(KtStubElementTypes.CONTEXT_RECEIVER) } var node = node.firstChildNode while (node != null) { val tt = node.elementType - if (tt === KtNodeTypes.CONTEXT_RECEIVER) { - val contextReceiver = node.psi as KtContextReceiver - return contextReceiver.typeReferences() + if (tt === KtNodeTypes.CONTEXT_RECEIVER_LIST) { + val contextReceiver = node.psi as KtContextReceiverList + return contextReceiver.contextReceivers() } node = node.treeNext } diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtConstructor.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/KtConstructor.kt index 0a33e4edae7..fce7cabf53f 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtConstructor.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtConstructor.kt @@ -40,7 +40,7 @@ abstract class KtConstructor> : KtDeclarationStub = emptyList() + override fun getContextReceivers(): List = emptyList() override fun getTypeReference() = null diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtContextReceiver.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/KtContextReceiver.kt index 8fec0adb248..23ce9bc00fa 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtContextReceiver.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtContextReceiver.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.psi import com.intellij.lang.ASTNode import org.jetbrains.kotlin.KtNodeTypes +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes @@ -14,9 +15,14 @@ class KtContextReceiver : KtElementImplStub) : super(stub, KtStubElementTypes.CONTEXT_RECEIVER) - override fun accept(visitor: KtVisitor, data: D): R { - return visitor.visitContextReceiver(this, data) - } + fun targetLabel(): KtSimpleNameExpression? = + findChildByType(KtNodeTypes.LABEL_QUALIFIER) + ?.findChildByType(KtNodeTypes.LABEL) - fun typeReferences(): List = findChildrenByType(KtNodeTypes.TYPE_REFERENCE) + fun labelName(): String? = targetLabel()?.getReferencedName() + fun labelNameAsName(): Name? = targetLabel()?.getReferencedNameAsName() + + fun typeReference(): KtTypeReference? = findChildByType(KtNodeTypes.TYPE_REFERENCE) + + fun name(): String? = labelName() ?: typeReference()?.nameForReceiverLabel() } \ No newline at end of file diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtContextReceiverList.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/KtContextReceiverList.kt new file mode 100644 index 00000000000..06b1a708f2b --- /dev/null +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtContextReceiverList.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.psi + +import com.intellij.lang.ASTNode +import org.jetbrains.kotlin.KtNodeTypes +import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub +import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes + +class KtContextReceiverList : KtElementImplStub> { + constructor(node: ASTNode) : super(node) + constructor(stub: KotlinPlaceHolderStub) : super(stub, KtStubElementTypes.CONTEXT_RECEIVER_LIST) + + override fun accept(visitor: KtVisitor, data: D): R { + return visitor.visitContextReceiverList(this, data) + } + + fun contextReceivers(): List = findChildrenByType(KtNodeTypes.CONTEXT_RECEIVER) + + fun typeReferences(): List = contextReceivers().mapNotNull { it.typeReference() } + +} \ No newline at end of file diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtDestructuringDeclarationEntry.java b/compiler/psi/src/org/jetbrains/kotlin/psi/KtDestructuringDeclarationEntry.java index 10232b07751..e25235e5443 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtDestructuringDeclarationEntry.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtDestructuringDeclarationEntry.java @@ -77,7 +77,7 @@ public class KtDestructuringDeclarationEntry extends KtNamedDeclarationNotStubbe @NotNull @Override - public List getContextReceiverTypeReferences() { + public List getContextReceivers() { return Collections.emptyList(); } diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtFunctionNotStubbed.java b/compiler/psi/src/org/jetbrains/kotlin/psi/KtFunctionNotStubbed.java index 37bcfda9f29..b3ac7e18f8d 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtFunctionNotStubbed.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtFunctionNotStubbed.java @@ -64,7 +64,7 @@ public abstract class KtFunctionNotStubbed extends KtTypeParameterListOwnerNotSt @NotNull @Override - public List getContextReceiverTypeReferences() { + public List getContextReceivers() { return Collections.emptyList(); } diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtNamedFunction.java b/compiler/psi/src/org/jetbrains/kotlin/psi/KtNamedFunction.java index 2b457d2c788..11bef2cb861 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtNamedFunction.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtNamedFunction.java @@ -185,12 +185,12 @@ public class KtNamedFunction extends KtTypeParameterListOwnerStub getContextReceiverTypeReferences() { + public List getContextReceivers() { KotlinFunctionStub stub = getStub(); if (stub != null) { - List childContextReceivers = getStubOrPsiChildrenAsList(KtStubElementTypes.CONTEXT_RECEIVER); + List childContextReceivers = getStubOrPsiChildrenAsList(KtStubElementTypes.CONTEXT_RECEIVER_LIST); if (!childContextReceivers.isEmpty()) { - return childContextReceivers.get(0).typeReferences(); + return childContextReceivers.get(0).contextReceivers(); } else { return Collections.emptyList(); @@ -200,13 +200,13 @@ public class KtNamedFunction extends KtTypeParameterListOwnerStub getContextReceiverTypeRefsByTree() { + private List getContextReceiverTypeRefsByTree() { PsiElement child = getFirstChild(); while (child != null) { IElementType tt = child.getNode().getElementType(); if (tt == KtTokens.LPAR || tt == KtTokens.COLON) break; - if (child instanceof KtContextReceiver) { - return ((KtContextReceiver) child).typeReferences(); + if (child instanceof KtContextReceiverList) { + return ((KtContextReceiverList) child).contextReceivers(); } child = child.getNextSibling(); } diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtParameter.java b/compiler/psi/src/org/jetbrains/kotlin/psi/KtParameter.java index 1254ed631db..9156ebbbab1 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtParameter.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtParameter.java @@ -195,7 +195,7 @@ public class KtParameter extends KtNamedDeclarationStub imp @NotNull @Override - public List getContextReceiverTypeReferences() { + public List getContextReceivers() { return Collections.emptyList(); } diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtProperty.java b/compiler/psi/src/org/jetbrains/kotlin/psi/KtProperty.java index 8f3a17bd8ac..186e79809fd 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtProperty.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtProperty.java @@ -116,12 +116,12 @@ public class KtProperty extends KtTypeParameterListOwnerStub @NotNull @Override - public List getContextReceiverTypeReferences() { + public List getContextReceivers() { KotlinPropertyStub stub = getStub(); if (stub != null) { - KtContextReceiver contextReceiver = getStubOrPsiChild(KtStubElementTypes.CONTEXT_RECEIVER); + KtContextReceiverList contextReceiver = getStubOrPsiChild(KtStubElementTypes.CONTEXT_RECEIVER_LIST); if (contextReceiver != null) { - return contextReceiver.typeReferences(); + return contextReceiver.contextReceivers(); } else { return Collections.emptyList(); } @@ -130,16 +130,16 @@ public class KtProperty extends KtTypeParameterListOwnerStub } @NotNull - private List getContextReceiverTypeRefsByTree() { + private List getContextReceiverTypeRefsByTree() { ASTNode node = getNode().getFirstChildNode(); while (node != null) { IElementType tt = node.getElementType(); if (tt == KtTokens.COLON) { break; } - if (tt == KtNodeTypes.CONTEXT_RECEIVER) { - KtContextReceiver contextReceiver = (KtContextReceiver) node.getPsi(); - return contextReceiver.typeReferences(); + if (tt == KtNodeTypes.CONTEXT_RECEIVER_LIST) { + KtContextReceiverList contextReceiver = (KtContextReceiverList) node.getPsi(); + return contextReceiver.contextReceivers(); } node = node.getTreeNext(); } diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtPureClassOrObject.java b/compiler/psi/src/org/jetbrains/kotlin/psi/KtPureClassOrObject.java index 95102ec7dcd..fa932ac1a74 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtPureClassOrObject.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtPureClassOrObject.java @@ -60,7 +60,7 @@ public interface KtPureClassOrObject extends KtPureElement, KtDeclarationContain @NotNull @ReadOnly - List getContextReceiverTypeReferences(); + List getContextReceivers(); @Nullable KtClassBody getBody(); diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtTypeReference.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/KtTypeReference.kt index e1c044726a2..c2069719b32 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtTypeReference.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtTypeReference.kt @@ -55,4 +55,6 @@ class KtTypeReference : KtModifierListOwnerStub(KtTokens.LPAR) != null && findChildByType(KtTokens.RPAR) != null } + + fun nameForReceiverLabel() = (typeElement as? KtUserType)?.referencedName } diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtVisitor.java b/compiler/psi/src/org/jetbrains/kotlin/psi/KtVisitor.java index fa3f42b3f57..2660b89c74e 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/KtVisitor.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtVisitor.java @@ -158,8 +158,8 @@ public class KtVisitor extends PsiElementVisitor { return visitSuperTypeListEntry(specifier, data); } - public R visitContextReceiver(@NotNull KtContextReceiver contextReceiver, D data) { - return visitKtElement(contextReceiver, data); + public R visitContextReceiverList(@NotNull KtContextReceiverList contextReceiverList, D data) { + return visitKtElement(contextReceiverList, data); } public R visitConstructorDelegationCall(@NotNull KtConstructorDelegationCall call, D data) { diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java index 651fedb1311..81726831539 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java @@ -145,6 +145,8 @@ public interface KtStubElementTypes { KtPlaceHolderStubElementType CONTEXT_RECEIVER = new KtPlaceHolderStubElementType<>("CONTEXT_RECEIVER", KtContextReceiver.class); + KtPlaceHolderStubElementType CONTEXT_RECEIVER_LIST = + new KtPlaceHolderStubElementType<>("CONTEXT_RECEIVER_LIST", KtContextReceiverList.class); KtConstantExpressionElementType NULL = new KtConstantExpressionElementType("NULL"); KtConstantExpressionElementType BOOLEAN_CONSTANT = new KtConstantExpressionElementType("BOOLEAN_CONSTANT"); diff --git a/compiler/testData/codegen/box/extensionFunctions/contextReceivers/this.kt b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/this.kt new file mode 100644 index 00000000000..ec5f00e5253 --- /dev/null +++ b/compiler/testData/codegen/box/extensionFunctions/contextReceivers/this.kt @@ -0,0 +1,20 @@ +// TARGET_BACKEND: JVM_IR +// IGNORE_BACKEND_FIR: JVM_IR + +class A(val a: T) +class B(val b: Any?) + +context(A, B) fun f() { + this@A.a.length + this@B.b +} + +fun box(): String { + with(A("")) { + with(B(null)) { + f() + } + } + return "OK" +} + diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/superWithContext.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/superWithContext.fir.kt new file mode 100644 index 00000000000..845c679ba49 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/superWithContext.fir.kt @@ -0,0 +1,19 @@ +interface Context { + fun h() {} +} + +open class A { + open fun f() {} +} + +class B : A() { + override fun f() {} + + context(Context) + inner class C { + fun g() { + super@B.f() + super@Context.h() + } + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/superWithContext.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/superWithContext.kt new file mode 100644 index 00000000000..523d2b4d5a4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/superWithContext.kt @@ -0,0 +1,19 @@ +interface Context { + fun h() {} +} + +open class A { + open fun f() {} +} + +class B : A() { + override fun f() {} + + context(Context) + inner class C { + fun g() { + super@B.f() + super@Context.h() + } + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/superWithContext.txt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/superWithContext.txt new file mode 100644 index 00000000000..6a867ecceba --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/superWithContext.txt @@ -0,0 +1,32 @@ +package + +public open class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun f(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class B : A { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun f(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public final inner class C { + public constructor C() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun g(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +public interface Context { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun h(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisIdentifierInfo.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisIdentifierInfo.fir.kt new file mode 100644 index 00000000000..c68401f13c1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisIdentifierInfo.fir.kt @@ -0,0 +1,6 @@ +class A(val a: String?) + +context(A) fun f() { + if (this@A.a == null) return + this@A.a.length +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisIdentifierInfo.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisIdentifierInfo.kt new file mode 100644 index 00000000000..594eea357e1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisIdentifierInfo.kt @@ -0,0 +1,6 @@ +class A(val a: String?) + +context(A) fun f() { + if (this@A.a == null) return + this@A.a.length +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisIdentifierInfo.txt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisIdentifierInfo.txt new file mode 100644 index 00000000000..3e8ba698060 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisIdentifierInfo.txt @@ -0,0 +1,11 @@ +package + +public fun f(): kotlin.Unit + +public final class A { + public constructor A(/*0*/ a: kotlin.String?) + public final val a: kotlin.String? + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.fir.kt new file mode 100644 index 00000000000..99a3ba6a292 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.fir.kt @@ -0,0 +1,22 @@ +class A(val a: T) +class B(val b: Any) +class C(val c: Any) + +context(labelAInt@A, A, labelB@B) fun f() { + this@labelAInt.a.toFloat() + this@A.a.length + this@labelB.b + this@B +} + +context(labelAInt@A, A, labelB@B) val C.p: Int + get() { + this@labelAInt.a.toFloat() + this@A.a.length + this@B + this@labelB.b + this@C.c + this@p.c + this.c + return 1 + } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.kt new file mode 100644 index 00000000000..9d1dad0c912 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.kt @@ -0,0 +1,22 @@ +class A(val a: T) +class B(val b: Any) +class C(val c: Any) + +context(labelAInt@A, A, labelB@B) fun f() { + this@labelAInt.a.toFloat() + this@A.a.length + this@labelB.b + this@B +} + +context(labelAInt@A, A, labelB@B) val C.p: Int + get() { + this@labelAInt.a.toFloat() + this@A.a.length + this@B + this@labelB.b + this@C.c + this@p.c + this.c + return 1 + } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.txt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.txt new file mode 100644 index 00000000000..2a33dd98d58 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.txt @@ -0,0 +1,28 @@ +package + +public val C.p: kotlin.Int +public fun f(): kotlin.Unit + +public final class A { + public constructor A(/*0*/ a: T) + public final val a: T + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class B { + public constructor B(/*0*/ b: kotlin.Any) + public final val b: kotlin.Any + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class C { + public constructor C(/*0*/ c: kotlin.Any) + public final val c: kotlin.Any + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsClasses.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsClasses.fir.kt new file mode 100644 index 00000000000..dc65f167b48 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsClasses.fir.kt @@ -0,0 +1,9 @@ +class A { + val x = 1 +} + +context(A) class B { + val prop = x + this@A.x + + fun f() = x + this@A.x +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsClasses.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsClasses.kt new file mode 100644 index 00000000000..fa02a6267b0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsClasses.kt @@ -0,0 +1,9 @@ +class A { + val x = 1 +} + +context(A) class B { + val prop = x + this@A.x + + fun f() = x + this@A.x +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsClasses.txt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsClasses.txt new file mode 100644 index 00000000000..b72e7f125c9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsClasses.txt @@ -0,0 +1,18 @@ +package + +public final class A { + public constructor A() + public final val x: kotlin.Int = 1 + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class B { + public constructor B() + public final val prop: [ERROR : Type for x + this@A.x] + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun f(): [ERROR : Error function type] + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.fir.kt new file mode 100644 index 00000000000..7981a5b3b49 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.fir.kt @@ -0,0 +1,17 @@ +class A(val a: T) +class B(val b: Any) +class C(val c: Any) + +context(A, A, B) fun f() { + this@A.a.length + this@B.b + this +} + +context(A, A, B) fun C.f() { + this@A.a.length + this@B.b + this@C.c + this@f.c + this.c +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.kt new file mode 100644 index 00000000000..92cd0197af3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.kt @@ -0,0 +1,17 @@ +class A(val a: T) +class B(val b: Any) +class C(val c: Any) + +context(A, A, B) fun f() { + this@A.a.length + this@B.b + this +} + +context(A, A, B) fun C.f() { + this@A.a.length + this@B.b + this@C.c + this@f.c + this.c +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.txt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.txt new file mode 100644 index 00000000000..19195f3ba6a --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.txt @@ -0,0 +1,28 @@ +package + +public fun f(): kotlin.Unit +public fun C.f(): kotlin.Unit + +public final class A { + public constructor A(/*0*/ a: T) + public final val a: T + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class B { + public constructor B(/*0*/ b: kotlin.Any) + public final val b: kotlin.Any + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class C { + public constructor C(/*0*/ c: kotlin.Any) + public final val c: kotlin.Any + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.fir.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.fir.kt new file mode 100644 index 00000000000..6276c3a145e --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.fir.kt @@ -0,0 +1,28 @@ +class A(val a: T) +class B(val b: Any) +class C(val c: Any) + +context(A, A, B) var p: Int + get() { + this@A.a.toDouble() + this@A.a.length + this@B.b + this + return 1 + } + set(value) { + this@A.a.length + this@B.b + this + field = value + } + +context(A, A, B) val C.p: Int + get() { + this@A.a.length + this@B.b + this@C.c + this@p.c + this.c + return 1 + } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.kt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.kt new file mode 100644 index 00000000000..768ced6d82f --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.kt @@ -0,0 +1,28 @@ +class A(val a: T) +class B(val b: Any) +class C(val c: Any) + +context(A, A, B) var p: Int + get() { + this@A.a.toDouble() + this@A.a.length + this@B.b + this + return 1 + } + set(value) { + this@A.a.length + this@B.b + this + field = value + } + +context(A, A, B) val C.p: Int + get() { + this@A.a.length + this@B.b + this@C.c + this@p.c + this.c + return 1 + } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.txt b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.txt new file mode 100644 index 00000000000..2d507b6ba6e --- /dev/null +++ b/compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.txt @@ -0,0 +1,28 @@ +package + +public var p: kotlin.Int +public val C.p: kotlin.Int + +public final class A { + public constructor A(/*0*/ a: T) + public final val a: T + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class B { + public constructor B(/*0*/ b: kotlin.Any) + public final val b: kotlin.Any + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class C { + public constructor C(/*0*/ c: kotlin.Any) + public final val c: kotlin.Any + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 36077899fc7..a38107d22a5 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -10630,6 +10630,42 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/plusMatrix.kt"); } + @Test + @TestMetadata("superWithContext.kt") + public void testSuperWithContext() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/superWithContext.kt"); + } + + @Test + @TestMetadata("thisIdentifierInfo.kt") + public void testThisIdentifierInfo() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/thisIdentifierInfo.kt"); + } + + @Test + @TestMetadata("thisWithCustomLabel.kt") + public void testThisWithCustomLabel() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithCustomLabel.kt"); + } + + @Test + @TestMetadata("thisWithReceiverLabelsClasses.kt") + public void testThisWithReceiverLabelsClasses() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsClasses.kt"); + } + + @Test + @TestMetadata("thisWithReceiverLabelsFunctions.kt") + public void testThisWithReceiverLabelsFunctions() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsFunctions.kt"); + } + + @Test + @TestMetadata("thisWithReceiverLabelsProperties.kt") + public void testThisWithReceiverLabelsProperties() throws Exception { + runTest("compiler/testData/diagnostics/tests/extensions/contextReceivers/thisWithReceiverLabelsProperties.kt"); + } + @Test @TestMetadata("typeParameterized.kt") public void testTypeParameterized() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index d628489dce2..4a8254651dd 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -16168,6 +16168,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testSimpleCall() throws Exception { runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/simpleCall.kt"); } + + @Test + @TestMetadata("this.kt") + public void testThis() throws Exception { + runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/this.kt"); + } } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorFactory.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorFactory.java index 43eb65a5ca0..9569a170811 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorFactory.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/DescriptorFactory.java @@ -188,9 +188,19 @@ public class DescriptorFactory { @NotNull CallableDescriptor owner, @Nullable KotlinType receiverParameterType, @NotNull Annotations annotations + ) { + return createExtensionReceiverParameterForCallable(owner, receiverParameterType, annotations, false); + } + + @Nullable + public static ReceiverParameterDescriptor createExtensionReceiverParameterForCallable( + @NotNull CallableDescriptor owner, + @Nullable KotlinType receiverParameterType, + @NotNull Annotations annotations, + boolean isContextReceiver ) { return receiverParameterType == null ? null - : new ReceiverParameterDescriptorImpl(owner, new ExtensionReceiver(owner, receiverParameterType, null), annotations); + : new ReceiverParameterDescriptorImpl(owner, new ExtensionReceiver(owner, receiverParameterType, null, isContextReceiver), annotations); } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/receivers/ExtensionReceiver.java b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/receivers/ExtensionReceiver.java index a871e09a89d..2bf90d2a00f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/receivers/ExtensionReceiver.java +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/receivers/ExtensionReceiver.java @@ -35,14 +35,25 @@ import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker; public class ExtensionReceiver extends AbstractReceiverValue implements ImplicitReceiver { private final CallableDescriptor descriptor; + private final boolean isContextReceiver; public ExtensionReceiver( @NotNull CallableDescriptor callableDescriptor, @NotNull KotlinType receiverType, @Nullable ReceiverValue original + ) { + this(callableDescriptor, receiverType, original, false); + } + + public ExtensionReceiver( + @NotNull CallableDescriptor callableDescriptor, + @NotNull KotlinType receiverType, + @Nullable ReceiverValue original, + boolean isContextReceiver ) { super(receiverType, original); this.descriptor = callableDescriptor; + this.isContextReceiver = isContextReceiver; } @NotNull @@ -61,4 +72,8 @@ public class ExtensionReceiver extends AbstractReceiverValue implements Implicit public String toString() { return getType() + ": Ext {" + descriptor + "}"; } + + public boolean isContextReceiver() { + return isContextReceiver; + } }