Skip to content

Commit

Permalink
Simplified code and resolved TODOs
Browse files Browse the repository at this point in the history
  • Loading branch information
stefankoppier committed Jul 27, 2024
1 parent cf4d2ac commit 3ce1797
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class ConstructorCallMappingConstructor(
val getter = irCall(source.property.function).apply {
dispatchReceiver = irGet(source.property.holder)
}
return source.via?.let { generateTransformation(generated, it, getter, source, target) } ?: getter
return source.via?.let { generateTransformation(generated, it, getter, source, target, file) } ?: getter
}

private fun IrBuilderWithScope.generatePropertyValueArgument(
Expand All @@ -91,7 +91,8 @@ class ConstructorCallMappingConstructor(
?: irGet(parameters.singleOrNull { it.type == source.property.targetType(file) }
?: mappieTerminate("Could not determine value parameters for property reference. Please use a property reference of an object instead of the class", location(file, source.property)))
}
return source.transformation?.let { generateTransformation(generated, it, getter, source, target) } ?: getter
return source.transformation?.let { generateTransformation(generated, it, getter, source, target, file) }
?: getter
}

private fun IrBuilderWithScope.generateExpressionValueArgument(source: ExpressionSource, parameters: List<IrValueParameter>): IrFunctionAccessExpression {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tech.mappie.generation

import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.IrFileEntry
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.expressions.IrExpression
Expand All @@ -11,6 +12,7 @@ import tech.mappie.mappieTerminate
import tech.mappie.resolving.MappieDefinition
import tech.mappie.resolving.classes.*
import tech.mappie.resolving.classes.targets.MappieTarget
import tech.mappie.util.location
import tech.mappie.util.referenceFunctionLet

fun IrBuilderWithScope.generateTransformation(
Expand All @@ -19,12 +21,13 @@ fun IrBuilderWithScope.generateTransformation(
value: IrExpression,
source: ObjectMappingSource,
target: MappieTarget,
file: IrFileEntry,
): IrExpression =
when (transformation) {
is MappieTransformOperator -> generateTransformOperator(transformation, value)
is MappieViaOperator -> generateViaOperator(transformation, target, value)
is MappieViaResolved -> generateViaResolved(transformation, target, value)
is MappieViaGeneratedClass -> generateViaGeneratedClass(transformation, generated, source, target, value)
is MappieViaResolved -> generateViaResolved(transformation, source, target, value, file)
is MappieViaGeneratedClass -> generateViaGeneratedClass(transformation, generated, source, target, value, file)
}

private fun IrBuilderWithScope.generateViaGeneratedClass(
Expand All @@ -33,69 +36,27 @@ private fun IrBuilderWithScope.generateViaGeneratedClass(
source: ObjectMappingSource,
target: MappieTarget,
value: IrExpression,
file: IrFileEntry,
): IrExpression {
val clazz = generated.find { it.name == transformation.definition.name }
?: mappieTerminate("Could not find generated class ${transformation.definition.name.asString()}. This is a bug.", null)

val definition = MappieDefinition(clazz)
val receiver = when (clazz.kind) {
ClassKind.CLASS -> {
val constructor = clazz.constructors.firstOrNull { it.valueParameters.isEmpty() }
if (constructor != null) {
irCallConstructor(constructor.symbol, emptyList())
} else {
mappieTerminate(
"Resolved mapping via ${clazz.name.asString()}, but it does not have a constructor without arguments",
null, // TODO
)
}
}
ClassKind.OBJECT -> {
irGetObject(clazz.symbol)
}
else -> {
mappieTerminate("", null) // TODO
}
return irCall(definition.function(value.type, target.type)).apply {
dispatchReceiver = getReceiver(clazz, file, source)
putValueArgument(0, value)
}
return irIfNull(source.type, receiver,
irNull(),
irCall(definition.function(value.type, target.type)).apply {
dispatchReceiver = receiver
putValueArgument(0, value)
}
)
}

private fun IrBuilderWithScope.generateViaResolved(
transformation: MappieViaResolved,
source: ObjectMappingSource,
target: MappieTarget,
value: IrExpression,
file: IrFileEntry,
): IrExpression {
val receiver = when (transformation.definition.clazz.kind) {
ClassKind.CLASS -> {
val constructor = transformation.definition.clazz.constructors.firstOrNull { it.valueParameters.isEmpty() }
if (constructor != null) {
irCallConstructor(constructor.symbol, emptyList())
} else {
mappieTerminate(
"Resolved mapping via ${transformation.definition.clazz.name.asString()}, but it does not have a constructor without arguments",
null, // TODO
)
}
}

ClassKind.OBJECT -> {
irGetObject(transformation.definition.clazz.symbol)
}

else -> {
mappieTerminate("", null) // TODO
}
}

val transformation = transformation.definition.function(value.type, target.type)
return irCall(transformation).apply {
dispatchReceiver = receiver
return irCall(transformation.definition.function(value.type, target.type)).apply {
dispatchReceiver = getReceiver(transformation.definition.clazz, file, source)
putValueArgument(0, value)
}
}
Expand All @@ -105,8 +66,7 @@ private fun IrBuilderWithScope.generateViaOperator(
target: MappieTarget,
value: IrExpression,
): IrFunctionAccessExpression {
val function = transformation.definition.function(value.type, target.type)
return irCall(function.symbol).apply {
return irCall(transformation.definition.function(value.type, target.type).symbol).apply {
dispatchReceiver = transformation.dispatchReceiver
putValueArgument(0, value)
}
Expand All @@ -117,3 +77,31 @@ private fun IrBuilderWithScope.generateTransformOperator(transformation: MappieT
letCall.extensionReceiver = value
letCall.putValueArgument(0, transformation.function)
}

private fun IrBuilderWithScope.getReceiver(
clazz: IrClass,
file: IrFileEntry,
source: ObjectMappingSource,
) = when (clazz.kind) {
ClassKind.CLASS -> {
val constructor = clazz.constructors.firstOrNull { it.valueParameters.isEmpty() }
if (constructor != null) {
irCallConstructor(constructor.symbol, emptyList())
} else {
mappieTerminate(
"Resolved mapping via ${clazz.name.asString()}, but it does not have a constructor without arguments",
location(file, source.origin),
)
}
}
ClassKind.OBJECT -> {
irGetObject(clazz.symbol)
}

else -> {
mappieTerminate(
"Resolved mapping via ${clazz.name.asString()}, but is an ${clazz.kind.codeRepresentation} and either an object or class was expected",
location(file, source.origin)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ClassResolver(private val declaration: IrFunction, private val symbols: Li
MappieTargetsCollector(constructor).all()
).also {
declaration.body?.accept(ObjectMappingBodyCollector(declaration.fileEntry), it)
}.construct()
}.construct(declaration)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tech.mappie.resolving.classes

import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
Expand All @@ -8,20 +9,22 @@ import tech.mappie.resolving.classes.sources.MappieSource

sealed interface ObjectMappingSource {
val type: IrType
val origin: IrElement
}

data class ResolvedSource(
val property: MappieSource,
val via: MappieTransformation? = null,
val viaType: IrType? = null,
override val origin: IrElement,
) : ObjectMappingSource {
override val type: IrType get() = viaType ?: property.type
}

data class PropertySource(
val property: IrPropertyReference,
val transformation: MappieTransformation? = null,
val origin: IrExpression,
override val origin: IrElement,
) : ObjectMappingSource {

val getter = property.getter!!
Expand All @@ -37,16 +40,19 @@ data class PropertySource(

data class ExpressionSource(
val expression: IrFunctionExpression,
val origin: IrExpression,
override val origin: IrElement,
) : ObjectMappingSource {
override val type = expression.function.returnType
}

data class ValueSource(
val value: IrExpression,
val origin: IrExpression?,
override val origin: IrElement,
) : ObjectMappingSource {
override val type = value.type
}

class DefaultArgumentSource(override val type: IrType) : ObjectMappingSource
class DefaultArgumentSource(
override val type: IrType,
override val origin: IrElement,
) : ObjectMappingSource
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tech.mappie.resolving.classes

import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
Expand All @@ -22,7 +23,7 @@ class ObjectMappingsConstructor(

private val targetType = constructor.returnType

fun construct(): ConstructorCallMapping {
fun construct(origin: IrElement): ConstructorCallMapping {
val generatedMappers = mutableSetOf<GeneratedMappieClass>()
val mappings = targets.associateWith { target ->
val concreteSource = explicit[target.name]
Expand All @@ -47,7 +48,7 @@ class ObjectMappingsConstructor(
val mappings = sources.filter { source -> source.name == getterName(target.name) }
.map { getter ->
if (target.type.isAssignableFrom(getter.type)) {
ResolvedSource(getter, null)
ResolvedSource(getter, null, null, origin)
} else {
val transformation = symbols
.singleOrNull { it.fits(getter.type, target.type) }
Expand All @@ -59,15 +60,16 @@ class ObjectMappingsConstructor(
ResolvedSource(
getter,
transformation,
transformation?.let { target.type }
transformation?.let { target.type },
origin,
)
}
}

if (mappings.isNotEmpty()) {
mappings
} else if (target is MappieValueParameterTarget && target.value.hasDefaultValue() && context.configuration.useDefaultArguments) {
listOf(DefaultArgumentSource(target.value.type))
listOf(DefaultArgumentSource(target.value.type, origin))
} else {
emptyList()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ data class MappieSetterTarget(val value: IrProperty) : MappieTarget {
}

data class MappieFunctionTarget(val value: IrSimpleFunctionSymbol) : MappieTarget {

override val name = Name.identifier(value.owner.name.asString().removePrefix("set").replaceFirstChar { it.lowercaseChar() })
override val type = value.owner.valueParameters.first().type
}
Expand Down

0 comments on commit 3ce1797

Please sign in to comment.