Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to canonicalize enum constants #70

Merged
merged 2 commits into from
Nov 20, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue
import org.jetbrains.kotlin.ir.expressions.IrVararg
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetEnumValueImpl
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classFqName
Expand All @@ -37,7 +38,9 @@ import org.jetbrains.kotlin.ir.types.isNullable
import org.jetbrains.kotlin.ir.util.classId
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.findDeclaration
import org.jetbrains.kotlin.ir.util.isEnumClass
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.NameUtils

Expand Down Expand Up @@ -204,7 +207,7 @@ private fun IrExpression.suggestedName(): String? {
}

@UnsafeDuringIrConstructionAPI
private fun enumValueArguments(
private fun IrPluginContext.enumValueArguments(
referenceClass: IrClass,
parameter: IrValueParameter,
): List<Argument> {
Expand All @@ -213,7 +216,7 @@ private fun enumValueArguments(
val defaultEnumSymbol = parameter.defaultValue?.let { defaultValue ->
val expression = defaultValue.expression
when {
expression is IrGetEnumValue -> expression.symbol
expression is IrGetEnumValue -> canonicalize(expression.symbol)
expression is IrConst<*> && expression.value == null -> null
else -> unexpectedDefaultValue(parameter)
}
Expand All @@ -225,7 +228,7 @@ private fun enumValueArguments(
EnumValueArgument(
original = parameter,
type = parameter.type,
isDefault = hasDefaultValue && enumEntry.symbol == defaultEnumSymbol,
isDefault = hasDefaultValue && canonicalize(enumEntry.symbol) == defaultEnumSymbol,
value = enumEntry,
),
)
Expand All @@ -242,6 +245,22 @@ private fun enumValueArguments(
}
}

/**
* It's possible we'll see two different [IrEnumEntrySymbol] instances for the same enum constant.
* This returns a canonical instance by looking up the enum by its name in this [IrPluginContext].
*
* https://kotlinlang.slack.com/archives/C7L3JB43G/p1732121246270569
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You seem to not be following their advice, though. Seems like we could actually just be using the name to track the default (rather than fully-qualified name) since we know the type will always match.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lemme switch to just the name!

*/
@UnsafeDuringIrConstructionAPI
private fun IrPluginContext.canonicalize(
enumSymbol: IrEnumEntrySymbol,
) : IrEnumEntrySymbol {
val classId = enumSymbol.owner.parentAsClass.classId ?: return enumSymbol
val classSymbol = referenceClass(classId) ?: return enumSymbol
val entry = classSymbol.owner.findDeclaration<IrEnumEntry> { it.name == enumSymbol.owner.name }
return entry?.symbol ?: enumSymbol
}

private fun IrPluginContext.booleanArguments(
parameter: IrValueParameter,
): List<Argument> {
Expand Down
Loading