From a80a0828a94ba44f426cc1ee3c78a87405b50655 Mon Sep 17 00:00:00 2001 From: Inaki Villar Date: Tue, 25 Aug 2026 10:36:20 -0700 Subject: [PATCH] fix: refactor module source-set layout to decouple shared writer from an --- .../writer/AndroidModulesWriter.kt | 2 +- .../writer/JvmModulesWriter.kt | 3 +- .../writer/ModuleSourceSetLayout.kt | 25 +++++++++ .../projectgenerator/writer/ModulesWriter.kt | 15 ++--- .../writer/ModulesWriterTest.kt | 56 ++++++++++++++++++- 5 files changed, 86 insertions(+), 15 deletions(-) create mode 100644 project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/ModuleSourceSetLayout.kt diff --git a/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/AndroidModulesWriter.kt b/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/AndroidModulesWriter.kt index 93130178..1395e1b7 100644 --- a/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/AndroidModulesWriter.kt +++ b/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/AndroidModulesWriter.kt @@ -36,5 +36,5 @@ class AndroidModulesWriter( resources = typeOfStringResources, nodes = nodes, languages = languages, - androidKotlinMultiplatformLibrary = versions.android.kotlinMultiplatformLibrary + sourceSetLayout = AndroidModuleSourceSetLayout(versions.android.kotlinMultiplatformLibrary) ) diff --git a/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/JvmModulesWriter.kt b/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/JvmModulesWriter.kt index 6f41e696..4f310671 100644 --- a/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/JvmModulesWriter.kt +++ b/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/JvmModulesWriter.kt @@ -23,5 +23,6 @@ class JvmModulesWriter( generateUnitTest = generateUnitTest, buildFilesGenerator = BuildFilesGeneratorJvm(), nodes = nodes, - languages = languages + languages = languages, + sourceSetLayout = JvmModuleSourceSetLayout ) diff --git a/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/ModuleSourceSetLayout.kt b/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/ModuleSourceSetLayout.kt new file mode 100644 index 00000000..ed3511c6 --- /dev/null +++ b/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/ModuleSourceSetLayout.kt @@ -0,0 +1,25 @@ +package io.github.cdsap.projectgenerator.writer + +import io.github.cdsap.projectgenerator.generator.android.AndroidSourceSetLayout +import io.github.cdsap.projectgenerator.model.ProjectGraph + +interface ModuleSourceSetLayout { + fun mainKotlinDir(node: ProjectGraph): String + fun testKotlinDir(node: ProjectGraph): String +} + +object JvmModuleSourceSetLayout : ModuleSourceSetLayout { + override fun mainKotlinDir(node: ProjectGraph): String = "src/main/kotlin" + + override fun testKotlinDir(node: ProjectGraph): String = "src/test/kotlin" +} + +class AndroidModuleSourceSetLayout( + private val kotlinMultiplatformLibrary: Boolean +) : ModuleSourceSetLayout { + override fun mainKotlinDir(node: ProjectGraph): String = + AndroidSourceSetLayout.kotlinMainSourceDir(node.type, kotlinMultiplatformLibrary) + + override fun testKotlinDir(node: ProjectGraph): String = + AndroidSourceSetLayout.kotlinTestSourceDir(node.type, kotlinMultiplatformLibrary) +} diff --git a/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/ModulesWriter.kt b/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/ModulesWriter.kt index 6032c5ec..e4ccfc89 100644 --- a/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/ModulesWriter.kt +++ b/project-generator/src/main/kotlin/io/github/cdsap/projectgenerator/writer/ModulesWriter.kt @@ -2,19 +2,15 @@ package io.github.cdsap.projectgenerator.writer import io.github.cdsap.projectgenerator.model.LanguageAttributes import io.github.cdsap.projectgenerator.NameMappings -import io.github.cdsap.projectgenerator.generator.android.AndroidSourceSetLayout import io.github.cdsap.projectgenerator.model.ProjectGraph import io.github.cdsap.projectgenerator.model.TypeOfStringResources import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.withContext import java.io.File import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.CopyOnWriteArrayList -import java.util.concurrent.Executors abstract class ModulesWrite( private val classGenerator: ClassGenerator, @@ -26,7 +22,7 @@ abstract class ModulesWrite( private val resources: TypeOfStringResources? = null, private val nodes: List, private val languages: List, - private val androidKotlinMultiplatformLibrary: Boolean = false + private val sourceSetLayout: ModuleSourceSetLayout = JvmModuleSourceSetLayout ) { suspend fun write() = coroutineScope { val classesDictionary = ConcurrentHashMap>() @@ -67,18 +63,15 @@ abstract class ModulesWrite( } } - - private fun createModuleStructure(node: ProjectGraph, lang: LanguageAttributes) { - // Create main source directory + private fun createModuleStructure(node: ProjectGraph, lang: LanguageAttributes) { val layerDir = NameMappings.layerName(node.layer) val moduleDir = NameMappings.moduleName(node.id) val packageDir = NameMappings.modulePackageName(node.id) - val mainSourceDir = AndroidSourceSetLayout.kotlinMainSourceDir(node.type, androidKotlinMultiplatformLibrary) + val mainSourceDir = sourceSetLayout.mainKotlinDir(node) File("${lang.projectName}/$layerDir/$moduleDir/$mainSourceDir/com/awesomeapp/$packageDir/").mkdirs() - // Create test directory if needed if (generateUnitTest) { - val testSourceDir = AndroidSourceSetLayout.kotlinTestSourceDir(node.type, androidKotlinMultiplatformLibrary) + val testSourceDir = sourceSetLayout.testKotlinDir(node) File("${lang.projectName}/$layerDir/$moduleDir/$testSourceDir/com/awesomeapp/$packageDir/").mkdirs() } } diff --git a/project-generator/src/test/kotlin/io/github/cdsap/projectgenerator/writer/ModulesWriterTest.kt b/project-generator/src/test/kotlin/io/github/cdsap/projectgenerator/writer/ModulesWriterTest.kt index 1e5493ef..09d057c5 100644 --- a/project-generator/src/test/kotlin/io/github/cdsap/projectgenerator/writer/ModulesWriterTest.kt +++ b/project-generator/src/test/kotlin/io/github/cdsap/projectgenerator/writer/ModulesWriterTest.kt @@ -1,13 +1,16 @@ package io.github.cdsap.projectgenerator.writer +import io.github.cdsap.projectgenerator.NameMappings import io.github.cdsap.projectgenerator.model.LanguageAttributes import io.github.cdsap.projectgenerator.model.ProjectGraph import io.github.cdsap.projectgenerator.model.TypeProject import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertSame +import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test import org.junit.jupiter.api.io.TempDir +import java.io.File import java.nio.file.Path import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.atomic.AtomicInteger @@ -50,6 +53,38 @@ class ModulesWriterTest { } } + @Test + fun `createModuleStructure uses injected source set layout for main and test kotlin dirs`() = runBlocking { + val module = ProjectGraph("module_1_1", 1, emptyList(), TypeProject.LIB, 1) + val projectRoot = tempDir.resolve("project").toString() + val languages = listOf(LanguageAttributes("gradle.kts", projectRoot)) + val layout = RecordingSourceSetLayout() + + TestModulesWrite( + classGenerator = RecordingClassGenerator(), + classPlanner = CountingPlanner(), + testGenerator = NoOpTestGenerator(), + generateUnitTest = true, + buildFilesGenerator = NoOpBuildFilesGenerator(), + nodes = listOf(module), + languages = languages, + sourceSetLayout = layout + ).write() + + assertEquals(listOf(module), layout.mainKotlinCalls) + assertEquals(listOf(module), layout.testKotlinCalls) + + val layerDir = NameMappings.layerName(module.layer) + val moduleDir = NameMappings.moduleName(module.id) + val packageDir = NameMappings.modulePackageName(module.id) + assertTrue( + File("$projectRoot/$layerDir/$moduleDir/src/main/kotlin/com/awesomeapp/$packageDir").isDirectory + ) + assertTrue( + File("$projectRoot/$layerDir/$moduleDir/src/test/kotlin/com/awesomeapp/$packageDir").isDirectory + ) + } + private class ModulePlan(val moduleId: String) private class CountingPlanner : ModuleClassPlanner { @@ -98,6 +133,21 @@ class ModulesWriterTest { ) = Unit } + private class RecordingSourceSetLayout : ModuleSourceSetLayout { + val mainKotlinCalls = CopyOnWriteArrayList() + val testKotlinCalls = CopyOnWriteArrayList() + + override fun mainKotlinDir(node: ProjectGraph): String { + mainKotlinCalls.add(node) + return JvmModuleSourceSetLayout.mainKotlinDir(node) + } + + override fun testKotlinDir(node: ProjectGraph): String { + testKotlinCalls.add(node) + return JvmModuleSourceSetLayout.testKotlinDir(node) + } + } + private class TestModulesWrite( classGenerator: ClassGenerator, classPlanner: ModuleClassPlanner, @@ -105,7 +155,8 @@ class ModulesWriterTest { generateUnitTest: Boolean, buildFilesGenerator: BuildFilesGenerator, nodes: List, - languages: List + languages: List, + sourceSetLayout: ModuleSourceSetLayout = JvmModuleSourceSetLayout ) : ModulesWrite( classGenerator = classGenerator, classPlanner = classPlanner, @@ -115,6 +166,7 @@ class ModulesWriterTest { buildFilesGenerator = buildFilesGenerator, resources = null, nodes = nodes, - languages = languages + languages = languages, + sourceSetLayout = sourceSetLayout ) }