[IR generator] Don't use kotlinpoet for auto-generating IrFactory
KT-61970
This commit is contained in:
committed by
Space Team
parent
ebe0a84dee
commit
a84277782a
@@ -8,26 +8,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.declarations
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||
import org.jetbrains.kotlin.ir.symbols.IrAnonymousInitializerSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrLocalDelegatedPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeAliasSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
@@ -362,10 +348,7 @@ interface IrFactory {
|
||||
" This variant of the method will be removed when the 2024.2 IntelliJ platform is shipped (see KTIJ-26314).",
|
||||
level = DeprecationLevel.HIDDEN,
|
||||
)
|
||||
fun createExpressionBody(expression: IrExpression): IrExpressionBody =
|
||||
createExpressionBody(
|
||||
expression,
|
||||
)
|
||||
fun createExpressionBody(expression: IrExpression): IrExpressionBody = createExpressionBody(expression)
|
||||
|
||||
@Deprecated(
|
||||
message = "The method's parameters were reordered." +
|
||||
|
||||
+2
@@ -32,6 +32,8 @@ val elementTransformerType = type(visitors, "IrElementTransformer")
|
||||
val typeTransformerType = type(visitors, "IrTypeTransformer")
|
||||
val mutableAnnotationContainerType = type(declarations, "IrMutableAnnotationContainer")
|
||||
val irTypeType = type(types, "IrType")
|
||||
val irFactoryType = type(declarations, "IrFactory")
|
||||
val stageControllerType = type(declarations, "StageController", TypeKind.Class)
|
||||
|
||||
val symbolType = type(symbols, "IrSymbol")
|
||||
val packageFragmentSymbolType = type(symbols, "IrPackageFragmentSymbol")
|
||||
|
||||
+16
-22
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.ir.generator.config.ListFieldConfig.Mutability.List
|
||||
import org.jetbrains.kotlin.ir.generator.config.ListFieldConfig.Mutability.Var
|
||||
import org.jetbrains.kotlin.ir.generator.config.SimpleFieldConfig
|
||||
import org.jetbrains.kotlin.ir.generator.model.Element.Companion.elementName2typeName
|
||||
import org.jetbrains.kotlin.ir.generator.print.IR_FACTORY_TYPE
|
||||
import org.jetbrains.kotlin.ir.generator.print.toPoet
|
||||
import org.jetbrains.kotlin.ir.generator.util.*
|
||||
import org.jetbrains.kotlin.ir.generator.util.Import
|
||||
@@ -69,7 +68,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
}
|
||||
}
|
||||
|
||||
private val factory: SimpleFieldConfig = field("factory", IR_FACTORY_TYPE, mutable = false) {
|
||||
private val factory: SimpleFieldConfig = field("factory", irFactoryType, mutable = false) {
|
||||
skipInIrFactory()
|
||||
}
|
||||
|
||||
@@ -132,7 +131,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
parent(declarationWithName)
|
||||
|
||||
+field("isExternal", boolean) {
|
||||
useFieldInIrFactory(false)
|
||||
useFieldInIrFactory(defaultValue = "false")
|
||||
}
|
||||
}
|
||||
val symbolOwner: ElementConfig by element(Declaration) {
|
||||
@@ -183,7 +182,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
parent(declarationWithName)
|
||||
|
||||
+field("containerSource", type<DeserializedContainerSource>(), nullable = true, mutable = false) {
|
||||
useFieldInIrFactory(defaultValue = code("null"))
|
||||
useFieldInIrFactory(defaultValue = "null")
|
||||
}
|
||||
}
|
||||
val valueDeclaration: ElementConfig by element(Declaration) {
|
||||
@@ -256,25 +255,25 @@ object IrTree : AbstractTreeBuilder() {
|
||||
+field("kind", type<ClassKind>())
|
||||
+field("modality", type<Modality>())
|
||||
+field("isCompanion", boolean) {
|
||||
useFieldInIrFactory(defaultValue = false)
|
||||
useFieldInIrFactory(defaultValue = "false")
|
||||
}
|
||||
+field("isInner", boolean) {
|
||||
useFieldInIrFactory(defaultValue = false)
|
||||
useFieldInIrFactory(defaultValue = "false")
|
||||
}
|
||||
+field("isData", boolean) {
|
||||
useFieldInIrFactory(defaultValue = false)
|
||||
useFieldInIrFactory(defaultValue = "false")
|
||||
}
|
||||
+field("isValue", boolean) {
|
||||
useFieldInIrFactory(defaultValue = false)
|
||||
useFieldInIrFactory(defaultValue = "false")
|
||||
}
|
||||
+field("isExpect", boolean) {
|
||||
useFieldInIrFactory(defaultValue = false)
|
||||
useFieldInIrFactory(defaultValue = "false")
|
||||
}
|
||||
+field("isFun", boolean) {
|
||||
useFieldInIrFactory(defaultValue = false)
|
||||
useFieldInIrFactory(defaultValue = "false")
|
||||
}
|
||||
+field("hasEnumEntries", boolean) {
|
||||
useFieldInIrFactory(defaultValue = false)
|
||||
useFieldInIrFactory(defaultValue = "false")
|
||||
kDoc = """
|
||||
Returns true iff this is a class loaded from dependencies which has the `HAS_ENUM_ENTRIES` metadata flag set.
|
||||
This flag is useful for Kotlin/JVM to determine whether an enum class from dependency actually has the `entries` property
|
||||
@@ -283,7 +282,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
""".trimIndent()
|
||||
}
|
||||
+field("source", type<SourceElement>(), mutable = false) {
|
||||
useFieldInIrFactory(defaultValue = code("%T.NO_SOURCE", SourceElement::class))
|
||||
useFieldInIrFactory(defaultValue = "SourceElement.NO_SOURCE")
|
||||
}
|
||||
+listField("superTypes", irTypeType, mutability = Var) {
|
||||
skipInIrFactory()
|
||||
@@ -334,7 +333,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
+descriptor("ClassDescriptor") // TODO special descriptor for anonymous initializer blocks
|
||||
+symbol(anonymousInitializerSymbolType)
|
||||
+field("isStatic", boolean) {
|
||||
useFieldInIrFactory(defaultValue = false)
|
||||
useFieldInIrFactory(defaultValue = "false")
|
||||
}
|
||||
+field("body", blockBody, isChild = true)
|
||||
}
|
||||
@@ -440,7 +439,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
|
||||
additionalIrFactoryMethodParameters.add(
|
||||
descriptor("DeclarationDescriptor", nullable = true).apply {
|
||||
useFieldInIrFactory(defaultValue = code("null"))
|
||||
useFieldInIrFactory(defaultValue = "null")
|
||||
}
|
||||
)
|
||||
|
||||
@@ -528,7 +527,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
+field("isLateinit", boolean)
|
||||
+field("isDelegated", boolean)
|
||||
+field("isExpect", boolean) {
|
||||
useFieldInIrFactory(defaultValue = false)
|
||||
useFieldInIrFactory(defaultValue = "false")
|
||||
}
|
||||
+isFakeOverrideField()
|
||||
+field("backingField", field, nullable = true, isChild = true)
|
||||
@@ -537,12 +536,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
}
|
||||
|
||||
private fun isFakeOverrideField() = field("isFakeOverride", boolean) {
|
||||
useFieldInIrFactory(
|
||||
defaultValue = code(
|
||||
"origin == %T.FAKE_OVERRIDE",
|
||||
type(Packages.declarations, "IrDeclarationOrigin").toPoet(),
|
||||
),
|
||||
)
|
||||
useFieldInIrFactory(defaultValue = "origin == IrDeclarationOrigin.FAKE_OVERRIDE")
|
||||
}
|
||||
|
||||
//TODO: make IrScript as IrPackageFragment, because script is used as a file, not as a class
|
||||
@@ -827,7 +821,7 @@ object IrTree : AbstractTreeBuilder() {
|
||||
|
||||
+symbol(constructorSymbolType, mutable = true)
|
||||
+field("source", type<SourceElement>()) {
|
||||
useFieldInIrFactory(defaultValue = code("%T.NO_SOURCE", SourceElement::class))
|
||||
useFieldInIrFactory(defaultValue = "SourceElement.NO_SOURCE")
|
||||
}
|
||||
+field("constructorTypeArgumentsCount", int)
|
||||
}
|
||||
|
||||
+26
-9
@@ -10,6 +10,7 @@ import com.squareup.kotlinpoet.PropertySpec
|
||||
import com.squareup.kotlinpoet.TypeSpec
|
||||
import org.jetbrains.kotlin.generators.tree.*
|
||||
import org.jetbrains.kotlin.ir.generator.BASE_PACKAGE
|
||||
import org.jetbrains.kotlin.ir.generator.model.Element
|
||||
import org.jetbrains.kotlin.ir.generator.util.*
|
||||
|
||||
class Config(
|
||||
@@ -73,9 +74,19 @@ class ElementConfig(
|
||||
|
||||
override fun toString() = element.name
|
||||
|
||||
override val packageName: String
|
||||
get() = category.packageName
|
||||
|
||||
override val typeName: String
|
||||
get() = Element.elementName2typeName(name)
|
||||
|
||||
context(ImportCollector)
|
||||
override fun renderTo(appendable: Appendable) {
|
||||
renderingIsNotSupported()
|
||||
addImport(this)
|
||||
appendable.append(typeName)
|
||||
if (params.isNotEmpty()) {
|
||||
params.joinTo(appendable, prefix = "<", postfix = ">") { it.name }
|
||||
}
|
||||
}
|
||||
|
||||
enum class Category(private val packageDir: String, val defaultVisitorParam: String) {
|
||||
@@ -87,7 +98,7 @@ class ElementConfig(
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface ElementConfigOrRef : ParametrizedTypeRef<ElementConfigOrRef, NamedTypeParameterRef>, TypeRefWithNullability {
|
||||
sealed interface ElementConfigOrRef : ParametrizedTypeRef<ElementConfigOrRef, NamedTypeParameterRef>, TypeRefWithNullability, Importable {
|
||||
val element: ElementConfig
|
||||
}
|
||||
|
||||
@@ -96,6 +107,13 @@ class ElementConfigRef(
|
||||
override val args: Map<NamedTypeParameterRef, TypeRef>,
|
||||
override val nullable: Boolean
|
||||
) : ElementConfigOrRef {
|
||||
|
||||
override val packageName: String
|
||||
get() = element.packageName
|
||||
|
||||
override val typeName: String
|
||||
get() = element.typeName
|
||||
|
||||
override fun copy(args: Map<NamedTypeParameterRef, TypeRef>) = ElementConfigRef(element, args, nullable)
|
||||
override fun copy(nullable: Boolean) = ElementConfigRef(element, args, nullable)
|
||||
|
||||
@@ -103,7 +121,10 @@ class ElementConfigRef(
|
||||
|
||||
context(ImportCollector)
|
||||
override fun renderTo(appendable: Appendable) {
|
||||
renderingIsNotSupported()
|
||||
addImport(element)
|
||||
appendable.append(element.typeName)
|
||||
renderArgsTo(appendable)
|
||||
renderNullabilityTo(appendable)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +132,7 @@ sealed class UseFieldAsParameterInIrFactoryStrategy {
|
||||
|
||||
data object No : UseFieldAsParameterInIrFactoryStrategy()
|
||||
|
||||
data class Yes(val defaultValue: CodeBlock?) : UseFieldAsParameterInIrFactoryStrategy()
|
||||
data class Yes(val defaultValue: String?) : UseFieldAsParameterInIrFactoryStrategy()
|
||||
}
|
||||
|
||||
sealed class FieldConfig(
|
||||
@@ -126,14 +147,10 @@ sealed class FieldConfig(
|
||||
internal var useFieldInIrFactoryStrategy: UseFieldAsParameterInIrFactoryStrategy =
|
||||
if (isChild) UseFieldAsParameterInIrFactoryStrategy.No else UseFieldAsParameterInIrFactoryStrategy.Yes(null)
|
||||
|
||||
fun useFieldInIrFactory(defaultValue: CodeBlock? = null) {
|
||||
fun useFieldInIrFactory(defaultValue: String? = null) {
|
||||
useFieldInIrFactoryStrategy = UseFieldAsParameterInIrFactoryStrategy.Yes(defaultValue)
|
||||
}
|
||||
|
||||
fun useFieldInIrFactory(defaultValue: Boolean) {
|
||||
useFieldInIrFactoryStrategy = UseFieldAsParameterInIrFactoryStrategy.Yes(code("%L", defaultValue))
|
||||
}
|
||||
|
||||
fun skipInIrFactory() {
|
||||
useFieldInIrFactoryStrategy = UseFieldAsParameterInIrFactoryStrategy.No
|
||||
}
|
||||
|
||||
+112
-112
@@ -5,66 +5,48 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.generator.print
|
||||
|
||||
import com.squareup.kotlinpoet.*
|
||||
import org.jetbrains.kotlin.generators.tree.*
|
||||
import org.jetbrains.kotlin.generators.tree.printer.FunctionParameter
|
||||
import org.jetbrains.kotlin.generators.tree.printer.GeneratedFile
|
||||
import org.jetbrains.kotlin.generators.tree.type
|
||||
import org.jetbrains.kotlin.generators.tree.printer.printFunctionDeclaration
|
||||
import org.jetbrains.kotlin.generators.tree.printer.printGeneratedType
|
||||
import org.jetbrains.kotlin.ir.generator.IrTree
|
||||
import org.jetbrains.kotlin.ir.generator.Packages
|
||||
import org.jetbrains.kotlin.ir.generator.config.UseFieldAsParameterInIrFactoryStrategy
|
||||
import org.jetbrains.kotlin.ir.generator.irFactoryType
|
||||
import org.jetbrains.kotlin.ir.generator.model.Element
|
||||
import org.jetbrains.kotlin.ir.generator.model.Model
|
||||
import org.jetbrains.kotlin.ir.generator.util.parameterizedByIfAny
|
||||
import org.jetbrains.kotlin.ir.generator.util.tryParameterizedBy
|
||||
import org.jetbrains.kotlin.ir.generator.stageControllerType
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
|
||||
import org.jetbrains.kotlin.utils.SmartPrinter
|
||||
import org.jetbrains.kotlin.utils.withIndent
|
||||
import java.io.File
|
||||
|
||||
internal val IR_FACTORY_TYPE = type(Packages.declarations, "IrFactory")
|
||||
|
||||
@Suppress("DuplicatedCode")
|
||||
internal fun printFactory(generationPath: File, model: Model): GeneratedFile {
|
||||
val visitorType = TypeSpec.interfaceBuilder(IR_FACTORY_TYPE.toPoet() as ClassName).apply {
|
||||
addProperty("stageController", ClassName(Packages.declarations, "StageController"))
|
||||
model.elements
|
||||
internal fun printFactory(generationPath: File, model: Model): GeneratedFile = printGeneratedType(
|
||||
generationPath,
|
||||
TREE_GENERATOR_README,
|
||||
irFactoryType.packageName,
|
||||
irFactoryType.simpleName,
|
||||
) {
|
||||
println()
|
||||
println("interface ", irFactoryType.simpleName, " {")
|
||||
withIndent {
|
||||
println("val stageController: ", stageControllerType.render())
|
||||
val factoryMethods = model.elements
|
||||
.filter { it.isLeaf && it.generateIrFactoryMethod }
|
||||
.sortedWith(compareBy({ it.packageName }, { it.name }))
|
||||
.forEach { element ->
|
||||
val typeParams = element.params.map { it.toPoet() }
|
||||
addFunction(
|
||||
FunSpec.builder("create${element.name.capitalizeAsciiOnly()}")
|
||||
.addTypeVariables(typeParams)
|
||||
.apply {
|
||||
val fields = (element.allFieldsRecursively() + element.additionalFactoryMethodParameters)
|
||||
.filterNot { it.name in element.fieldsToSkipInIrFactoryMethod }
|
||||
.mapNotNull { field ->
|
||||
(field.useInIrFactoryStrategy as? UseFieldAsParameterInIrFactoryStrategy.Yes)?.let {
|
||||
field to it.defaultValue
|
||||
}
|
||||
}
|
||||
.sortedBy { (_, defaultValue) -> defaultValue != null } // All parameters with default values must go last
|
||||
fields.forEach { (field, defaultValue) ->
|
||||
addParameter(
|
||||
ParameterSpec.builder(field.name, field.typeRef.toPoet().copy(nullable = field.nullable))
|
||||
.defaultValue(defaultValue)
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
}
|
||||
.returns(element.toPoet().parameterizedByIfAny(typeParams))
|
||||
.addModifiers(KModifier.ABSTRACT)
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
.map(::FactoryMethod)
|
||||
|
||||
fun replacement(name: String) = funSpecs.find { it.name == name } ?: error("Method '$name' not found")
|
||||
factoryMethods.forEach { printFactoryMethod(it) }
|
||||
|
||||
fun replacement(name: String) = factoryMethods.find { it.name == name } ?: error("Method '$name' not found")
|
||||
|
||||
addDeprecatedFunction(
|
||||
replacement("createBlockBody")
|
||||
.toBuilder()
|
||||
.addParameter(
|
||||
"initializer",
|
||||
LambdaTypeName.get(receiver = IrTree.blockBody.toPoet(), returnType = UNIT)
|
||||
)
|
||||
.build()
|
||||
Lambda(receiver = IrTree.blockBody, returnType = StandardTypes.unit),
|
||||
),
|
||||
) {
|
||||
deprecationMessage = "This method was moved to an extension."
|
||||
parameter("startOffset")
|
||||
@@ -74,12 +56,10 @@ internal fun printFactory(generationPath: File, model: Model): GeneratedFile {
|
||||
|
||||
addDeprecatedFunction(
|
||||
replacement("createBlockBody")
|
||||
.toBuilder()
|
||||
.addParameter(
|
||||
"statements",
|
||||
LIST.tryParameterizedBy(IrTree.statement.toPoet())
|
||||
)
|
||||
.build()
|
||||
StandardTypes.list.withArgs(IrTree.statement),
|
||||
),
|
||||
) {
|
||||
deprecationMessage = "This method was moved to an extension."
|
||||
parameter("startOffset")
|
||||
@@ -104,7 +84,7 @@ internal fun printFactory(generationPath: File, model: Model): GeneratedFile {
|
||||
parameter("isExpect")
|
||||
parameter("isFun")
|
||||
parameter("source")
|
||||
defaultValue["hasEnumEntries"] = false
|
||||
defaultValue["hasEnumEntries"] = "false"
|
||||
}
|
||||
|
||||
addDeprecatedFunction(replacement("createConstructor")) {
|
||||
@@ -149,7 +129,7 @@ internal fun printFactory(generationPath: File, model: Model): GeneratedFile {
|
||||
}
|
||||
|
||||
addDeprecatedFunction(replacement("createFunctionWithLateBinding")) {
|
||||
returnType = IrTree.simpleFunction.toPoet()
|
||||
returnType = IrTree.simpleFunction
|
||||
parameter("startOffset")
|
||||
parameter("endOffset")
|
||||
parameter("origin")
|
||||
@@ -195,7 +175,7 @@ internal fun printFactory(generationPath: File, model: Model): GeneratedFile {
|
||||
}
|
||||
|
||||
addDeprecatedFunction(replacement("createPropertyWithLateBinding")) {
|
||||
returnType = IrTree.property.toPoet()
|
||||
returnType = IrTree.property
|
||||
parameter("startOffset")
|
||||
parameter("endOffset")
|
||||
parameter("origin")
|
||||
@@ -267,37 +247,64 @@ internal fun printFactory(generationPath: File, model: Model): GeneratedFile {
|
||||
parameter("isHidden")
|
||||
parameter("isAssignable")
|
||||
}
|
||||
}.build()
|
||||
|
||||
return printTypeCommon(generationPath, IR_FACTORY_TYPE.packageName, visitorType)
|
||||
}
|
||||
println("}")
|
||||
}
|
||||
|
||||
private class DeprecatedFunctionBuilder(private val replacement: FunSpec) {
|
||||
val deprecatedFunctionParameterSpecs = mutableListOf<ParameterSpec>()
|
||||
private class FactoryMethod(val element: Element) {
|
||||
|
||||
val name = "create" + element.name.capitalizeAsciiOnly()
|
||||
|
||||
val parameters = (element.allFieldsRecursively() + element.additionalFactoryMethodParameters)
|
||||
.filterNot { it.name in element.fieldsToSkipInIrFactoryMethod }
|
||||
.mapNotNull { field ->
|
||||
(field.useInIrFactoryStrategy as? UseFieldAsParameterInIrFactoryStrategy.Yes)?.let {
|
||||
FunctionParameter(field.name, field.typeRef, it.defaultValue)
|
||||
}
|
||||
}
|
||||
.sortedBy { it.defaultValue != null } // All parameters with default values must go last
|
||||
.toMutableList()
|
||||
|
||||
fun addParameter(name: String, type: TypeRef): FactoryMethod {
|
||||
parameters.add(FunctionParameter(name, type))
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
private const val MAX_FUNCTION_PARAMETERS_ON_ONE_LINE = 2
|
||||
|
||||
context(ImportCollector)
|
||||
private fun SmartPrinter.printFactoryMethod(factoryMethod: FactoryMethod) {
|
||||
println()
|
||||
printFunctionDeclaration(
|
||||
name = factoryMethod.name,
|
||||
parameters = factoryMethod.parameters,
|
||||
returnType = factoryMethod.element,
|
||||
typeParameters = factoryMethod.element.params,
|
||||
allParametersOnSeparateLines = factoryMethod.parameters.size > MAX_FUNCTION_PARAMETERS_ON_ONE_LINE,
|
||||
)
|
||||
println()
|
||||
}
|
||||
|
||||
private class DeprecatedFunctionBuilder(private val replacement: FactoryMethod) {
|
||||
val deprecatedFunctionParameters = mutableListOf<FunctionParameter>()
|
||||
var oldName = replacement.name
|
||||
var returnType = replacement.returnType
|
||||
var returnType: TypeRef = replacement.element
|
||||
var deprecationMessage: String? = null
|
||||
val defaultValue = mutableMapOf<String, Any?>()
|
||||
val defaultValue = mutableMapOf<String, String>()
|
||||
|
||||
fun parameter(name: String, removeDefaultValue: Boolean = false) {
|
||||
val replacementParameter =
|
||||
replacement.parameters.find { it.name == name } ?: error("Parameter '$name' not found in $replacement")
|
||||
deprecatedFunctionParameterSpecs.add(
|
||||
replacementParameter
|
||||
.toBuilder()
|
||||
.applyIf(removeDefaultValue) {
|
||||
defaultValue(null)
|
||||
}
|
||||
.build()
|
||||
)
|
||||
deprecatedFunctionParameters.add(if (removeDefaultValue) replacementParameter.copy(defaultValue = null) else replacementParameter)
|
||||
}
|
||||
}
|
||||
|
||||
private fun TypeSpec.Builder.addDeprecatedFunction(
|
||||
replacement: FunSpec,
|
||||
context(ImportCollector)
|
||||
private fun SmartPrinter.addDeprecatedFunction(
|
||||
replacement: FactoryMethod,
|
||||
build: DeprecatedFunctionBuilder.() -> Unit
|
||||
): TypeSpec.Builder {
|
||||
|
||||
) {
|
||||
val builder = DeprecatedFunctionBuilder(replacement)
|
||||
builder.build()
|
||||
|
||||
@@ -307,46 +314,39 @@ private fun TypeSpec.Builder.addDeprecatedFunction(
|
||||
"The method's parameters were reordered."
|
||||
}
|
||||
|
||||
return addFunction(
|
||||
FunSpec.builder(builder.oldName)
|
||||
.addTypeVariables(replacement.typeVariables)
|
||||
.addCode(
|
||||
CodeBlock.builder()
|
||||
.add("return ")
|
||||
.add("%N(\n", replacement)
|
||||
.apply {
|
||||
for (parameter in replacement.parameters) {
|
||||
if (builder.deprecatedFunctionParameterSpecs.any { it.name == parameter.name }) {
|
||||
indent()
|
||||
add("%N,\n", parameter)
|
||||
unindent()
|
||||
} else {
|
||||
val value = builder.defaultValue[parameter.name]
|
||||
if (value != null) {
|
||||
indent()
|
||||
add("$value,\n")
|
||||
unindent()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.add(")")
|
||||
.build()
|
||||
)
|
||||
.addAnnotation(
|
||||
AnnotationSpec.builder(Deprecated::class)
|
||||
.addMember(
|
||||
"message = %S + %S",
|
||||
message,
|
||||
" This variant of the method will be removed when the 2024.2 IntelliJ platform is shipped (see KTIJ-26314).",
|
||||
)
|
||||
.addMember("level = %T.%N", DeprecationLevel::class, DeprecationLevel.HIDDEN.name)
|
||||
.build(),
|
||||
)
|
||||
.addParameters(builder.deprecatedFunctionParameterSpecs)
|
||||
.apply {
|
||||
builder.returnType?.let { returns(it) }
|
||||
}
|
||||
.build(),
|
||||
println()
|
||||
println("@Deprecated(")
|
||||
withIndent {
|
||||
println("message = \"", message, "\" +")
|
||||
println(" \" This variant of the method will be removed when the 2024.2 IntelliJ platform is shipped (see KTIJ-26314).\",")
|
||||
println("level = DeprecationLevel.HIDDEN,")
|
||||
}
|
||||
println(")")
|
||||
val allParametersOnSeparateLines = builder.deprecatedFunctionParameters.size > MAX_FUNCTION_PARAMETERS_ON_ONE_LINE
|
||||
printFunctionDeclaration(
|
||||
name = builder.oldName,
|
||||
parameters = builder.deprecatedFunctionParameters,
|
||||
returnType = builder.returnType,
|
||||
typeParameters = replacement.element.params,
|
||||
allParametersOnSeparateLines = allParametersOnSeparateLines,
|
||||
)
|
||||
}
|
||||
print(" = ", replacement.name, "(")
|
||||
|
||||
val renderedParameters = replacement.parameters.mapNotNull { parameter ->
|
||||
if (builder.deprecatedFunctionParameters.any { it.name == parameter.name }) {
|
||||
parameter.name
|
||||
} else {
|
||||
builder.defaultValue[parameter.name]
|
||||
}
|
||||
}
|
||||
|
||||
if (allParametersOnSeparateLines) {
|
||||
println()
|
||||
withIndent {
|
||||
renderedParameters.forEach { println(it, ",") }
|
||||
}
|
||||
} else {
|
||||
print(renderedParameters.joinToString())
|
||||
}
|
||||
println(")")
|
||||
}
|
||||
|
||||
+31
-2
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.generators.tree
|
||||
|
||||
import org.jetbrains.kotlin.generators.tree.printer.braces
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.joinToWithBuffer
|
||||
import java.util.*
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@@ -168,6 +169,34 @@ data class ElementRef<Element : AbstractElement<Element, Field>, Field : Abstrac
|
||||
}
|
||||
}
|
||||
|
||||
data class Lambda(
|
||||
val receiver: TypeRefWithNullability?,
|
||||
val parameterTypes: List<TypeRefWithNullability> = emptyList(),
|
||||
val returnType: TypeRefWithNullability,
|
||||
override val nullable: Boolean = false,
|
||||
) : TypeRefWithNullability {
|
||||
override fun substitute(map: TypeParameterSubstitutionMap) =
|
||||
Lambda(
|
||||
receiver?.substitute(map) as TypeRefWithNullability?,
|
||||
parameterTypes.map { it.substitute(map) as TypeRefWithNullability },
|
||||
returnType.substitute(map) as TypeRefWithNullability,
|
||||
nullable,
|
||||
)
|
||||
|
||||
context(ImportCollector)
|
||||
override fun renderTo(appendable: Appendable) {
|
||||
if (nullable) appendable.append("(")
|
||||
receiver?.let {
|
||||
it.renderTo(appendable)
|
||||
appendable.append('.')
|
||||
}
|
||||
parameterTypes.joinToWithBuffer(appendable, prefix = "(", postfix = ") -> ") { it.renderTo(this) }
|
||||
returnType.renderTo(appendable)
|
||||
if (nullable) appendable.append(")?")
|
||||
}
|
||||
|
||||
override fun copy(nullable: Boolean) = Lambda(receiver, parameterTypes, returnType, nullable)
|
||||
}
|
||||
|
||||
sealed interface TypeParameterRef : TypeRef, TypeRefWithNullability {
|
||||
override fun substitute(map: TypeParameterSubstitutionMap): TypeRef = map[this] ?: this
|
||||
@@ -216,7 +245,7 @@ interface TypeRefWithNullability : TypeRef {
|
||||
fun copy(nullable: Boolean): TypeRefWithNullability
|
||||
}
|
||||
|
||||
private fun TypeRefWithNullability.renderNullabilityTo(appendable: Appendable) {
|
||||
fun TypeRefWithNullability.renderNullabilityTo(appendable: Appendable) {
|
||||
if (nullable) {
|
||||
appendable.append('?')
|
||||
}
|
||||
@@ -232,7 +261,7 @@ interface ParametrizedTypeRef<Self : ParametrizedTypeRef<Self, P>, P : TypeParam
|
||||
}
|
||||
|
||||
context(ImportCollector)
|
||||
private fun ParametrizedTypeRef<*, *>.renderArgsTo(appendable: Appendable) {
|
||||
fun ParametrizedTypeRef<*, *>.renderArgsTo(appendable: Appendable) {
|
||||
if (args.isNotEmpty()) {
|
||||
args.values.joinTo(appendable, prefix = "<", postfix = ">") {
|
||||
it.renderTo(appendable)
|
||||
|
||||
Reference in New Issue
Block a user