diff --git a/cli/src/jvmMain/kotlin/Cli.kt b/cli/src/jvmMain/kotlin/Cli.kt index 50c0d48..326ef9d 100644 --- a/cli/src/jvmMain/kotlin/Cli.kt +++ b/cli/src/jvmMain/kotlin/Cli.kt @@ -225,8 +225,7 @@ suspend fun main(args: Array) { Init(), Add().subcommands(AddModule()), Docs().subcommands(DocsList(), DocsSearch(), DocsGet()), - Install().subcommands(InstallMcp()), - Target()) + Install().subcommands(InstallMcp())) .main(args) } @@ -1065,818 +1064,6 @@ private fun copyBundledResource(resourcePath: String, targetFile: File) { } } -class Target : CliktCommand("target") { - override fun help(context: Context): String = - """ - Adds a new Kotlin target to the current Compose Multiplatform project (options: android, jvm, ios, wasm). - """ - .trimIndent() - - private val targetName by argument(name = "target") - - override fun run() { - val validTargets = setOf("android", "jvm", "ios", "wasm") - - if (targetName !in validTargets) { - echo("Unknown target '$targetName'") - echo("Available targets: android, jvm, ios, wasm") - echo("Usage: composables target ") - return - } - - val workingDir = System.getProperty("user.dir") - - if (!isValidComposeAppDirectory(workingDir)) { - echo("This doesn't appear to be a Compose Multiplatform project.") - echo("To create a new Compose app, run:") - echo( - " composables init app --package com.example.app --app-name \"My App\" --targets android,jvm,ios,wasm") - return - } - - val composeModuleBuildFile = findComposeModuleBuildFile(workingDir) - if (composeModuleBuildFile == null) { - echo("Could not find a Compose Multiplatform module in this project.") - return - } - - when (targetName) { - "android" -> { - if (hasAndroidTarget(composeModuleBuildFile)) { - echo("Android target is already configured in this project.") - return - } - try { - addAndroidTarget(workingDir, composeModuleBuildFile) - echo("Android target added successfully!") - echo("Run '$gradleScript build' to verify the configuration.") - } catch (e: Exception) { - echo("Failed to add Android target: ${e.message}", err = true) - } - } - - "jvm" -> { - if (hasJvmTarget(composeModuleBuildFile)) { - echo("JVM target is already configured in this project.") - return - } - try { - addJvmTarget(workingDir, composeModuleBuildFile) - echo("JVM target added successfully!") - echo("Run '$gradleScript build' to verify the configuration.") - } catch (e: Exception) { - echo("Failed to add JVM target: ${e.message}", err = true) - } - } - - "ios" -> { - if (hasIosTarget(composeModuleBuildFile)) { - echo("iOS target is already configured in this project.") - return - } - try { - addIosTarget(workingDir, composeModuleBuildFile) - echo("iOS target added successfully!") - echo("Run '$gradleScript build' to verify the configuration.") - } catch (e: Exception) { - echo("Failed to add iOS target: ${e.message}", err = true) - } - } - - "wasm" -> { - if (hasWasmTarget(composeModuleBuildFile)) { - echo("Wasm target is already configured in this project.") - return - } - try { - addWasmTarget(workingDir, composeModuleBuildFile) - echo("Wasm target added successfully!") - echo("Run '$gradleScript build' to verify the configuration.") - } catch (e: Exception) { - echo("Failed to add wasm target: ${e.message}", err = true) - } - } - } - } - - private fun isValidComposeAppDirectory(directory: String): Boolean { - val dir = File(directory) - - // Check for root build.gradle.kts - val rootBuildFile = File(dir, "build.gradle.kts") - if (!rootBuildFile.exists()) { - return false - } - - // Look for any subdirectory with build.gradle.kts that has Compose dependencies - val subDirs = - dir.listFiles()?.filter { subDir -> - subDir.isDirectory && File(subDir, "build.gradle.kts").exists() - } ?: return false - - return subDirs.any { subDir -> - val buildFile = File(subDir, "build.gradle.kts") - val content = buildFile.readText() - hasComposeDependencies(content) - } - } - - private fun hasComposeDependencies(content: String): Boolean { - val composeDependencies = - listOf( - "compose.components.resources", - "org.jetbrains.compose.ui:ui-tooling-preview", - "libs.compose.ui", - "libs.compose.ui.tooling.preview", - "libs.composables.ui", - "com.composables:ui:", - "compose.desktop.currentOs", - "compose.runtime", - ) - - return composeDependencies.any { dependency -> content.contains(dependency) } - } - - private fun findComposeModuleBuildFile(workingDir: String): File? { - val dir = File(workingDir) - - val sharedBuildFile = File(dir, "$SHARED_MODULE/build.gradle.kts") - if (sharedBuildFile.exists()) { - return sharedBuildFile - } - - val composeModules = - dir.listFiles() - ?.filter { subDir -> subDir.isDirectory && File(subDir, "build.gradle.kts").exists() } - ?.filter { subDir -> - val buildFile = File(subDir, "build.gradle.kts") - val content = buildFile.readText() - hasComposeDependencies(content) - } ?: return null - - val sharedLikeComposeModules = - composeModules.filter { subDir -> File(subDir, "src/commonMain").isDirectory } - - when { - sharedLikeComposeModules.size == 1 -> - return File(sharedLikeComposeModules.first(), "build.gradle.kts") - sharedLikeComposeModules.size > 1 -> return selectComposeModule(sharedLikeComposeModules) - composeModules.isEmpty() -> return null - composeModules.size == 1 -> return File(composeModules.first(), "build.gradle.kts") - else -> { - return selectComposeModule(composeModules) - } - } - } - - private fun selectComposeModule(composeModules: List): File? { - val sortedModules = composeModules.sortedBy { it.name } - echo("Multiple Compose modules detected:") - sortedModules.forEachIndexed { index, module -> echo(" ${index + 1}. ${module.name}") } - - while (true) { - echo("Select a module (1-${sortedModules.size}): ", trailingNewline = false) - val input = readln().trim() - - val selection = input.toIntOrNull() - if (selection != null && selection in 1..sortedModules.size) { - val selectedModule = sortedModules[selection - 1] - echo("Selected module: ${selectedModule.name}") - return File(selectedModule, "build.gradle.kts") - } else { - echo("Invalid selection. Please enter a number between 1 and ${sortedModules.size}") - } - } - } - - private fun hasAndroidTarget(buildFile: File): Boolean { - val content = buildFile.readText() - return content.contains("android {") - } - - private fun hasJvmTarget(buildFile: File): Boolean { - val content = buildFile.readText() - return content.contains("jvm()") - } - - private fun hasIosTarget(buildFile: File): Boolean { - val content = buildFile.readText() - return content.contains("iosArm64()") || content.contains("iosSimulatorArm64()") - } - - private fun hasWasmTarget(buildFile: File): Boolean { - val content = buildFile.readText() - return content.contains("wasmJs") - } - - private fun addAndroidTarget(workingDir: String, buildFile: File) { - val content = buildFile.readText() - val lines = content.lines().toMutableList() - val moduleDir = buildFile.parentFile - val moduleName = moduleDir.name - val namespace = inferNamespace(moduleDir) - - // Add import if needed - if (!content.contains("import org.jetbrains.kotlin.gradle.dsl.JvmTarget")) { - val importLine = "import org.jetbrains.kotlin.gradle.dsl.JvmTarget" - // Find the last import line and add after it - val lastImportIndex = lines.indexOfLast { it.startsWith("import ") } - if (lastImportIndex >= 0) { - lines.add(lastImportIndex + 1, importLine) - } else { - // Add before the first non-empty, non-comment line - val firstCodeLine = - lines.indexOfFirst { !it.trim().isEmpty() && !it.trim().startsWith("//") } - if (firstCodeLine >= 0) { - lines.add(firstCodeLine, importLine) - } - } - } - - // Append to plugins block - val pluginsCloseIndex = findPluginsBlockEnd(lines) - if (pluginsCloseIndex >= 0) { - lines.add(pluginsCloseIndex, " alias(libs.plugins.android.kotlin.multiplatform.library)") - } - - // Append to kotlin block - val kotlinCloseIndex = findKotlinBlockEnd(lines) - if (kotlinCloseIndex >= 0) { - val moduleNamespace = toNamespaceSegment(moduleName) - val androidTargetLines = - listOf( - "", - " android {", - " namespace = \"$namespace.$moduleNamespace\"", - " compileSdk = libs.versions.android.compileSdk.get().toInt()", - " minSdk = libs.versions.android.minSdk.get().toInt()", - " withJava()", - " androidResources {", - " enable = true", - " }", - " compilerOptions {", - " jvmTarget.set(JvmTarget.JVM_17)", - " }", - " }", - ) - androidTargetLines.reversed().forEach { line -> lines.add(kotlinCloseIndex, line) } - } - - // Write updated content - buildFile.writeText(lines.joinToString("\n")) - - createAndroidAppModule( - projectDir = File(workingDir), - sharedModuleName = moduleName, - namespace = namespace, - ) - addModuleIncludeToSettings(workingDir, ANDROID_APP_MODULE) - - // Update root build.gradle.kts - updateRootBuildFile(workingDir, setOf(ANDROID)) - - // Update gradle.properties - updateGradleProperties(workingDir) - - // Update libs.versions.toml - updateVersionCatalog(workingDir, setOf(ANDROID)) - } - - private fun findPluginsBlockEnd(lines: List): Int { - var depth = 0 - for (i in lines.indices) { - val line = lines[i].trim() - if (line.startsWith("plugins {")) { - depth = 1 - for (j in i + 1 until lines.size) { - val currentLine = lines[j].trim() - if (currentLine.contains("{")) depth++ - if (currentLine.contains("}")) depth-- - if (depth == 0) return j - } - } - } - return -1 - } - - private fun findKotlinBlockEnd(lines: List): Int { - var depth = 0 - for (i in lines.indices) { - val line = lines[i].trim() - if (line.startsWith("kotlin {")) { - depth = 1 - for (j in i + 1 until lines.size) { - val currentLine = lines[j].trim() - if (currentLine.contains("{")) depth++ - if (currentLine.contains("}")) depth-- - if (depth == 0) return j - } - } - } - return -1 - } - - private fun extractNamespace(lines: List): String { - // Try to find existing namespace from android block or use a default - for (line in lines) { - if (line.trim().startsWith("namespace =")) { - return line.trim().substringAfter("namespace =").trim().removeSurrounding("\"") - } - } - return "com.example.app" // fallback - } - - private fun inferNamespace(moduleDir: File): String { - val commonMainDir = File(moduleDir, "src/commonMain/kotlin") - if (commonMainDir.exists()) { - commonMainDir - .walkTopDown() - .firstOrNull { it.isFile && it.extension == "kt" } - ?.useLines { lines -> - lines - .firstOrNull { it.startsWith("package ") } - ?.removePrefix("package ") - ?.trim() - ?.takeIf { it.isNotEmpty() } - } - ?.let { - return it - } - } - - return "com.example.app" - } - - private fun updateGradleProperties(workingDir: String) { - val gradlePropertiesFile = File(workingDir, "gradle.properties") - if (!gradlePropertiesFile.exists()) return - - var content = gradlePropertiesFile.readText() - - // Add Android properties if not present - if (!content.contains("android.useAndroidX")) { - content += "\n\n#Android\nandroid.useAndroidX=true\nandroid.nonTransitiveRClass=true\n" - } - - gradlePropertiesFile.writeText(content) - } - - private fun createAndroidAppModule( - projectDir: File, - sharedModuleName: String, - namespace: String, - ) { - val androidAppDir = File(projectDir, ANDROID_APP_MODULE) - androidAppDir.mkdirs() - File(androidAppDir, "build.gradle.kts") - .writeText( - """ - plugins { - alias(libs.plugins.android.application) - alias(libs.plugins.jetbrains.compose.compiler) - } - - android { - namespace = "$namespace" - compileSdk = libs.versions.android.compileSdk.get().toInt() - - defaultConfig { - applicationId = "$namespace" - minSdk = libs.versions.android.minSdk.get().toInt() - targetSdk = libs.versions.android.targetSdk.get().toInt() - versionCode = 1 - versionName = "1.0" - } - buildFeatures { - compose = true - } - packaging { - resources { - excludes += "/META-INF/{AL2.0,LGPL2.1}" - } - } - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - } - - dependencies { - implementation(projects.${toProjectAccessorName(sharedModuleName)}) - implementation(libs.androidx.activity.compose) - } - """ - .trimIndent() + "\n", - ) - - fun copyResource(resourcePath: String, targetFile: File) { - val inputStream: InputStream? = object {}.javaClass.getResourceAsStream(resourcePath) - if (inputStream != null) { - targetFile.parentFile?.mkdirs() - inputStream.use { input -> - targetFile.outputStream().use { output -> input.copyTo(output) } - } - } - } - - fun listResources(path: String): List { - val resources = mutableListOf() - val resourceUrl = object {}.javaClass.getResource(path) - - if (resourceUrl != null) { - when (resourceUrl.protocol) { - "file" -> { - val dir = File(resourceUrl.toURI()) - dir.walkTopDown().forEach { file -> - if (file.isFile) { - val relativePath = file.relativeTo(dir) - resources.add("$path/${relativePath.toResourcePath()}") - } - } - } - - "jar" -> { - val jarPath = resourceUrl.path.substringBefore("!") - val jarFile = JarFile(File(jarPath.substringAfter("file:"))) - val entries = jarFile.entries() - - while (entries.hasMoreElements()) { - val entry = entries.nextElement() - if (entry.name.startsWith(path.substring(1)) && !entry.isDirectory) { - resources.add("/${entry.name}") - } - } - jarFile.close() - } - } - } - - return resources - } - - val resources = listResources("/project/$ANDROID_APP_MODULE/src/main") - resources.forEach { resourcePath -> - val targetPath = - resourcePath - .removePrefix("/project/$ANDROID_APP_MODULE/src/main/") - .replace("org/example/project", namespace.replace(".", "/")) - val targetFile = File(androidAppDir, "src/main/$targetPath") - copyResource(resourcePath, targetFile) - - if (targetFile.name.endsWith(".kt") || targetFile.name.endsWith(".xml")) { - try { - val content = targetFile.readText() - var updatedContent = content.replace("{{namespace}}", namespace) - updatedContent = updatedContent.replace("{{app_name}}", projectDir.name) - if (content != updatedContent) { - targetFile.writeText(updatedContent) - } - } catch (e: Exception) { - // Skip binary files - } - } - } - } - - private fun addModuleIncludeToSettings( - workingDir: String, - moduleName: String, - ) { - val settingsFile = File(workingDir, "settings.gradle.kts") - if (!settingsFile.exists()) return - - val content = settingsFile.readText() - if (content.contains("""include(":$moduleName")""")) return - - settingsFile.writeText(content.trimEnd() + "\ninclude(\":$moduleName\")\n") - } - - private fun addJvmTarget(workingDir: String, buildFile: File) { - val content = buildFile.readText() - val lines = content.lines().toMutableList() - - // Append to kotlin block - val kotlinCloseIndex = findKotlinBlockEnd(lines) - if (kotlinCloseIndex >= 0) { - lines.add(kotlinCloseIndex, " jvm()") - } - - // Write updated content - buildFile.writeText(lines.joinToString("\n")) - - val moduleDir = buildFile.parentFile - val moduleName = moduleDir.name - val namespace = inferNamespace(moduleDir) - - createDesktopAppModule( - projectDir = File(workingDir), - sharedModuleName = moduleName, - namespace = namespace, - appName = File(workingDir).name, - ) - addModuleIncludeToSettings(workingDir, DESKTOP_APP_MODULE) - updateRootBuildFile(workingDir, setOf(JVM)) - updateVersionCatalog(workingDir, setOf(JVM)) - } - - private fun addIosTarget(workingDir: String, buildFile: File) { - var content = buildFile.readText() - val lines = content.lines().toMutableList() - - // Append to kotlin block - val kotlinCloseIndex = findKotlinBlockEnd(lines) - if (kotlinCloseIndex >= 0) { - val moduleName = buildFile.parentFile.name - val baseName = toCamelCase(moduleName) - val iosTargetLines = - listOf( - "", - " listOf(", - " iosArm64(),", - " iosSimulatorArm64()", - " ).forEach { iosTarget ->", - " iosTarget.binaries.framework {", - " baseName = \"$baseName\"", - " isStatic = true", - " }", - " }", - ) - iosTargetLines.reversed().forEach { line -> lines.add(kotlinCloseIndex, line) } - } - - // Write updated content - buildFile.writeText(lines.joinToString("\n")) - - // Create iosMain source set - val moduleDir = buildFile.parentFile - createIosSourceSet(moduleDir, extractNamespace(lines)) - - // Copy iOS app directory - copyIosAppDirectory(workingDir, moduleDir.name) - } - - private fun createIosSourceSet(moduleDir: File, namespace: String) { - val iosMainDir = File(moduleDir, "src/iosMain/kotlin") - val packageDir = File(iosMainDir, namespace.replace(".", "/")) - - // Create directories - packageDir.mkdirs() - - val mainFile = File(packageDir, "MainViewController.kt") - val mainContent = - """package $namespace - -import androidx.compose.ui.window.ComposeUIViewController - -fun MainViewController() = ComposeUIViewController { App() } -""" - mainFile.writeText(mainContent) - } - - private fun addWasmTarget(workingDir: String, buildFile: File) { - val content = buildFile.readText() - val lines = content.lines().toMutableList() - - // Add imports if needed - if (!content.contains("import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl")) { - val importLine = "import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl" - val lastImportIndex = lines.indexOfLast { it.startsWith("import ") } - if (lastImportIndex >= 0) { - lines.add(lastImportIndex + 1, importLine) - } else { - val firstCodeLine = - lines.indexOfFirst { !it.trim().isEmpty() && !it.trim().startsWith("//") } - if (firstCodeLine >= 0) { - lines.add(firstCodeLine, importLine) - } - } - } - - // Append to kotlin block - val kotlinCloseIndex = findKotlinBlockEnd(lines) - if (kotlinCloseIndex >= 0) { - val wasmTargetLines = - listOf( - "", - " @OptIn(ExperimentalWasmDsl::class)", - " wasmJs {", - " browser()", - " }", - ) - wasmTargetLines.reversed().forEach { line -> lines.add(kotlinCloseIndex, line) } - } - - // Write updated content - buildFile.writeText(lines.joinToString("\n")) - - val moduleDir = buildFile.parentFile - val moduleName = moduleDir.name - val namespace = inferNamespace(moduleDir) - - createWebAppModule( - projectDir = File(workingDir), - sharedModuleName = moduleName, - namespace = namespace, - ) - addModuleIncludeToSettings(workingDir, WEB_APP_MODULE) - updateRootBuildFile(workingDir, setOf(WASM)) - updateVersionCatalog(workingDir, setOf(WASM)) - } - - private fun createDesktopAppModule( - projectDir: File, - sharedModuleName: String, - namespace: String, - appName: String, - ) { - val desktopAppDir = File(projectDir, DESKTOP_APP_MODULE) - desktopAppDir.mkdirs() - File(desktopAppDir, "build.gradle.kts") - .writeText( - object {} - .javaClass - .getResource("/project/$DESKTOP_APP_MODULE/build.gradle.kts")!! - .readText() - .replace("{{shared_module_accessor}}", toProjectAccessorName(sharedModuleName)) - .replace("{{namespace}}", namespace) - .trim() + "\n", - ) - - val mainFile = File(desktopAppDir, "src/jvmMain/kotlin/${namespace.replace(".", "/")}/main.kt") - mainFile.parentFile.mkdirs() - mainFile.writeText( - object {} - .javaClass - .getResource("/project/$DESKTOP_APP_MODULE/src/jvmMain/kotlin/org/example/main.kt")!! - .readText() - .replace("{{namespace}}", namespace) - .replace("{{app_name}}", appName) - .trim() + "\n", - ) - } - - private fun createWebAppModule( - projectDir: File, - sharedModuleName: String, - namespace: String, - ) { - val webAppDir = File(projectDir, WEB_APP_MODULE) - - fun copyResource(resourcePath: String, targetFile: File) { - val inputStream: InputStream? = object {}.javaClass.getResourceAsStream(resourcePath) - if (inputStream != null) { - targetFile.parentFile?.mkdirs() - inputStream.use { input -> - targetFile.outputStream().use { output -> input.copyTo(output) } - } - } - } - - fun listResources(path: String): List { - val resources = mutableListOf() - val resourceUrl = object {}.javaClass.getResource(path) - - if (resourceUrl != null) { - when (resourceUrl.protocol) { - "file" -> { - val dir = File(resourceUrl.toURI()) - dir.walkTopDown().forEach { file -> - if (file.isFile) { - val relativePath = file.relativeTo(dir) - resources.add("$path/${relativePath.toResourcePath()}") - } - } - } - - "jar" -> { - val jarPath = resourceUrl.path.substringBefore("!") - val jarFile = JarFile(File(jarPath.substringAfter("file:"))) - val entries = jarFile.entries() - - while (entries.hasMoreElements()) { - val entry = entries.nextElement() - if (entry.name.startsWith(path.substring(1)) && !entry.isDirectory) { - resources.add("/${entry.name}") - } - } - jarFile.close() - } - } - } - - return resources - } - - listResources("/project/$WEB_APP_MODULE").forEach { resourcePath -> - var targetPath = resourcePath.removePrefix("/project/$WEB_APP_MODULE/") - targetPath = targetPath.replace("org/example", namespace.replace(".", "/")) - val targetFile = webAppDir.resolve(targetPath) - copyResource(resourcePath, targetFile) - - if (targetFile.isFile && - (targetFile.extension == "kts" || - targetFile.extension == "kt" || - targetFile.extension == "html" || - targetFile.extension == "css" || - targetFile.extension == "js")) { - val content = targetFile.readText() - val updatedContent = - content - .replace("{{shared_module_accessor}}", toProjectAccessorName(sharedModuleName)) - .replace("{{namespace}}", namespace) - if (content != updatedContent) { - targetFile.writeText(updatedContent.trim() + "\n") - } - } - } - } - - private fun copyIosAppDirectory(workingDir: String, moduleName: String) { - val targetDir = File(workingDir, IOS_APP_MODULE) - - fun copyResource(resourcePath: String, targetFile: File) { - val inputStream: InputStream? = object {}.javaClass.getResourceAsStream(resourcePath) - if (inputStream != null) { - targetFile.parentFile?.mkdirs() - inputStream.use { input -> - targetFile.outputStream().use { output -> input.copyTo(output) } - } - } - } - - fun listResources(path: String): List { - val resources = mutableListOf() - val resourceUrl = object {}.javaClass.getResource(path) - - if (resourceUrl != null) { - when (resourceUrl.protocol) { - "file" -> { - val dir = File(resourceUrl.toURI()) - dir.walkTopDown().forEach { file -> - if (file.isFile) { - val relativePath = file.relativeTo(dir) - resources.add("$path/${relativePath.toResourcePath()}") - } - } - } - - "jar" -> { - val jarPath = resourceUrl.path.substringBefore("!") - val jarFile = JarFile(File(jarPath.substringAfter("file:"))) - val entries = jarFile.entries() - - while (entries.hasMoreElements()) { - val entry = entries.nextElement() - if (entry.name.startsWith(path.substring(1)) && !entry.isDirectory) { - resources.add("/${entry.name}") - } - } - jarFile.close() - } - } - } - - return resources - } - - val resources = listResources("/project/$IOS_APP_MODULE") - resources.forEach { resourcePath -> - val targetPath = resourcePath.removePrefix("/project/$IOS_APP_MODULE/") - val targetFile = targetDir.resolve(targetPath) - copyResource(resourcePath, targetFile) - - // Replace placeholders in text files - if (targetFile.name.endsWith(".swift") || - targetFile.name.endsWith(".h") || - targetFile.name.endsWith(".m") || - targetFile.name.endsWith( - ".pbxproj", - ) || - targetFile.name.endsWith(".xcconfig")) { - try { - val content = targetFile.readText() - var updatedContent = content.replace("{{module_name}}", moduleName) - updatedContent = updatedContent.replace("{{ios_binary_name}}", toCamelCase(moduleName)) - updatedContent = updatedContent.replace("{{target_name}}", "$IOS_APP_MODULE.app") - // For target command, use hardcoded defaults since appName/namespace aren't in scope - updatedContent = updatedContent.replace("{{app_name}}", "My App") - updatedContent = updatedContent.replace("{{namespace}}", "com.example.app") - if (content != updatedContent) { - targetFile.writeText(updatedContent) - } - } catch (e: Exception) { - // Skip binary files - } - } - } - } -} - val gradleScript: String get() { return if (System.getProperty("os.name").lowercase().contains("win")) { diff --git a/cli/src/jvmTest/kotlin/com/composables/cli/CliTest.kt b/cli/src/jvmTest/kotlin/com/composables/cli/CliTest.kt index 0a8867b..d0f9c52 100644 --- a/cli/src/jvmTest/kotlin/com/composables/cli/CliTest.kt +++ b/cli/src/jvmTest/kotlin/com/composables/cli/CliTest.kt @@ -336,60 +336,6 @@ class CliTest { } } - @Test - fun `target command detects current android target shape`() { - withTempDir { targetDir -> - val buildFile = - File(targetDir, "build.gradle.kts").apply { - writeText( - """ - kotlin { - android { - namespace = "com.example.shared" - } - } - """ - .trimIndent(), - ) - } - - assertThat(hasAndroidTarget(buildFile)).isTrue() - } - } - - @Test - fun `target command ignores legacy android target shapes`() { - withTempDir { targetDir -> - val androidTargetFile = - File(targetDir, "android-target.gradle.kts").apply { - writeText( - """ - kotlin { - androidTarget() - } - """ - .trimIndent(), - ) - } - val androidLibraryFile = - File(targetDir, "android-library.gradle.kts").apply { - writeText( - """ - kotlin { - androidLibrary { - namespace = "com.example.shared" - } - } - """ - .trimIndent(), - ) - } - - assertThat(hasAndroidTarget(androidTargetFile)).isFalse() - assertThat(hasAndroidTarget(androidLibraryFile)).isFalse() - } - } - @Test fun `gradleScript uses batch file on windows`() { withOsName("Windows 11") { assertThat(gradleScript).isEqualTo("gradlew.bat") } @@ -679,11 +625,5 @@ class CliTest { } } - private fun hasAndroidTarget(buildFile: File): Boolean { - val method = Target::class.java.getDeclaredMethod("hasAndroidTarget", File::class.java) - method.isAccessible = true - return method.invoke(Target(), buildFile) as Boolean - } - private fun String.countOccurrences(value: String): Int = split(value).size - 1 }