[IR] [Refactoring] Add toString and String::plus to IrBuiltins
Also use `OperatorNameConventions` constants instead of magic strings
This commit is contained in:
@@ -454,15 +454,31 @@ class IrBuiltInsOverFir(
|
||||
}
|
||||
|
||||
override val extensionToString: IrSimpleFunctionSymbol by lazy {
|
||||
findFunctions(kotlinPackage, Name.identifier("toString")).first { function ->
|
||||
findFunctions(kotlinPackage, OperatorNameConventions.TO_STRING).single { function ->
|
||||
function.owner.extensionReceiverParameter?.let { receiver -> receiver.type == anyNType } ?: false
|
||||
}
|
||||
}
|
||||
|
||||
override val stringPlus: IrSimpleFunctionSymbol
|
||||
get() = intClass.functions.single {
|
||||
it.owner.name == OperatorNameConventions.PLUS && it.owner.valueParameters[0].type == stringType
|
||||
override val memberToString: IrSimpleFunctionSymbol by lazy {
|
||||
findBuiltInClassMemberFunctions(anyClass, OperatorNameConventions.TO_STRING).single { function ->
|
||||
function.owner.valueParameters.isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
override val extensionStringPlus: IrSimpleFunctionSymbol by lazy {
|
||||
findFunctions(kotlinPackage, OperatorNameConventions.PLUS).single { function ->
|
||||
val isStringExtension =
|
||||
function.owner.extensionReceiverParameter?.let { receiver -> receiver.type == stringType.withHasQuestionMark(true) }
|
||||
?: false
|
||||
isStringExtension && function.owner.valueParameters.size == 1 && function.owner.valueParameters[0].type == anyNType
|
||||
}
|
||||
}
|
||||
|
||||
override val memberStringPlus: IrSimpleFunctionSymbol by lazy {
|
||||
findBuiltInClassMemberFunctions(stringClass, OperatorNameConventions.PLUS).single { function ->
|
||||
function.owner.valueParameters.size == 1 && function.owner.valueParameters[0].type == anyNType
|
||||
}
|
||||
}
|
||||
|
||||
private class KotlinPackageFuns(
|
||||
val arrayOf: IrSimpleFunctionSymbol,
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
class Fir2IrLazyClass(
|
||||
components: Fir2IrComponents,
|
||||
@@ -214,9 +215,9 @@ class Fir2IrLazyClass(
|
||||
private fun FirNamedFunctionSymbol.isAbstractMethodOfAny(): Boolean {
|
||||
val fir = fir
|
||||
if (fir.modality != Modality.ABSTRACT) return false
|
||||
return when (fir.name.asString()) {
|
||||
"equals" -> fir.valueParameters.singleOrNull()?.returnTypeRef?.isNullableAny == true
|
||||
"hashCode", "toString" -> fir.valueParameters.isEmpty()
|
||||
return when (fir.name) {
|
||||
OperatorNameConventions.EQUALS -> fir.valueParameters.singleOrNull()?.returnTypeRef?.isNullableAny == true
|
||||
OperatorNameConventions.HASH_CODE, OperatorNameConventions.TO_STRING -> fir.valueParameters.isEmpty()
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
object FunctionsFromAny {
|
||||
val EQUALS_METHOD_NAME = OperatorNameConventions.EQUALS
|
||||
val HASH_CODE_METHOD_NAME = Name.identifier("hashCode")
|
||||
val TO_STRING_METHOD_NAME = Name.identifier("toString")
|
||||
val HASH_CODE_METHOD_NAME = OperatorNameConventions.HASH_CODE
|
||||
val TO_STRING_METHOD_NAME = OperatorNameConventions.TO_STRING
|
||||
|
||||
fun addFunctionFromAnyIfNeeded(
|
||||
thisDescriptor: ClassDescriptor,
|
||||
|
||||
@@ -18,9 +18,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.types.defaultType
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
@@ -187,7 +185,20 @@ open class BuiltinSymbolsBase(val irBuiltIns: IrBuiltIns, private val symbolTabl
|
||||
fun kmutableproperty2(): IrClassSymbol = irBuiltIns.kMutableProperty2Class
|
||||
|
||||
val extensionToString: IrSimpleFunctionSymbol get() = irBuiltIns.extensionToString
|
||||
val stringPlus: IrSimpleFunctionSymbol get() = irBuiltIns.stringPlus
|
||||
val memberToString: IrSimpleFunctionSymbol get() = irBuiltIns.memberToString
|
||||
val extensionStringPlus: IrSimpleFunctionSymbol get() = irBuiltIns.extensionStringPlus
|
||||
val memberStringPlus: IrSimpleFunctionSymbol get() = irBuiltIns.memberStringPlus
|
||||
|
||||
fun isStringPlus(functionSymbol: IrFunctionSymbol): Boolean {
|
||||
val plusSymbol = if (functionSymbol.owner.dispatchReceiverParameter?.type?.isString() == true)
|
||||
memberStringPlus
|
||||
else if (functionSymbol.owner.extensionReceiverParameter?.type?.isNullableString() == true)
|
||||
extensionStringPlus
|
||||
else
|
||||
return false
|
||||
|
||||
return functionSymbol == plusSymbol
|
||||
}
|
||||
}
|
||||
|
||||
// Some symbols below are used in kotlin-native, so they can't be private
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import java.io.StringWriter
|
||||
|
||||
fun ir2string(ir: IrElement?): String = ir?.render() ?: ""
|
||||
@@ -399,9 +400,9 @@ fun isElseBranch(branch: IrBranch) = branch is IrElseBranch || ((branch.conditio
|
||||
|
||||
fun IrFunction.isMethodOfAny(): Boolean =
|
||||
extensionReceiverParameter == null && dispatchReceiverParameter != null &&
|
||||
when (name.asString()) {
|
||||
"hashCode", "toString" -> valueParameters.isEmpty()
|
||||
"equals" -> valueParameters.singleOrNull()?.type?.isNullableAny() == true
|
||||
when (name) {
|
||||
OperatorNameConventions.HASH_CODE, OperatorNameConventions.TO_STRING -> valueParameters.isEmpty()
|
||||
OperatorNameConventions.EQUALS -> valueParameters.singleOrNull()?.type?.isNullableAny() == true
|
||||
else -> false
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
val flattenStringConcatenationPhase = makeIrFilePhase(
|
||||
::FlattenStringConcatenationLowering,
|
||||
@@ -86,14 +87,14 @@ class FlattenStringConcatenationLowering(val context: CommonBackendContext) : Fi
|
||||
&& receiver.type.isStringClassType()
|
||||
&& function.returnType.isStringClassType()
|
||||
&& function.valueParameters.size == 1
|
||||
&& function.name.asString() == "plus"
|
||||
&& function.name == OperatorNameConventions.PLUS
|
||||
&& function.fqNameWhenAvailable?.parent() in PARENT_NAMES
|
||||
}
|
||||
|
||||
/** @return true if the function is Any.toString or an override of Any.toString */
|
||||
val IrSimpleFunction.isToString: Boolean
|
||||
get() {
|
||||
if (name.asString() != "toString" || valueParameters.size != 0 || !returnType.isString())
|
||||
if (name != OperatorNameConventions.TO_STRING || valueParameters.isNotEmpty() || !returnType.isString())
|
||||
return false
|
||||
|
||||
return (dispatchReceiverParameter != null && extensionReceiverParameter == null
|
||||
@@ -103,7 +104,7 @@ class FlattenStringConcatenationLowering(val context: CommonBackendContext) : Fi
|
||||
/** @return true if the function is Any?.toString */
|
||||
private val IrSimpleFunction.isNullableToString: Boolean
|
||||
get() {
|
||||
if (name.asString() != "toString" || valueParameters.size != 0 || !returnType.isString())
|
||||
if (name != OperatorNameConventions.TO_STRING || valueParameters.isNotEmpty() || !returnType.isString())
|
||||
return false
|
||||
|
||||
return dispatchReceiverParameter == null
|
||||
|
||||
+4
-11
@@ -55,10 +55,6 @@ class StringConcatenationLowering(context: CommonBackendContext) : FileLoweringP
|
||||
it.valueParameters.isEmpty()
|
||||
}
|
||||
|
||||
private val toStringFunction = stringBuilder.functions.single {
|
||||
it.valueParameters.isEmpty() && it.name == OperatorNameConventions.TO_STRING
|
||||
}
|
||||
|
||||
private val defaultAppendFunction = stringBuilder.functions.single {
|
||||
it.name == nameAppend &&
|
||||
it.valueParameters.size == 1 &&
|
||||
@@ -90,22 +86,19 @@ class StringConcatenationLowering(context: CommonBackendContext) : FileLoweringP
|
||||
builder.irCall(symbols.extensionToString).apply {
|
||||
extensionReceiver = argument
|
||||
}
|
||||
else builder.irCall(
|
||||
irBuiltIns.anyClass.functions
|
||||
.single { it.owner.name == OperatorNameConventions.TO_STRING }).apply {
|
||||
else builder.irCall(symbols.memberToString).apply {
|
||||
dispatchReceiver = argument
|
||||
}
|
||||
}
|
||||
|
||||
arguments.size == 2 && arguments[0].type.isStringClassType() ->
|
||||
if (arguments[0].type.isNullable())
|
||||
builder.irCall(symbols.stringPlus).apply {
|
||||
builder.irCall(symbols.extensionStringPlus).apply {
|
||||
extensionReceiver = arguments[0]
|
||||
putValueArgument(0, arguments[1])
|
||||
}
|
||||
else
|
||||
builder.irCall(symbols.string.functions
|
||||
.single { it.owner.name == OperatorNameConventions.PLUS }).apply {
|
||||
builder.irCall(symbols.memberStringPlus).apply {
|
||||
dispatchReceiver = arguments[0]
|
||||
putValueArgument(0, arguments[1])
|
||||
}
|
||||
@@ -119,7 +112,7 @@ class StringConcatenationLowering(context: CommonBackendContext) : FileLoweringP
|
||||
putValueArgument(0, arg)
|
||||
}
|
||||
}
|
||||
+irCall(toStringFunction).apply {
|
||||
+irCall(symbols.memberToString).apply {
|
||||
dispatchReceiver = irGet(stringBuilderImpl)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@@ -142,7 +140,10 @@ abstract class IrBuiltIns {
|
||||
abstract val intXorSymbol: IrSimpleFunctionSymbol
|
||||
|
||||
abstract val extensionToString: IrSimpleFunctionSymbol
|
||||
abstract val stringPlus: IrSimpleFunctionSymbol
|
||||
abstract val memberToString: IrSimpleFunctionSymbol
|
||||
|
||||
abstract val extensionStringPlus: IrSimpleFunctionSymbol
|
||||
abstract val memberStringPlus: IrSimpleFunctionSymbol
|
||||
|
||||
abstract val arrayOf: IrSimpleFunctionSymbol
|
||||
abstract val arrayOfNulls: IrSimpleFunctionSymbol
|
||||
|
||||
+22
-3
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
class IrBuiltInsOverDescriptors(
|
||||
@@ -502,14 +503,22 @@ class IrBuiltInsOverDescriptors(
|
||||
} else null
|
||||
}
|
||||
|
||||
override val extensionToString: IrSimpleFunctionSymbol = findFunctions(Name.identifier("toString"), "kotlin").first {
|
||||
override val extensionToString: IrSimpleFunctionSymbol = findFunctions(OperatorNameConventions.TO_STRING, "kotlin").first {
|
||||
val descriptor = it.descriptor
|
||||
descriptor is SimpleFunctionDescriptor && descriptor.dispatchReceiverParameter == null &&
|
||||
descriptor.extensionReceiverParameter != null &&
|
||||
KotlinBuiltIns.isNullableAny(descriptor.extensionReceiverParameter!!.type) && descriptor.valueParameters.size == 0
|
||||
KotlinBuiltIns.isNullableAny(descriptor.extensionReceiverParameter!!.type) && descriptor.valueParameters.isEmpty()
|
||||
}
|
||||
|
||||
override val stringPlus: IrSimpleFunctionSymbol = findFunctions(Name.identifier("plus"), "kotlin").first {
|
||||
override val memberToString: IrSimpleFunctionSymbol = findBuiltInClassMemberFunctions(
|
||||
anyClass,
|
||||
OperatorNameConventions.TO_STRING
|
||||
).single {
|
||||
val descriptor = it.descriptor
|
||||
descriptor is SimpleFunctionDescriptor && descriptor.valueParameters.isEmpty()
|
||||
}
|
||||
|
||||
override val extensionStringPlus: IrSimpleFunctionSymbol = findFunctions(OperatorNameConventions.PLUS, "kotlin").first {
|
||||
val descriptor = it.descriptor
|
||||
descriptor is SimpleFunctionDescriptor && descriptor.dispatchReceiverParameter == null &&
|
||||
descriptor.extensionReceiverParameter != null &&
|
||||
@@ -518,6 +527,16 @@ class IrBuiltInsOverDescriptors(
|
||||
KotlinBuiltIns.isNullableAny(descriptor.valueParameters.first().type)
|
||||
}
|
||||
|
||||
override val memberStringPlus: IrSimpleFunctionSymbol = findBuiltInClassMemberFunctions(
|
||||
stringClass,
|
||||
OperatorNameConventions.PLUS
|
||||
).single {
|
||||
val descriptor = it.descriptor
|
||||
descriptor is SimpleFunctionDescriptor &&
|
||||
descriptor.valueParameters.size == 1 &&
|
||||
KotlinBuiltIns.isNullableAny(descriptor.valueParameters.first().type)
|
||||
}
|
||||
|
||||
override fun functionN(arity: Int): IrClass = functionFactory.functionN(arity)
|
||||
override fun kFunctionN(arity: Int): IrClass = functionFactory.kFunctionN(arity)
|
||||
override fun suspendFunctionN(arity: Int): IrClass = functionFactory.suspendFunctionN(arity)
|
||||
|
||||
@@ -24,6 +24,7 @@ object OperatorNameConventions {
|
||||
@JvmField val PROVIDE_DELEGATE = Name.identifier("provideDelegate")
|
||||
|
||||
@JvmField val EQUALS = Name.identifier("equals")
|
||||
@JvmField val HASH_CODE = Name.identifier("hashCode")
|
||||
@JvmField val COMPARE_TO = Name.identifier("compareTo")
|
||||
@JvmField val CONTAINS = Name.identifier("contains")
|
||||
@JvmField val INVOKE = Name.identifier("invoke")
|
||||
|
||||
Reference in New Issue
Block a user