Add new "invent name" phase to generate names for regenerated classes
This commit is contained in:
+36
-5
@@ -6,19 +6,25 @@
|
||||
package org.jetbrains.kotlin.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.ir.getAdditionalStatementsFromInlinedBlock
|
||||
import org.jetbrains.kotlin.backend.common.ir.getNonDefaultAdditionalStatementsFromInlinedBlock
|
||||
import org.jetbrains.kotlin.backend.common.ir.getOriginalStatementsFromInlinedBlock
|
||||
import org.jetbrains.kotlin.backend.common.ir.isFunctionInlining
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.util.isAnonymousObject
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toUpperCaseAsciiOnly
|
||||
import kotlin.collections.set
|
||||
|
||||
abstract class InventNamesForLocalClasses(private val allowTopLevelCallables: Boolean) : FileLoweringPass {
|
||||
abstract class InventNamesForLocalClasses(
|
||||
private val allowTopLevelCallables: Boolean,
|
||||
private val generateNamesForRegeneratedObjects: Boolean = false
|
||||
) : FileLoweringPass {
|
||||
|
||||
protected abstract fun computeTopLevelClassName(clazz: IrClass): String
|
||||
protected abstract fun sanitizeNameIfNeeded(name: String): String
|
||||
@@ -33,7 +39,7 @@ abstract class InventNamesForLocalClasses(private val allowTopLevelCallables: Bo
|
||||
* @property enclosingName internal name of the enclosing class (including anonymous classes, local objects and callable references)
|
||||
* @property isLocal true if the next declaration to be encountered in the IR tree is local
|
||||
*/
|
||||
private data class Data(val enclosingName: String?, val isLocal: Boolean) {
|
||||
private data class Data(val enclosingName: String?, val isLocal: Boolean, val processingInlinedFunction: Boolean = false) {
|
||||
fun makeLocal(): Data = if (isLocal) this else copy(isLocal = true)
|
||||
}
|
||||
|
||||
@@ -41,6 +47,25 @@ abstract class InventNamesForLocalClasses(private val allowTopLevelCallables: Bo
|
||||
private val anonymousClassesCount = mutableMapOf<String, Int>()
|
||||
private val localFunctionNames = mutableMapOf<IrFunctionSymbol, String>()
|
||||
|
||||
override fun visitContainerExpression(expression: IrContainerExpression, data: Data) {
|
||||
if (expression is IrInlinedFunctionBlock && !generateNamesForRegeneratedObjects) {
|
||||
return expression.getNonDefaultAdditionalStatementsFromInlinedBlock().forEach { it.accept(this, data) }
|
||||
}
|
||||
|
||||
if (!data.processingInlinedFunction && expression is IrInlinedFunctionBlock && expression.isFunctionInlining()) {
|
||||
expression.getAdditionalStatementsFromInlinedBlock().forEach { it.accept(this, data) }
|
||||
|
||||
val inlinedAt = expression.inlineCall.symbol.owner.name.asString()
|
||||
val newData = data.copy(
|
||||
enclosingName = data.enclosingName + "$\$inlined\$$inlinedAt", isLocal = true, processingInlinedFunction = true
|
||||
)
|
||||
expression.getOriginalStatementsFromInlinedBlock().forEach { it.accept(this, newData) }
|
||||
|
||||
return
|
||||
}
|
||||
super.visitContainerExpression(expression, data)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass, data: Data) {
|
||||
if (!data.isLocal) {
|
||||
// This is not a local class, so we need not invent a name for it, the type mapper will correctly compute it
|
||||
@@ -99,6 +124,8 @@ abstract class InventNamesForLocalClasses(private val allowTopLevelCallables: Bo
|
||||
localFunctionNames[declaration.symbol] = name
|
||||
}
|
||||
}
|
||||
|
||||
declaration is IrVariable && generateNamesForRegeneratedObjects || data.processingInlinedFunction -> enclosingName
|
||||
enclosingName != null -> "$enclosingName$$simpleName"
|
||||
else -> simpleName
|
||||
}
|
||||
@@ -115,6 +142,10 @@ abstract class InventNamesForLocalClasses(private val allowTopLevelCallables: Bo
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference, data: Data) {
|
||||
if (data.processingInlinedFunction && expression.attributeOwnerIdBeforeInline == null) {
|
||||
// skip IrFunctionReference from `singleArgumentInlineFunction`
|
||||
return
|
||||
}
|
||||
val internalName = localFunctionNames[expression.symbol] ?: inventName(null, data)
|
||||
putLocalClassName(expression, internalName)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user