[IR] Add a kdoc for IrValueParameter.isHidden

This commit is contained in:
Sergej Jaskiewicz
2023-05-23 11:50:24 +02:00
committed by Space Team
parent 9a77632f1c
commit 2fc5316c1b
7 changed files with 78 additions and 11 deletions
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
@@ -35,6 +36,36 @@ abstract class IrValueParameter : IrDeclarationBase(), IrValueDeclaration {
abstract var isNoinline: Boolean abstract var isNoinline: Boolean
/**
* If `true`, the value parameter does not participate in [IdSignature] computation.
*
* This is a workaround that is needed for better support of compiler plugins.
* Suppose you have the following code and some IR plugin that adds a value parameter to
* functions
* marked with the `@PluginMarker` annotation.
* ```kotlin
* @PluginMarker
* fun foo(defined: Int) { /* ... */ }
* ```
*
* Suppose that after applying the plugin the function is changed to:
* ```kotlin
* @PluginMarker
* fun foo(defined: Int, $extra: String) { /* ... */ }
* ```
*
* If a compiler plugin adds parameters to an [IrFunction],
* the representations of the function in the frontend and in the backend may diverge,
* potentially causing signature mismatch and
* linkage errors (see [KT-40980](https://youtrack.jetbrains.com/issue/KT-40980)).
* We wouldn't want IR plugins to affect the frontend representation, since in an IDE you'd want
* to be able to see those
* declarations in their original form (without the `$extra` parameter).
*
* To fix this problem, [isHidden] was introduced.
*
* TODO: consider dropping [isHidden] if it isn't used by any known plugin.
*/
abstract var isHidden: Boolean abstract var isHidden: Boolean
abstract var defaultValue: IrExpressionBody? abstract var defaultValue: IrExpressionBody?
@@ -5,10 +5,7 @@
package org.jetbrains.kotlin.ir.generator package org.jetbrains.kotlin.ir.generator
import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.*
import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.MemberName
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.descriptors.SourceElement
@@ -23,6 +20,7 @@ import org.jetbrains.kotlin.ir.generator.config.SimpleFieldConfig
import org.jetbrains.kotlin.ir.generator.model.Element.Companion.elementName2typeName import org.jetbrains.kotlin.ir.generator.model.Element.Companion.elementName2typeName
import org.jetbrains.kotlin.ir.generator.print.toPoet import org.jetbrains.kotlin.ir.generator.print.toPoet
import org.jetbrains.kotlin.ir.generator.util.* import org.jetbrains.kotlin.ir.generator.util.*
import org.jetbrains.kotlin.ir.generator.util.Import
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
@@ -165,11 +163,36 @@ object IrTree : AbstractTreeBuilder() {
+field("varargElementType", irTypeType, nullable = true) +field("varargElementType", irTypeType, nullable = true)
+field("isCrossinline", boolean) +field("isCrossinline", boolean)
+field("isNoinline", boolean) +field("isNoinline", boolean)
// if true parameter is not included into IdSignature. +field("isHidden", boolean) {
// Skipping hidden params makes IrFunction be look similar to FE. additionalImports.add(Import("org.jetbrains.kotlin.ir.util", "IdSignature"))
// NOTE: it is introduced to fix KT-40980 because more clear solution was not possible to implement. kdoc = """
// Once we are able to load any top-level declaration from klib this hack should be deprecated and removed. If `true`, the value parameter does not participate in [IdSignature] computation.
+field("isHidden", boolean)
This is a workaround that is needed for better support of compiler plugins.
Suppose you have the following code and some IR plugin that adds a value parameter to functions
marked with the `@PluginMarker` annotation.
```kotlin
@PluginMarker
fun foo(defined: Int) { /* ... */ }
```
Suppose that after applying the plugin the function is changed to:
```kotlin
@PluginMarker
fun foo(defined: Int, ${'$'}extra: String) { /* ... */ }
```
If a compiler plugin adds parameters to an [${elementName2typeName(function.name)}],
the representations of the function in the frontend and in the backend may diverge, potentially causing signature mismatch and
linkage errors (see [KT-40980](https://youtrack.jetbrains.com/issue/KT-40980)).
We wouldn't want IR plugins to affect the frontend representation, since in an IDE you'd want to be able to see those
declarations in their original form (without the `${'$'}extra` parameter).
To fix this problem, [$name] was introduced.
TODO: consider dropping [$name] if it isn't used by any known plugin.
""".trimIndent()
}
+field("defaultValue", expressionBody, nullable = true, isChild = true) +field("defaultValue", expressionBody, nullable = true, isChild = true)
} }
val `class`: ElementConfig by element(Declaration) { val `class`: ElementConfig by element(Declaration) {
@@ -24,6 +24,7 @@ class ElementConfig(
val params = mutableListOf<TypeVariable>() val params = mutableListOf<TypeVariable>()
val parents = mutableListOf<TypeRef>() val parents = mutableListOf<TypeRef>()
val fields = mutableListOf<FieldConfig>() val fields = mutableListOf<FieldConfig>()
val additionalImports = mutableListOf<Import>()
var visitorName: String? = null var visitorName: String? = null
var visitorParent: ElementConfig? = null var visitorParent: ElementConfig? = null
@@ -43,6 +43,7 @@ class Element(
val suppressPrint = config.suppressPrint val suppressPrint = config.suppressPrint
val propertyName = config.propertyName val propertyName = config.propertyName
val kDoc = config.kDoc val kDoc = config.kDoc
val additionalImports: List<Import> = config.additionalImports
override fun toString() = name override fun toString() = name
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.generator.print
import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.TypeSpec import com.squareup.kotlinpoet.TypeSpec
import org.jetbrains.kotlin.ir.generator.util.GeneratedFile import org.jetbrains.kotlin.ir.generator.util.GeneratedFile
import org.jetbrains.kotlin.ir.generator.util.Import
import java.io.File import java.io.File
private val COPYRIGHT by lazy { File("license/COPYRIGHT_HEADER.txt").readText() } private val COPYRIGHT by lazy { File("license/COPYRIGHT_HEADER.txt").readText() }
@@ -17,8 +18,16 @@ private val GENERATED_MESSAGE = """
""".trimIndent() """.trimIndent()
private val PREFIX by lazy { "$COPYRIGHT\n\n$GENERATED_MESSAGE\n\n" } private val PREFIX by lazy { "$COPYRIGHT\n\n$GENERATED_MESSAGE\n\n" }
fun printTypeCommon(generationPath: File, packageName: String, type: TypeSpec): GeneratedFile { fun printTypeCommon(
generationPath: File,
packageName: String,
type: TypeSpec,
additionalImports: List<Import> = emptyList(),
): GeneratedFile {
val code = FileSpec.builder(packageName, type.name!!) val code = FileSpec.builder(packageName, type.name!!)
.apply {
additionalImports.forEach { addImport(it.packageName, it.className) }
}
.indent(" ") .indent(" ")
.addType(type) .addType(type)
.build() .build()
@@ -266,7 +266,7 @@ fun printElements(generationPath: File, model: Model) = sequence {
element.generationCallback?.invoke(this) element.generationCallback?.invoke(this)
}.build() }.build()
yield(printTypeCommon(generationPath, elementName.packageName, elementType)) yield(printTypeCommon(generationPath, elementName.packageName, elementType, element.additionalImports))
} }
} }
@@ -14,6 +14,8 @@ import java.io.File
class GeneratedFile(val file: File, val newText: String) class GeneratedFile(val file: File, val newText: String)
class Import(val packageName: String, val className: String)
fun ClassName.parameterizedByIfAny(typeArguments: List<TypeName>) = fun ClassName.parameterizedByIfAny(typeArguments: List<TypeName>) =
if (typeArguments.isNotEmpty()) parameterizedBy(typeArguments) else this if (typeArguments.isNotEmpty()) parameterizedBy(typeArguments) else this