diff --git a/compiler-plugin/src/main/kotlin/community/flock/kmapper/compiler/fir/KMapperFirMappingChecker.kt b/compiler-plugin/src/main/kotlin/community/flock/kmapper/compiler/fir/KMapperFirMappingChecker.kt index cf1464d..558a0b1 100644 --- a/compiler-plugin/src/main/kotlin/community/flock/kmapper/compiler/fir/KMapperFirMappingChecker.kt +++ b/compiler-plugin/src/main/kotlin/community/flock/kmapper/compiler/fir/KMapperFirMappingChecker.kt @@ -176,7 +176,6 @@ class KMapperFirMappingChecker(val collector: MessageCollector, private val sess private fun ConeKotlinType.resolvePropertyFields(): List { val classSymbol = toRegularClassSymbol(session) - if (classSymbol?.moduleData is FirBinaryDependenciesModuleData) return emptyList() return classSymbol?.declaredProperties(session) .orEmpty() .map { property -> diff --git a/test-integration/src/main/kotlin/community/flock/kmapper/IntegrationTest.kt b/test-integration/src/main/kotlin/community/flock/kmapper/IntegrationTest.kt index 71399cc..6231d9f 100644 --- a/test-integration/src/main/kotlin/community/flock/kmapper/IntegrationTest.kt +++ b/test-integration/src/main/kotlin/community/flock/kmapper/IntegrationTest.kt @@ -5,7 +5,9 @@ import java.nio.file.Files class IntegrationTest(options: Options) { data class Options( - val kotlinVersion: String + val kotlinVersion: String, + val additionalPlugins: List = emptyList(), + val additionalDependencies: List = emptyList(), ) data class File( @@ -16,7 +18,7 @@ class IntegrationTest(options: Options) { val files = mutableListOf( settingsGradle, - buildGradle, + buildGradle(options), ) private fun compile(): GradleRunner { @@ -69,29 +71,35 @@ class IntegrationTest(options: Options) { """.trimMargin() ) - val buildGradle = File( - "", - "build.gradle.kts", - """ - |plugins { - | id("community.flock.kmapper") version "0.0.0-SNAPSHOT" - | kotlin("jvm") version "2.3.10" - | application - |} - |repositories { - | mavenCentral() - | mavenLocal() - |} - |dependencies { - | implementation(kotlin("stdlib")) - |} - |kotlin { - | jvmToolchain(21) - |} - |application { - | mainClass.set("sample.AppKt") - |} - """.trimMargin() - ) + fun buildGradle(options: Options): File { + val additionalPlugins = options.additionalPlugins.joinToString("\n") { "| $it" } + val additionalDeps = options.additionalDependencies.joinToString("\n") { "| implementation(\"$it\")" } + return File( + "", + "build.gradle.kts", + """ + |plugins { + | id("community.flock.kmapper") version "0.0.0-SNAPSHOT" + | kotlin("jvm") version "${options.kotlinVersion}" + | application + ${additionalPlugins} + |} + |repositories { + | mavenCentral() + | mavenLocal() + |} + |dependencies { + | implementation(kotlin("stdlib")) + ${additionalDeps} + |} + |kotlin { + | jvmToolchain(21) + |} + |application { + | mainClass.set("sample.AppKt") + |} + """.trimMargin() + ) + } } } \ No newline at end of file diff --git a/test-integration/src/test/kotlin/community/flock/kmapper/SerializableTest.kt b/test-integration/src/test/kotlin/community/flock/kmapper/SerializableTest.kt new file mode 100644 index 0000000..28edc48 --- /dev/null +++ b/test-integration/src/test/kotlin/community/flock/kmapper/SerializableTest.kt @@ -0,0 +1,146 @@ +package community.flock.kmapper + +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test + +class SerializableTest { + + val options = IntegrationTest.Options( + kotlinVersion = "2.3.10", + additionalPlugins = listOf("""kotlin("plugin.serialization") version "2.3.10""""), + additionalDependencies = listOf("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1"), + ) + + @Test + fun shouldCompile_autoMapWithSerializableTarget() { + IntegrationTest(options) + .file("App.kt") { + $$""" + |package sample + | + |import community.flock.kmapper.mapper + |import kotlinx.serialization.Serializable + | + |data class Pagination( + | val pageNumber: Int, + | val pageSize: Int, + | val totalElements: Long, + |) + | + |@Serializable + |data class PaginationDto( + | val pageNumber: Long, + | val pageSize: Long, + | val totalElements: Long, + |) + | + |fun Pagination.toDto(): PaginationDto = mapper { + | pageNumber = it.pageNumber.toLong() + | pageSize = it.pageSize.toLong() + |} + | + |fun main() { + | val pagination = Pagination(pageNumber = 1, pageSize = 10, totalElements = 100L) + | val dto = pagination.toDto() + | println(dto) + |} + | + """.trimMargin() + } + .compileSuccess { output -> + assertTrue( + output.contains("PaginationDto(pageNumber=1, pageSize=10, totalElements=100)"), + "Expected PaginationDto(pageNumber=1, pageSize=10, totalElements=100) in output" + ) + } + } + + @Test + fun shouldCompile_autoMapWithSerializableAndSealedInterface() { + IntegrationTest(options) + .file("App.kt") { + $$""" + |package sample + | + |import community.flock.kmapper.mapper + |import kotlinx.serialization.Serializable + |import kotlinx.serialization.SerialName + | + |sealed interface Message { + | val sender: String + | val createdAt: String + | val category: String + | + | data class Text( + | override val sender: String, + | override val createdAt: String, + | val text: String, + | override val category: String = "EXECUTION", + | ) : Message + |} + | + |@Serializable + |sealed interface MessageDto + | + |@Serializable + |@SerialName("TextMessageDto") + |data class TextMessageDto( + | val sender: String, + | val createdAt: String, + | val text: String, + |) : MessageDto + | + |fun Message.Text.toDto(): TextMessageDto = mapper { + | sender = it.sender.uppercase() + | createdAt = it.createdAt + |} + | + |fun main() { + | val message = Message.Text(sender = "agent", createdAt = "2025-01-01", text = "hello") + | val dto = message.toDto() + | println(dto) + |} + | + """.trimMargin() + } + .compileSuccess { output -> + assertTrue( + output.contains("TextMessageDto(sender=AGENT, createdAt=2025-01-01, text=hello)"), + "Expected TextMessageDto(sender=AGENT, createdAt=2025-01-01, text=hello) in output" + ) + } + } + + @Test + fun shouldCompile_allFieldsAutoMappedWithSerializable() { + IntegrationTest(options) + .file("App.kt") { + $$""" + |package sample + | + |import community.flock.kmapper.mapper + |import kotlinx.serialization.Serializable + | + |data class Result(val description: String, val response: String?) + | + |@Serializable + |data class ResultDto(val description: String, val response: String?) + | + |fun Result.toDto(): ResultDto = mapper() + | + |fun main() { + | val result = Result(description = "done", response = "ok") + | val dto = result.toDto() + | println(dto) + |} + | + """.trimMargin() + } + .compileSuccess { output -> + assertTrue( + output.contains("ResultDto(description=done, response=ok)"), + "Expected ResultDto(description=done, response=ok) in output" + ) + } + } +}