[decompiler] render annotated context receivers properly
^KT-79412 Fixed
(cherry picked from commit 3433b520a14cfaa2d16142bd57106be45c882797)
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/annotatedContextParameterType.kt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/annotatedContextParameterType.kt
index d7f12c2..7a23899 100644
--- a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/annotatedContextParameterType.kt
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/annotatedContextParameterType.kt
@@ -1,4 +1,3 @@
-// IGNORE_FIR
// LANGUAGE: +ContextParameters
// DECLARATION_TYPE: org.jetbrains.kotlin.psi.KtClass
// MAIN_FILE_NAME: MyClass
diff --git a/analysis/low-level-api-fir/testData/getOrBuildFirBinary/annotatedContextParameterType.txt b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/annotatedContextParameterType.txt
new file mode 100644
index 0000000..8506a62
--- /dev/null
+++ b/analysis/low-level-api-fir/testData/getOrBuildFirBinary/annotatedContextParameterType.txt
@@ -0,0 +1,23 @@
+KT element: KtClass
+KT element text:
+public final class MyClass public constructor() {
+ context((@MyAnnotation ParameterizedInterface<@MyAnnotation kotlin.String>)) public final val bar: kotlin.String /* compiled code */ /* hasBackingField: false */
+ public final get() {/* compiled code */ }
+
+ context((@MyAnnotation ParameterizedInterface<@MyAnnotation kotlin.String>)) public final fun foo(): kotlin.Unit { /* compiled code */ }
+}
+FIR element: FirRegularClassImpl
+FIR source kind: KtRealSourceElementKind
+
+FIR element rendered:
+public final [ResolvedTo(BODY_RESOLVE)] [IsNewPlaceForBodyGeneration=false] class MyClass : R|kotlin/Any| {
+ context([ResolvedTo(BODY_RESOLVE)] <unused var>@R|@R|MyAnnotation|() ParameterizedInterface<@R|MyAnnotation|() kotlin/String>|)
+ public final [ResolvedTo(BODY_RESOLVE)] fun foo(): R|kotlin/Unit|
+
+ context([ResolvedTo(BODY_RESOLVE)] <unused var>@R|@R|MyAnnotation|() ParameterizedInterface<@R|MyAnnotation|() kotlin/String>|)
+ public final [ResolvedTo(BODY_RESOLVE)] [HasBackingFieldKey=false] val bar: R|kotlin/String|
+ public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=MyClass] get(): R|kotlin/String|
+
+ public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=MyClass] constructor(): R|MyClass|
+
+}
diff --git a/compiler/testData/psi/contextParameters/annotatedContextParameterType.decompiled.stubs.txt b/compiler/testData/psi/contextParameters/annotatedContextParameterType.decompiled.stubs.txt
index 2138933..9d5f49f 100644
--- a/compiler/testData/psi/contextParameters/annotatedContextParameterType.decompiled.stubs.txt
+++ b/compiler/testData/psi/contextParameters/annotatedContextParameterType.decompiled.stubs.txt
@@ -2,24 +2,32 @@
PsiJetFileStubImpl[package=]
PACKAGE_DIRECTIVE
IMPORT_LIST
- MODIFIER_LIST[]
- CONTEXT_RECEIVER_LIST
- CONTEXT_RECEIVER[label=null]
- TYPE_REFERENCE
- USER_TYPE
- REFERENCE_EXPRESSION[referencedName=receiver]
- VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=null]
- TYPE_REFERENCE
- USER_TYPE
- REFERENCE_EXPRESSION[referencedName=MyAnnotation]
- MODIFIER_LIST[]
- ANNOTATION_ENTRY[hasValueArguments=false, shortName=MyAnnotation]
- CONSTRUCTOR_CALLEE
- TYPE_REFERENCE
- USER_TYPE
- REFERENCE_EXPRESSION[referencedName=MyAnnotation]
PROPERTY[fqName=bar, hasBackingField=false, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=true, isVar=false, name=bar]
MODIFIER_LIST[public]
+ CONTEXT_RECEIVER_LIST
+ CONTEXT_RECEIVER[label=null]
+ TYPE_REFERENCE
+ MODIFIER_LIST[]
+ ANNOTATION_ENTRY[hasValueArguments=false, shortName=MyAnnotation]
+ CONSTRUCTOR_CALLEE
+ TYPE_REFERENCE
+ USER_TYPE
+ REFERENCE_EXPRESSION[referencedName=MyAnnotation]
+ USER_TYPE
+ REFERENCE_EXPRESSION[referencedName=ParameterizedInterface]
+ TYPE_ARGUMENT_LIST
+ TYPE_PROJECTION[projectionKind=NONE]
+ TYPE_REFERENCE
+ MODIFIER_LIST[]
+ ANNOTATION_ENTRY[hasValueArguments=false, shortName=MyAnnotation]
+ CONSTRUCTOR_CALLEE
+ TYPE_REFERENCE
+ USER_TYPE
+ REFERENCE_EXPRESSION[referencedName=MyAnnotation]
+ USER_TYPE
+ USER_TYPE
+ REFERENCE_EXPRESSION[referencedName=kotlin]
+ REFERENCE_EXPRESSION[referencedName=String]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
@@ -28,24 +36,32 @@
PROPERTY_ACCESSOR[hasBlockBody=true, hasBody=true, isGetter=true]
MODIFIER_LIST[public final]
VALUE_PARAMETER_LIST
- MODIFIER_LIST[]
- CONTEXT_RECEIVER_LIST
- CONTEXT_RECEIVER[label=null]
- TYPE_REFERENCE
- USER_TYPE
- REFERENCE_EXPRESSION[referencedName=receiver]
- VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=null]
- TYPE_REFERENCE
- USER_TYPE
- REFERENCE_EXPRESSION[referencedName=MyAnnotation]
- MODIFIER_LIST[]
- ANNOTATION_ENTRY[hasValueArguments=false, shortName=MyAnnotation]
- CONSTRUCTOR_CALLEE
- TYPE_REFERENCE
- USER_TYPE
- REFERENCE_EXPRESSION[referencedName=MyAnnotation]
FUN[fqName=foo, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=true, mayHaveContract=false, name=foo]
MODIFIER_LIST[public]
+ CONTEXT_RECEIVER_LIST
+ CONTEXT_RECEIVER[label=null]
+ TYPE_REFERENCE
+ MODIFIER_LIST[]
+ ANNOTATION_ENTRY[hasValueArguments=false, shortName=MyAnnotation]
+ CONSTRUCTOR_CALLEE
+ TYPE_REFERENCE
+ USER_TYPE
+ REFERENCE_EXPRESSION[referencedName=MyAnnotation]
+ USER_TYPE
+ REFERENCE_EXPRESSION[referencedName=ParameterizedInterface]
+ TYPE_ARGUMENT_LIST
+ TYPE_PROJECTION[projectionKind=NONE]
+ TYPE_REFERENCE
+ MODIFIER_LIST[]
+ ANNOTATION_ENTRY[hasValueArguments=false, shortName=MyAnnotation]
+ CONSTRUCTOR_CALLEE
+ TYPE_REFERENCE
+ USER_TYPE
+ REFERENCE_EXPRESSION[referencedName=MyAnnotation]
+ USER_TYPE
+ USER_TYPE
+ REFERENCE_EXPRESSION[referencedName=kotlin]
+ REFERENCE_EXPRESSION[referencedName=String]
VALUE_PARAMETER_LIST
TYPE_REFERENCE
USER_TYPE
diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt
index a846bf4..c3c126a 100644
--- a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt
+++ b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt
@@ -761,9 +761,9 @@
}
}
- private fun KotlinType.renderForReceiver(): String {
+ private fun KotlinType.renderForReceiver(wrapAnnotated: Boolean = false): String {
var result = renderType(this)
- if ((shouldRenderAsPrettyFunctionType(this) && !TypeUtils.isNullableType(this)) || this is DefinitelyNotNullType) {
+ if ((shouldRenderAsPrettyFunctionType(this) && !TypeUtils.isNullableType(this)) || this is DefinitelyNotNullType || wrapAnnotated && !this.annotations.isEmpty()) {
result = "($result)"
}
return result
@@ -776,8 +776,8 @@
return
}
for ((i, contextReceiver) in contextReceivers.withIndex()) {
- builder.renderAnnotations(contextReceiver, AnnotationUseSiteTarget.RECEIVER)
- val typeString = contextReceiver.type.renderForReceiver()
+ // Context receivers have to wrap type annotation to be parsed correctly
+ val typeString = contextReceiver.type.renderForReceiver(wrapAnnotated = true)
builder.append(typeString)
if (i == contextReceivers.lastIndex) {
builder.append(") ")