diff --git a/cli/src/main/kotlin/com/mitteloupe/cag/cli/AppArgumentProcessor.kt b/cli/src/main/kotlin/com/mitteloupe/cag/cli/AppArgumentProcessor.kt index 74388e9..d44c2f3 100644 --- a/cli/src/main/kotlin/com/mitteloupe/cag/cli/AppArgumentProcessor.kt +++ b/cli/src/main/kotlin/com/mitteloupe/cag/cli/AppArgumentProcessor.kt @@ -126,6 +126,7 @@ class AppArgumentProcessor( .parsePrimaryWithSecondaries(arguments = arguments, primaryFlag = NewArchitecturePrimary) .map { secondaries -> ArchitectureRequest( + enableHilt = true, enableCompose = !secondaries.containsKey(SecondaryFlagConstants.NO_COMPOSE), enableKtlint = secondaries.containsKey(SecondaryFlagConstants.KTLINT), enableDetekt = secondaries.containsKey(SecondaryFlagConstants.DETEKT), @@ -141,6 +142,7 @@ class AppArgumentProcessor( ProjectTemplateRequest( projectName = secondaries[SecondaryFlagConstants.NAME].orEmpty(), packageName = secondaries[SecondaryFlagConstants.PACKAGE].orEmpty(), + enableHilt = true, enableCompose = !secondaries.containsKey(SecondaryFlagConstants.NO_COMPOSE), enableKtlint = secondaries.containsKey(SecondaryFlagConstants.KTLINT), enableDetekt = secondaries.containsKey(SecondaryFlagConstants.DETEKT), diff --git a/cli/src/main/kotlin/com/mitteloupe/cag/cli/Main.kt b/cli/src/main/kotlin/com/mitteloupe/cag/cli/Main.kt index 9624702..5b4e0bf 100644 --- a/cli/src/main/kotlin/com/mitteloupe/cag/cli/Main.kt +++ b/cli/src/main/kotlin/com/mitteloupe/cag/cli/Main.kt @@ -1,8 +1,9 @@ package com.mitteloupe.cag.cli -import com.mitteloupe.cag.cli.HelpContent.USAGE_SYNTAX import com.mitteloupe.cag.cli.configuration.ClientConfigurationLoader import com.mitteloupe.cag.cli.filesystem.CliFileSystemBridge +import com.mitteloupe.cag.cli.help.printHelpMessage +import com.mitteloupe.cag.cli.help.printUsageMessage import com.mitteloupe.cag.core.GenerationException import com.mitteloupe.cag.core.Generator import com.mitteloupe.cag.core.GeneratorFactory @@ -87,6 +88,7 @@ fun main(arguments: Array) { packageName = request.packageName, overrideMinimumAndroidSdk = null, overrideAndroidGradlePluginVersion = null, + enableHilt = request.enableHilt, enableCompose = request.enableCompose, enableKtlint = request.enableKtlint, enableDetekt = request.enableDetekt, @@ -116,6 +118,7 @@ fun main(arguments: Array) { GenerateArchitectureRequest( destinationRootDirectory = destinationRootDirectory, architecturePackageName = architecturePackageName, + enableHilt = request.enableHilt, enableCompose = request.enableCompose, enableKtlint = request.enableKtlint, enableDetekt = request.enableDetekt @@ -239,98 +242,6 @@ private fun String?.toDirectory(destinationRootDirectory: File) = } } -private fun printUsageMessage() { - println( - """ - $USAGE_SYNTAX - - Run with --help or -h for more options. - """.trimIndent() - ) -} - -private fun printHelpMessage() { - println( - """ - $USAGE_SYNTAX - - Note: You must use either long form (--flag) or short form (-f) arguments consistently throughout your command. Mixing both forms is not allowed. - - Options: - --new-project | -np - Generate a complete Clean Architecture project template - --name=ProjectName | -n=ProjectName | -n ProjectName | -nProjectName - Specify the project name (required) - --package=PackageName | --package PackageName | -p=PackageName | -p PackageName | -pPackageName - Specify the package name (required) - --no-compose | -nc - Disable Compose support for the project - --ktlint | -kl - Enable ktlint for the project - --detekt | -d - Enable detekt for the project - --ktor | -kt - Enable Ktor for data sources - --retrofit | -rt - Enable Retrofit for data sources - --new-architecture | -na - Generate a new Clean Architecture package with domain, presentation, and UI layers - --no-compose | -nc - Disable Compose support for the preceding architecture package - --ktlint | -kl - Enable ktlint for the preceding architecture package - --detekt | -d - Enable detekt for the preceding architecture package - --new-feature | -nf - Generate a new feature - --name=FeatureName | -n=FeatureName | -n FeatureName | -nFeatureName - Specify the feature name (required) - --package=PackageName | --package PackageName | -p=PackageName | -p PackageName | -pPackageName - Override the feature package for the preceding feature - --ktlint | -kl - Enable ktlint for the preceding feature (adds plugin and .editorconfig if missing) - --detekt | -d - Enable detekt for the preceding feature (adds plugin and detekt.yml if missing) - --new-datasource | -nds - Generate a new data source - --name=DataSourceName | -n=DataSourceName | -n DataSourceName | -nDataSourceName - Specify the data source name (required, DataSource suffix will be added automatically) - --with=ktor|retrofit|ktor,retrofit | -w=ktor|retrofit|ktor,retrofit - Attach dependencies to the preceding new data source - --new-use-case | -nuc - Generate a new use case - --name=UseCaseName | -n=UseCaseName | -n UseCaseName | -nUseCaseName - Specify the use case name (required) - --path=TargetPath | --path TargetPath | -p=TargetPath | -p TargetPath | -pTargetPath - Specify the target directory for the preceding use case - --new-view-model | -nvm - Generate a new ViewModel - --name=ViewModelName | -n=ViewModelName | -n ViewModelName | -nViewModelName - Specify the ViewModel name (required) - --path=TargetPath | --path TargetPath | -p=TargetPath | -p TargetPath | -pTargetPath - Specify the target directory for the preceding ViewModel - --help, -h - Show this help message and exit - """.trimIndent() - ) -} - -private fun printHelpMessage(topic: String?) { - val normalized = topic?.lowercase()?.trim() - if (normalized.isNullOrEmpty() || normalized == "all" || normalized == "overview") { - printHelpMessage() - return - } - val sections = HelpContent.helpSections() - val content = sections[normalized] - if (content != null) { - println(content) - } else { - println("Unknown help topic: $topic\nAvailable topics: ${sections.keys.sorted().joinToString(", ")}\n") - printHelpMessage() - } -} - private fun produceGenerator(): Generator = GeneratorFactory(CliFileSystemBridge()).create() private fun executeAndReport(operation: () -> Unit) = diff --git a/cli/src/main/kotlin/com/mitteloupe/cag/cli/ManPagePrinter.kt b/cli/src/main/kotlin/com/mitteloupe/cag/cli/ManPagePrinter.kt index 776baf4..03c71fc 100644 --- a/cli/src/main/kotlin/com/mitteloupe/cag/cli/ManPagePrinter.kt +++ b/cli/src/main/kotlin/com/mitteloupe/cag/cli/ManPagePrinter.kt @@ -1,5 +1,7 @@ package com.mitteloupe.cag.cli +import com.mitteloupe.cag.cli.help.HelpContent + object ManPagePrinter { fun printManPage(topic: String?) { val name = "cag" diff --git a/cli/src/main/kotlin/com/mitteloupe/cag/cli/HelpContent.kt b/cli/src/main/kotlin/com/mitteloupe/cag/cli/help/HelpContent.kt similarity index 99% rename from cli/src/main/kotlin/com/mitteloupe/cag/cli/HelpContent.kt rename to cli/src/main/kotlin/com/mitteloupe/cag/cli/help/HelpContent.kt index 1c5c690..6c37d97 100644 --- a/cli/src/main/kotlin/com/mitteloupe/cag/cli/HelpContent.kt +++ b/cli/src/main/kotlin/com/mitteloupe/cag/cli/help/HelpContent.kt @@ -1,4 +1,4 @@ -package com.mitteloupe.cag.cli +package com.mitteloupe.cag.cli.help object HelpContent { private const val NEW_PROJECT_SYNTAX = diff --git a/cli/src/main/kotlin/com/mitteloupe/cag/cli/help/HelpPrinter.kt b/cli/src/main/kotlin/com/mitteloupe/cag/cli/help/HelpPrinter.kt new file mode 100644 index 0000000..89cfc8d --- /dev/null +++ b/cli/src/main/kotlin/com/mitteloupe/cag/cli/help/HelpPrinter.kt @@ -0,0 +1,95 @@ +package com.mitteloupe.cag.cli.help + +import com.mitteloupe.cag.cli.help.HelpContent.USAGE_SYNTAX + +fun printUsageMessage() { + println( + """ + $USAGE_SYNTAX + + Run with --help or -h for more options. + """.trimIndent() + ) +} + +fun printHelpMessage() { + println( + """ + $USAGE_SYNTAX + + Note: You must use either long form (--flag) or short form (-f) arguments consistently throughout your command. Mixing both forms is not allowed. + + Options: + --new-project | -np + Generate a complete Clean Architecture project template + --name=ProjectName | -n=ProjectName | -n ProjectName | -nProjectName + Specify the project name (required) + --package=PackageName | --package PackageName | -p=PackageName | -p PackageName | -pPackageName + Specify the package name (required) + --no-compose | -nc + Disable Compose support for the project + --ktlint | -kl + Enable ktlint for the project + --detekt | -d + Enable detekt for the project + --ktor | -kt + Enable Ktor for data sources + --retrofit | -rt + Enable Retrofit for data sources + --new-architecture | -na + Generate a new Clean Architecture package with domain, presentation, and UI layers + --no-compose | -nc + Disable Compose support for the preceding architecture package + --ktlint | -kl + Enable ktlint for the preceding architecture package + --detekt | -d + Enable detekt for the preceding architecture package + --new-feature | -nf + Generate a new feature + --name=FeatureName | -n=FeatureName | -n FeatureName | -nFeatureName + Specify the feature name (required) + --package=PackageName | --package PackageName | -p=PackageName | -p PackageName | -pPackageName + Override the feature package for the preceding feature + --ktlint | -kl + Enable ktlint for the preceding feature (adds plugin and .editorconfig if missing) + --detekt | -d + Enable detekt for the preceding feature (adds plugin and detekt.yml if missing) + --new-datasource | -nds + Generate a new data source + --name=DataSourceName | -n=DataSourceName | -n DataSourceName | -nDataSourceName + Specify the data source name (required, DataSource suffix will be added automatically) + --with=ktor|retrofit|ktor,retrofit | -w=ktor|retrofit|ktor,retrofit + Attach dependencies to the preceding new data source + --new-use-case | -nuc + Generate a new use case + --name=UseCaseName | -n=UseCaseName | -n UseCaseName | -nUseCaseName + Specify the use case name (required) + --path=TargetPath | --path TargetPath | -p=TargetPath | -p TargetPath | -pTargetPath + Specify the target directory for the preceding use case + --new-view-model | -nvm + Generate a new ViewModel + --name=ViewModelName | -n=ViewModelName | -n ViewModelName | -nViewModelName + Specify the ViewModel name (required) + --path=TargetPath | --path TargetPath | -p=TargetPath | -p TargetPath | -pTargetPath + Specify the target directory for the preceding ViewModel + --help, -h + Show this help message and exit + """.trimIndent() + ) +} + +fun printHelpMessage(topic: String?) { + val normalized = topic?.lowercase()?.trim() + if (normalized.isNullOrEmpty() || normalized == "all" || normalized == "overview") { + printHelpMessage() + return + } + val sections = HelpContent.helpSections() + val content = sections[normalized] + if (content != null) { + println(content) + } else { + println("Unknown help topic: $topic\nAvailable topics: ${sections.keys.sorted().joinToString(", ")}\n") + printHelpMessage() + } +} diff --git a/cli/src/main/kotlin/com/mitteloupe/cag/cli/request/ArchitectureRequest.kt b/cli/src/main/kotlin/com/mitteloupe/cag/cli/request/ArchitectureRequest.kt index 912855d..e63fc5a 100644 --- a/cli/src/main/kotlin/com/mitteloupe/cag/cli/request/ArchitectureRequest.kt +++ b/cli/src/main/kotlin/com/mitteloupe/cag/cli/request/ArchitectureRequest.kt @@ -1,8 +1,9 @@ package com.mitteloupe.cag.cli.request data class ArchitectureRequest( - val enableCompose: Boolean = true, - val enableKtlint: Boolean = false, - val enableDetekt: Boolean = false, - val enableGit: Boolean = false + val enableHilt: Boolean, + val enableCompose: Boolean, + val enableKtlint: Boolean, + val enableDetekt: Boolean, + val enableGit: Boolean ) diff --git a/cli/src/main/kotlin/com/mitteloupe/cag/cli/request/ProjectTemplateRequest.kt b/cli/src/main/kotlin/com/mitteloupe/cag/cli/request/ProjectTemplateRequest.kt index ec0cae0..c8cbfa7 100644 --- a/cli/src/main/kotlin/com/mitteloupe/cag/cli/request/ProjectTemplateRequest.kt +++ b/cli/src/main/kotlin/com/mitteloupe/cag/cli/request/ProjectTemplateRequest.kt @@ -3,10 +3,11 @@ package com.mitteloupe.cag.cli.request data class ProjectTemplateRequest( val projectName: String, val packageName: String, - val enableCompose: Boolean = true, - val enableKtlint: Boolean = false, - val enableDetekt: Boolean = false, - val enableKtor: Boolean = false, - val enableRetrofit: Boolean = false, - val enableGit: Boolean = false + val enableHilt: Boolean, + val enableCompose: Boolean, + val enableKtlint: Boolean, + val enableDetekt: Boolean, + val enableKtor: Boolean, + val enableRetrofit: Boolean, + val enableGit: Boolean ) diff --git a/cli/src/test/kotlin/com/mitteloupe/cag/cli/AppArgumentProcessorTest.kt b/cli/src/test/kotlin/com/mitteloupe/cag/cli/AppArgumentProcessorTest.kt index 607463a..58b234f 100644 --- a/cli/src/test/kotlin/com/mitteloupe/cag/cli/AppArgumentProcessorTest.kt +++ b/cli/src/test/kotlin/com/mitteloupe/cag/cli/AppArgumentProcessorTest.kt @@ -750,11 +750,13 @@ class AppArgumentProcessorTest { ProjectTemplateRequest( projectName = "MyApp", packageName = "com.example", + enableHilt = true, enableCompose = true, enableKtlint = true, enableDetekt = true, enableKtor = true, - enableRetrofit = true + enableRetrofit = true, + enableGit = false ) // When @@ -772,11 +774,13 @@ class AppArgumentProcessorTest { ProjectTemplateRequest( projectName = "TestApp", packageName = "com.test", + enableHilt = true, enableCompose = false, enableKtlint = true, enableDetekt = true, enableKtor = true, - enableRetrofit = true + enableRetrofit = true, + enableGit = false ) // When @@ -794,11 +798,13 @@ class AppArgumentProcessorTest { ProjectTemplateRequest( projectName = "MinimalApp", packageName = "", + enableHilt = true, enableCompose = true, enableKtlint = false, enableDetekt = false, enableKtor = false, - enableRetrofit = false + enableRetrofit = false, + enableGit = false ) // When @@ -816,11 +822,13 @@ class AppArgumentProcessorTest { ProjectTemplateRequest( projectName = "NoComposeApp", packageName = "", + enableHilt = true, enableCompose = false, enableKtlint = false, enableDetekt = false, enableKtor = false, - enableRetrofit = false + enableRetrofit = false, + enableGit = false ) // When @@ -838,21 +846,25 @@ class AppArgumentProcessorTest { ProjectTemplateRequest( projectName = "First", packageName = "com.first", + enableHilt = true, enableCompose = true, enableKtlint = false, enableDetekt = false, enableKtor = false, - enableRetrofit = false + enableRetrofit = false, + enableGit = false ) val expectedRequest2 = ProjectTemplateRequest( projectName = "Second", packageName = "", + enableHilt = true, enableCompose = true, enableKtlint = false, enableDetekt = false, enableKtor = false, - enableRetrofit = false + enableRetrofit = false, + enableGit = false ) // When @@ -968,6 +980,7 @@ class AppArgumentProcessorTest { ProjectTemplateRequest( projectName = "GitApp", packageName = "", + enableHilt = true, enableCompose = true, enableKtlint = false, enableDetekt = false, diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/Generator.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/Generator.kt index dc9d1bf..d25abf4 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/Generator.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/Generator.kt @@ -83,6 +83,7 @@ class Generator( architectureFilesGenerator.generateArchitecture( destinationRootDirectory = request.destinationRootDirectory, architecturePackageName = request.architecturePackageName, + enableHilt = request.enableHilt, enableCompose = request.enableCompose, enableKtlint = request.enableKtlint, enableDetekt = request.enableDetekt @@ -96,6 +97,7 @@ class Generator( packageName = request.packageName, overrideMinimumAndroidSdk = request.overrideMinimumAndroidSdk, overrideAndroidGradlePluginVersion = request.overrideAndroidGradlePluginVersion, + enableHilt = request.enableHilt, enableCompose = request.enableCompose, enableKtlint = request.enableKtlint, enableDetekt = request.enableDetekt, diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/content/AppGradleBuilder.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/content/AppGradleBuilder.kt index 306425a..0618ef4 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/content/AppGradleBuilder.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/content/AppGradleBuilder.kt @@ -7,6 +7,7 @@ import com.mitteloupe.cag.core.generation.versioncatalog.asAccessor fun buildAppGradleScript( packageName: String, + enableHilt: Boolean, enableCompose: Boolean, catalog: VersionCatalogReader ): String { @@ -55,7 +56,14 @@ fun buildAppGradleScript( val aliasAndroidApplication = catalog.getResolvedPluginAliasFor(PluginConstants.ANDROID_APPLICATION).asAccessor val aliasKotlinAndroid = catalog.getResolvedPluginAliasFor(PluginConstants.KOTLIN_ANDROID).asAccessor val aliasKsp = catalog.getResolvedPluginAliasFor(PluginConstants.KSP).asAccessor - val aliasPluginHilt = catalog.getResolvedPluginAliasFor(PluginConstants.HILT_ANDROID).asAccessor + val hiltPlugin = + if (enableHilt) { + val aliasPluginHilt = catalog.getResolvedPluginAliasFor(PluginConstants.HILT_ANDROID).asAccessor + """ + alias(libs.plugins.$aliasPluginHilt)""" + } else { + "" + } val aliasMaterial = catalog.getResolvedLibraryAliasForModule(LibraryConstants.MATERIAL).asAccessor val aliasCoreKtx = catalog.getResolvedLibraryAliasForModule(LibraryConstants.ANDROIDX_CORE_KTX).asAccessor val aliasLifecycleRuntimeKtx = catalog.getResolvedLibraryAliasForModule(LibraryConstants.ANDROIDX_LIFECYCLE_RUNTIME_KTX).asAccessor @@ -71,8 +79,7 @@ fun buildAppGradleScript( plugins { alias(libs.plugins.$aliasAndroidApplication) alias(libs.plugins.$aliasKotlinAndroid) - alias(libs.plugins.$aliasKsp) - alias(libs.plugins.$aliasPluginHilt)$composePlugins + alias(libs.plugins.$aliasKsp)$hiltPlugin$composePlugins } kotlin { diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/content/ProjectGradleScriptBuilder.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/content/ProjectGradleScriptBuilder.kt index 745b353..337c780 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/content/ProjectGradleScriptBuilder.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/content/ProjectGradleScriptBuilder.kt @@ -6,6 +6,7 @@ import com.mitteloupe.cag.core.generation.versioncatalog.VersionCatalogReader import com.mitteloupe.cag.core.generation.versioncatalog.asAccessor fun buildProjectGradleScript( + enableHilt: Boolean, enableKtlint: Boolean, enableDetekt: Boolean, catalog: VersionCatalogReader @@ -43,9 +44,15 @@ fun buildProjectGradleScript( val aliasAndroidLibrary = catalog.getResolvedPluginAliasFor(PluginConstants.ANDROID_LIBRARY).asAccessor val aliasKotlinAndroid = catalog.getResolvedPluginAliasFor(PluginConstants.KOTLIN_ANDROID).asAccessor val aliasKotlinJvm = catalog.getResolvedPluginAliasFor(PluginConstants.KOTLIN_JVM).asAccessor - val aliasHilt = catalog.getResolvedPluginAliasFor(PluginConstants.HILT_ANDROID).asAccessor val aliasKsp = catalog.getResolvedPluginAliasFor(PluginConstants.KSP).asAccessor - + val hiltPlugin = + if (enableHilt) { + val aliasHilt = catalog.getResolvedPluginAliasFor(PluginConstants.HILT_ANDROID).asAccessor + """ + alias(libs.plugins.$aliasHilt) apply false""" + } else { + "" + } return """ // Top-level build file where you can add configuration options common to all sub-projects/modules. import org.jetbrains.kotlin.gradle.dsl.JvmTarget @@ -55,8 +62,7 @@ fun buildProjectGradleScript( alias(libs.plugins.$aliasAndroidApplication) apply false alias(libs.plugins.$aliasAndroidLibrary) apply false alias(libs.plugins.$aliasKotlinAndroid) apply false - alias(libs.plugins.$aliasKotlinJvm) apply false - alias(libs.plugins.$aliasHilt) apply false + alias(libs.plugins.$aliasKotlinJvm) apply false$hiltPlugin alias(libs.plugins.$aliasKsp) apply false$ktlintPlugins$detektPlugins } diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/content/architecture/ArchitectureInstrumentationTestGradleScriptBuilder.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/content/architecture/ArchitectureInstrumentationTestGradleScriptBuilder.kt index 8eb894e..92aa991 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/content/architecture/ArchitectureInstrumentationTestGradleScriptBuilder.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/content/architecture/ArchitectureInstrumentationTestGradleScriptBuilder.kt @@ -8,6 +8,7 @@ import com.mitteloupe.cag.core.generation.versioncatalog.asAccessor fun buildArchitectureInstrumentationTestGradleScript( architecturePackageName: String, + enableHilt: Boolean, catalog: VersionCatalogReader ): String { val aliasAndroidLibrary = catalog.getResolvedPluginAliasFor(PluginConstants.ANDROID_LIBRARY).asAccessor @@ -23,7 +24,6 @@ fun buildArchitectureInstrumentationTestGradleScript( val aliasTestAndroidxJunit = catalog.getResolvedLibraryAliasForModule(LibraryConstants.TEST_ANDROIDX_JUNIT).asAccessor val aliasTestAndroidxEspressoCore = catalog.getResolvedLibraryAliasForModule(LibraryConstants.TEST_ANDROIDX_ESPRESSO_CORE).asAccessor val aliasTestComposeUiJunit4 = catalog.getResolvedLibraryAliasForModule(LibraryConstants.TEST_COMPOSE_UI_JUNIT4).asAccessor - val aliasTestAndroidHilt = catalog.getResolvedLibraryAliasForModule(LibraryConstants.TEST_ANDROID_HILT).asAccessor val aliasTestAndroidUiAutomator = catalog.getResolvedLibraryAliasForModule(LibraryConstants.TEST_ANDROID_UI_AUTOMATOR).asAccessor val aliasOkhttp3 = catalog.getResolvedLibraryAliasForModule(LibraryConstants.OKHTTP3).asAccessor val aliasTestAndroidMockWebServer = catalog.getResolvedLibraryAliasForModule(LibraryConstants.TEST_ANDROID_MOCKWEBSERVER).asAccessor @@ -39,6 +39,14 @@ fun buildArchitectureInstrumentationTestGradleScript( val detektConfiguration = gradleFileExtender.buildDetektConfiguration(catalog) val configurations = "$ktlintConfiguration$detektConfiguration".trimIndent() + val hiltDependency = + if (enableHilt) { + val aliasTestAndroidHilt = catalog.getResolvedLibraryAliasForModule(LibraryConstants.TEST_ANDROID_HILT).asAccessor + """ + implementation(libs.$aliasTestAndroidHilt)""" + } else { + "" + } return """plugins { alias(libs.plugins.$aliasAndroidLibrary) alias(libs.plugins.$aliasKotlinAndroid)$composePluginLine$ktlintPluginLine$detektPluginLine @@ -93,8 +101,7 @@ dependencies { implementation(libs.$aliasTestJunit) implementation(libs.$aliasTestAndroidxJunit) implementation(libs.$aliasTestAndroidxEspressoCore) - implementation(libs.$aliasTestComposeUiJunit4) - implementation(libs.$aliasTestAndroidHilt) + implementation(libs.$aliasTestComposeUiJunit4)$hiltDependency implementation(libs.$aliasTestAndroidUiAutomator) implementation(libs.$aliasTestAndroidxEspressoCore) implementation(libs.$aliasOkhttp3) diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/generation/architecture/ArchitectureModulesContentGenerator.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/generation/architecture/ArchitectureModulesContentGenerator.kt index 0b74f13..1116bd3 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/generation/architecture/ArchitectureModulesContentGenerator.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/generation/architecture/ArchitectureModulesContentGenerator.kt @@ -28,9 +28,10 @@ class ArchitectureModulesContentGenerator( fun generate( architectureRoot: File, architecturePackageName: String, + enableHilt: Boolean, enableCompose: Boolean, - enableKtlint: Boolean = false, - enableDetekt: Boolean = false + enableKtlint: Boolean, + enableDetekt: Boolean ) { val packageSegments = architecturePackageName.toSegments() if (packageSegments.isEmpty()) { @@ -54,22 +55,30 @@ class ArchitectureModulesContentGenerator( } val libraries = - LibraryConstants.CORE_ANDROID_LIBRARIES + - LibraryConstants.HILT_LIBRARIES + - LibraryConstants.TESTING_LIBRARIES + - LibraryConstants.TEST_KOTLINX_COROUTINES + - LibraryConstants.NETWORK_LIBRARIES + - LibraryConstants.TEST_MOCKITO_LIBRARIES + - LibraryConstants.TEST_MOCKITO_ANDROID + - if (enableCompose) { - LibraryConstants.COMPOSE_LIBRARIES + - LibraryConstants.COMPOSE_TESTING_LIBRARIES + - LibraryConstants.ANDROIDX_RECYCLERVIEW + - LibraryConstants.ANDROIDX_FRAGMENT_KTX + - LibraryConstants.ANDROIDX_NAVIGATION_FRAGMENT_KTX - } else { - LibraryConstants.VIEW_LIBRARIES + buildList { + addAll( + LibraryConstants.CORE_ANDROID_LIBRARIES + + LibraryConstants.TESTING_LIBRARIES + + LibraryConstants.TEST_KOTLINX_COROUTINES + + LibraryConstants.NETWORK_LIBRARIES + + LibraryConstants.TEST_MOCKITO_LIBRARIES + + LibraryConstants.TEST_MOCKITO_ANDROID + ) + if (enableHilt) { + addAll(LibraryConstants.HILT_LIBRARIES) } + addAll( + if (enableCompose) { + LibraryConstants.COMPOSE_LIBRARIES + + LibraryConstants.COMPOSE_TESTING_LIBRARIES + + LibraryConstants.ANDROIDX_RECYCLERVIEW + + LibraryConstants.ANDROIDX_FRAGMENT_KTX + + LibraryConstants.ANDROIDX_NAVIGATION_FRAGMENT_KTX + } else { + LibraryConstants.VIEW_LIBRARIES + } + ) + } val plugins = buildList { addAll(PluginConstants.KOTLIN_PLUGINS + PluginConstants.ANDROID_PLUGINS) @@ -116,7 +125,13 @@ class ArchitectureModulesContentGenerator( gradleFileCreator.writeGradleFileIfMissing( featureRoot = architectureRoot, layer = "instrumentation-test" - ) { buildArchitectureInstrumentationTestGradleScript(architecturePackageName, catalogUpdater) } + ) { + buildArchitectureInstrumentationTestGradleScript( + architecturePackageName = architecturePackageName, + enableHilt = enableHilt, + catalog = catalogUpdater + ) + } val domainRoot = File(architectureRoot, "domain") domainModuleCreator.generateDomainContent( @@ -142,9 +157,10 @@ class ArchitectureModulesContentGenerator( uiModuleCreator.generateUiContent(uiRoot, architecturePackageName, packageSegments + "ui") val instrumentationTestRoot = File(architectureRoot, "instrumentation-test") instrumentationTestModuleCreator.generateInstrumentationTestContent( - instrumentationTestRoot, - architecturePackageName.substringBeforeLast('.'), - architecturePackageName.substringBeforeLast('.').toSegments() + "test" + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName.substringBeforeLast('.'), + architecturePackageNameSegments = architecturePackageName.substringBeforeLast('.').toSegments() + "test", + enableHilt = enableHilt ) } } diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/generation/architecture/InstrumentationTestModuleCreator.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/generation/architecture/InstrumentationTestModuleCreator.kt index 83dfc43..357ae21 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/generation/architecture/InstrumentationTestModuleCreator.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/generation/architecture/InstrumentationTestModuleCreator.kt @@ -9,7 +9,8 @@ class InstrumentationTestModuleCreator internal constructor() { fun generateInstrumentationTestContent( architectureRoot: File, architecturePackageName: String, - architecturePackageNameSegments: List + architecturePackageNameSegments: List, + enableHilt: Boolean ) { val codeRoot = File(architectureRoot, "src/main/java") val packageDirectory = buildPackageDirectory(codeRoot, architecturePackageNameSegments) @@ -28,7 +29,9 @@ class InstrumentationTestModuleCreator internal constructor() { generateKeyValueStore(packageDirectory, architecturePackageName) generateWithBackgroundColorMatcher(packageDirectory, architecturePackageName) generateWithDrawableIdMatcher(packageDirectory, architecturePackageName) - generateHiltInjectorRule(packageDirectory, architecturePackageName) + if (enableHilt) { + generateHiltInjectorRule(packageDirectory, architecturePackageName) + } generateLocalStoreRule(packageDirectory, architecturePackageName) generateScreenshotFailureRule(packageDirectory, architecturePackageName) generateSdkAwareGrantPermissionRule(packageDirectory, architecturePackageName) diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/generation/bulk/ArchitectureFilesGenerator.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/generation/bulk/ArchitectureFilesGenerator.kt index ca50092..fa88102 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/generation/bulk/ArchitectureFilesGenerator.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/generation/bulk/ArchitectureFilesGenerator.kt @@ -19,6 +19,7 @@ class ArchitectureFilesGenerator( fun generateArchitecture( destinationRootDirectory: File, architecturePackageName: String, + enableHilt: Boolean, enableCompose: Boolean, enableKtlint: Boolean, enableDetekt: Boolean @@ -59,6 +60,7 @@ class ArchitectureFilesGenerator( .generate( architectureRoot = architectureRoot, architecturePackageName = architecturePackageName, + enableHilt = enableHilt, enableCompose = enableCompose, enableKtlint = enableKtlint, enableDetekt = enableDetekt diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/generation/bulk/ProjectTemplateFilesGenerator.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/generation/bulk/ProjectTemplateFilesGenerator.kt index 7b02681..1a0ad6d 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/generation/bulk/ProjectTemplateFilesGenerator.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/generation/bulk/ProjectTemplateFilesGenerator.kt @@ -35,6 +35,7 @@ class ProjectTemplateFilesGenerator( packageName: String, overrideMinimumAndroidSdk: Int?, overrideAndroidGradlePluginVersion: String?, + enableHilt: Boolean, enableCompose: Boolean, enableKtlint: Boolean, enableDetekt: Boolean, @@ -122,6 +123,7 @@ class ProjectTemplateFilesGenerator( architectureFilesGenerator.generateArchitecture( destinationRootDirectory = projectRoot, architecturePackageName = "$packageName.architecture", + enableHilt = enableHilt, enableCompose = enableCompose, enableKtlint = enableKtlint, enableDetekt = enableDetekt @@ -151,6 +153,7 @@ class ProjectTemplateFilesGenerator( generateTemplateProjectGradleFiles( projectRoot = projectRoot, packageName = packageName, + enableHilt = enableHilt, enableCompose = enableCompose, enableKtlint = enableKtlint, enableDetekt = enableDetekt @@ -191,12 +194,14 @@ class ProjectTemplateFilesGenerator( private fun generateTemplateProjectGradleFiles( projectRoot: File, packageName: String, + enableHilt: Boolean, enableCompose: Boolean, enableKtlint: Boolean, enableDetekt: Boolean ) { gradleFileCreator.writeProjectGradleFile( projectRoot = projectRoot, + enableHilt = enableHilt, enableKtlint = enableKtlint, enableDetekt = enableDetekt, catalog = catalogUpdater @@ -205,6 +210,7 @@ class ProjectTemplateFilesGenerator( gradleFileCreator.writeAppGradleFile( projectRoot = projectRoot, packageName = packageName, + enableHilt = enableHilt, enableCompose = enableCompose, catalog = catalogUpdater ) diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/generation/gradle/GradleFileCreator.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/generation/gradle/GradleFileCreator.kt index 800e0c9..0293a77 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/generation/gradle/GradleFileCreator.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/generation/gradle/GradleFileCreator.kt @@ -21,23 +21,32 @@ class GradleFileCreator( fun writeProjectGradleFile( projectRoot: File, + enableHilt: Boolean, enableKtlint: Boolean, enableDetekt: Boolean, catalog: VersionCatalogReader ) { val buildGradleFile = File(projectRoot, "build.gradle.kts") fileCreator.createOrUpdateFile(buildGradleFile) { - buildProjectGradleScript(enableKtlint, enableDetekt, catalog) + buildProjectGradleScript( + enableHilt = enableHilt, + enableKtlint = enableKtlint, + enableDetekt = enableDetekt, + catalog = catalog + ) } } fun writeAppGradleFile( projectRoot: File, packageName: String, + enableHilt: Boolean, enableCompose: Boolean, catalog: VersionCatalogReader ) { val appGradleFile = File(projectRoot, "app/build.gradle.kts") - fileCreator.createOrUpdateFile(appGradleFile) { buildAppGradleScript(packageName, enableCompose, catalog) } + fileCreator.createOrUpdateFile(appGradleFile) { + buildAppGradleScript(packageName, enableHilt, enableCompose, catalog) + } } } diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/request/GenerateArchitectureRequest.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/request/GenerateArchitectureRequest.kt index 2a8e21a..7a9438e 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/request/GenerateArchitectureRequest.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/request/GenerateArchitectureRequest.kt @@ -5,7 +5,8 @@ import java.io.File data class GenerateArchitectureRequest( val destinationRootDirectory: File, val architecturePackageName: String, - val enableCompose: Boolean = true, - val enableKtlint: Boolean = false, - val enableDetekt: Boolean = false + val enableHilt: Boolean, + val enableCompose: Boolean, + val enableKtlint: Boolean, + val enableDetekt: Boolean ) diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/request/GenerateProjectTemplateRequest.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/request/GenerateProjectTemplateRequest.kt index 49e3286..96d4661 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/request/GenerateProjectTemplateRequest.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/request/GenerateProjectTemplateRequest.kt @@ -8,6 +8,7 @@ data class GenerateProjectTemplateRequest( val packageName: String, val overrideMinimumAndroidSdk: Int?, val overrideAndroidGradlePluginVersion: String?, + val enableHilt: Boolean, val enableCompose: Boolean, val enableKtlint: Boolean, val enableDetekt: Boolean, diff --git a/core/src/test/kotlin/com/mitteloupe/cag/core/GeneratorTest.kt b/core/src/test/kotlin/com/mitteloupe/cag/core/GeneratorTest.kt index fe0a634..47e51ef 100644 --- a/core/src/test/kotlin/com/mitteloupe/cag/core/GeneratorTest.kt +++ b/core/src/test/kotlin/com/mitteloupe/cag/core/GeneratorTest.kt @@ -291,7 +291,10 @@ class GeneratorTest { GenerateArchitectureRequest( architecturePackageName = "", destinationRootDirectory = temporaryDirectory, - enableCompose = true + enableHilt = false, + enableCompose = true, + enableKtlint = false, + enableDetekt = false ) // When @@ -307,7 +310,10 @@ class GeneratorTest { GenerateArchitectureRequest( architecturePackageName = "...", destinationRootDirectory = temporaryDirectory, - enableCompose = true + enableHilt = false, + enableCompose = true, + enableKtlint = false, + enableDetekt = false ) // When @@ -325,7 +331,10 @@ class GeneratorTest { GenerateArchitectureRequest( architecturePackageName = "com.example.architecture", destinationRootDirectory = temporaryDirectory, - enableCompose = true + enableHilt = false, + enableCompose = true, + enableKtlint = false, + enableDetekt = false ) // When @@ -341,7 +350,10 @@ class GeneratorTest { GenerateArchitectureRequest( architecturePackageName = "com.example.architecture", destinationRootDirectory = temporaryDirectory, - enableCompose = true + enableHilt = false, + enableCompose = true, + enableKtlint = false, + enableDetekt = false ) // When @@ -365,6 +377,7 @@ class GeneratorTest { GenerateArchitectureRequest( architecturePackageName = "com.example.architecture", destinationRootDirectory = temporaryDirectory, + enableHilt = false, enableCompose = true, enableKtlint = true, enableDetekt = true diff --git a/core/src/test/kotlin/com/mitteloupe/cag/core/generation/architecture/ArchitectureModulesContentGeneratorTest.kt b/core/src/test/kotlin/com/mitteloupe/cag/core/generation/architecture/ArchitectureModulesContentGeneratorTest.kt index 6d3dabd..3ebc905 100644 --- a/core/src/test/kotlin/com/mitteloupe/cag/core/generation/architecture/ArchitectureModulesContentGeneratorTest.kt +++ b/core/src/test/kotlin/com/mitteloupe/cag/core/generation/architecture/ArchitectureModulesContentGeneratorTest.kt @@ -75,7 +75,14 @@ class ArchitectureModulesContentGeneratorTest { val enableCompose = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) // Then throws GenerationException } @@ -88,7 +95,14 @@ class ArchitectureModulesContentGeneratorTest { val enableCompose = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) // Then throws GenerationException } @@ -101,7 +115,14 @@ class ArchitectureModulesContentGeneratorTest { val enableCompose = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) // Then throws GenerationException } @@ -114,7 +135,14 @@ class ArchitectureModulesContentGeneratorTest { val enableCompose = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) // Then verify { @@ -134,7 +162,14 @@ class ArchitectureModulesContentGeneratorTest { val enableCompose = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) // Then verify { @@ -154,7 +189,14 @@ class ArchitectureModulesContentGeneratorTest { val enableCompose = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) // Then verify { @@ -174,7 +216,14 @@ class ArchitectureModulesContentGeneratorTest { val enableCompose = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) // Then verify { @@ -194,14 +243,22 @@ class ArchitectureModulesContentGeneratorTest { val enableCompose = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) // Then verify { instrumentationTestModuleCreator.generateInstrumentationTestContent( architectureRoot = File(architectureRoot, "instrumentation-test"), architecturePackageName = "com.example.architecture", - architecturePackageNameSegments = listOf("com", "example", "architecture", "test") + architecturePackageNameSegments = listOf("com", "example", "architecture", "test"), + enableHilt = true ) } } @@ -214,7 +271,14 @@ class ArchitectureModulesContentGeneratorTest { val enableCompose = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) // Then verify { @@ -249,7 +313,8 @@ class ArchitectureModulesContentGeneratorTest { instrumentationTestModuleCreator.generateInstrumentationTestContent( architectureRoot = File(architectureRoot, "instrumentation-test"), architecturePackageName = "com.example.architecture", - architecturePackageNameSegments = listOf("com", "example", "architecture", "test") + architecturePackageNameSegments = listOf("com", "example", "architecture", "test"), + enableHilt = true ) } } @@ -264,7 +329,14 @@ class ArchitectureModulesContentGeneratorTest { val enableDetekt = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose, enableKtlint, enableDetekt) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableHilt = true, + enableCompose = enableCompose, + enableKtlint = enableKtlint, + enableDetekt = enableDetekt + ) // Then verify { @@ -299,7 +371,8 @@ class ArchitectureModulesContentGeneratorTest { instrumentationTestModuleCreator.generateInstrumentationTestContent( architectureRoot = File(architectureRoot, "instrumentation-test"), architecturePackageName = "com.example.architecture", - architecturePackageNameSegments = listOf("com", "example", "architecture", "test") + architecturePackageNameSegments = listOf("com", "example", "architecture", "test"), + enableHilt = true ) } } @@ -340,7 +413,14 @@ dependencies { val domainGradle = File(architectureRoot, "domain/build.gradle.kts") // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) // Then assertEquals(expectedDomain, domainGradle.readText()) @@ -372,7 +452,14 @@ dependencies { val presentationGradle = File(architectureRoot, "presentation/build.gradle.kts") // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) // Then assertEquals(expectedPresentation, presentationGradle.readText()) @@ -433,7 +520,14 @@ dependencies { val uiGradle = File(architectureRoot, "ui/build.gradle.kts") // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) // Then assertEquals(expectedUi, uiGradle.readText()) @@ -466,7 +560,14 @@ dependencies { val presentationTestGradle = File(architectureRoot, "presentation-test/build.gradle.kts") // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) // Then assertEquals(expectedPresentationTest, presentationTestGradle.readText()) @@ -543,7 +644,96 @@ dependencies { val instrumentationTestGradle = File(architectureRoot, "instrumentation-test/build.gradle.kts") // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = enableCompose, + enableHilt = true, + enableKtlint = false, + enableDetekt = false + ) + + // Then + assertEquals(expectedInstrumentationTest, instrumentationTestGradle.readText()) + } + + @Test + fun `Given no hilt when generate then writes instrumentation test gradle file without hilt`() { + // Given + val architectureRoot = File(temporaryDirectory, "architecture").apply { mkdirs() } + val architecturePackageName = "com.example.architecture" + val enableHilt = false + val expectedInstrumentationTest = """plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) +} + +android { + namespace = "com.example.test" + compileSdk = libs.versions.compileSdk.get().toInt() + + defaultConfig { + minSdk = libs.versions.minSdk.get().toInt() + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + buildFeatures { + compose = true + } +} + +kotlin { + sourceSets.all { + languageSettings.enableLanguageFeature("ExplicitBackingFields") + } +} + +dependencies { + implementation(libs.material) + + implementation(platform(libs.compose.bom)) + implementation(libs.compose.ui) + implementation(libs.compose.ui.graphics) + implementation(libs.compose.ui.tooling.preview) + implementation(libs.compose.material3) + + implementation(libs.test.junit) + implementation(libs.test.androidx.junit) + implementation(libs.test.androidx.espresso.core) + implementation(libs.test.compose.ui.junit4) + implementation(libs.test.android.uiautomator) + implementation(libs.test.androidx.espresso.core) + implementation(libs.okhttp3) + implementation(libs.test.android.mockwebserver) + implementation(libs.androidx.appcompat) + implementation(libs.test.androidx.rules) + implementation(libs.androidx.recyclerview) + implementation(kotlin("reflect")) +} +""" + val instrumentationTestGradle = File(architectureRoot, "instrumentation-test/build.gradle.kts") + + // When + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableCompose = false, + enableHilt = enableHilt, + enableKtlint = false, + enableDetekt = false + ) // Then assertEquals(expectedInstrumentationTest, instrumentationTestGradle.readText()) @@ -1507,7 +1697,12 @@ interface CoroutineContextProvider { val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val baseTestFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/test/BaseTest.kt") @@ -1649,7 +1844,12 @@ abstract class BaseTest { val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val clickChildViewFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/action/ClickChildView.kt") @@ -1703,7 +1903,12 @@ class ClickChildView(private val matcher: Matcher) : ViewAction { val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val serverRequestResponseFile = @@ -1725,7 +1930,12 @@ annotation class ServerRequestResponse(val requestResponseIds: Array) val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val localStoreFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/annotation/LocalStore.kt") @@ -1746,7 +1956,12 @@ annotation class LocalStore(val localStoreDataIds: Array) val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val itemAtPositionMatcherFile = @@ -1783,7 +1998,12 @@ fun matchesItemAtPosition(matcher: Matcher?, position: Int) = val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val assetReaderFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/asset/AssetReader.kt") @@ -1813,7 +2033,12 @@ fun processAssetStream( val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val appNotRespondingHandlerFile = @@ -1880,7 +2105,12 @@ private fun UiDevice.closeAnrWithWait(appNotRespondingDialog: UiObject) { val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val doesNotFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/test/DoesNot.kt") @@ -1908,7 +2138,12 @@ fun doesNot(description: String, block: () -> Unit) { val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val retryFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/test/Retry.kt") @@ -1942,7 +2177,12 @@ fun retry(waitMilliseconds: Long = 200L, repeat: Int = 5, block: () -> Unit) { val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val composeOkHttp3IdlingResourceFile = @@ -1978,7 +2218,12 @@ class ComposeOkHttp3IdlingResource private constructor(dispatcher: Dispatcher) : val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val espressoOkHttp3IdlingResourceFile = @@ -2034,7 +2279,12 @@ class EspressoOkHttp3IdlingResource private constructor( val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val appLauncherFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/launcher/AppLauncher.kt") @@ -2056,7 +2306,12 @@ fun interface AppLauncher { val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val fromComposableFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/launcher/FromComposable.kt") @@ -2094,7 +2349,12 @@ fun fromComposable( val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val keyValueStoreFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/localstore/KeyValueStore.kt") @@ -2131,7 +2391,12 @@ abstract class KeyValueStore { val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val withBackgroundColorMatcherFile = @@ -2191,7 +2456,12 @@ class WithBackgroundColorMatcher( val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val withDrawableIdMatcherFile = @@ -2316,7 +2586,12 @@ class WithDrawableIdMatcher(@param:DrawableRes private val expectedId: Int) : val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val hiltInjectorRuleFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/rule/HiltInjectorRule.kt") @@ -2349,7 +2624,12 @@ class HiltInjectorRule(private val hiltAndroidRule: HiltAndroidRule) : TestRule val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val mockRequestFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/server/MockRequest.kt") @@ -2369,7 +2649,12 @@ data class MockRequest(val url: String) val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val mockResponseFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/server/MockResponse.kt") @@ -2394,7 +2679,12 @@ data class MockResponse( val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val mockRequestResponseFactoryFile = @@ -2424,7 +2714,12 @@ data class MockRequestResponseFactory( val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val mockResponseFactoryFile = @@ -2449,7 +2744,12 @@ interface MockResponseFactory { val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val errorResponseFactoryFile = @@ -2476,7 +2776,12 @@ sealed class ErrorResponseFactory { val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val simpleResponseFactoryFile = @@ -2514,7 +2819,12 @@ data class SimpleResponseFactory( val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val sequenceResponseFactoryFile = @@ -2548,7 +2858,12 @@ class SequenceResponseFactory(private vararg val responses: MockResponseFactory) val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val responseBinderFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/server/ResponseBinder.kt") @@ -2578,7 +2893,12 @@ interface ResponseBinder { val packageSegments = listOf("com", "example", "architecture", "test") // When - classUnderTest.generateInstrumentationTestContent(instrumentationTestRoot, architecturePackageName, packageSegments) + classUnderTest.generateInstrumentationTestContent( + architectureRoot = instrumentationTestRoot, + architecturePackageName = architecturePackageName, + architecturePackageNameSegments = packageSegments, + enableHilt = true + ) // Then val responseStoreFile = File(instrumentationTestRoot, "src/main/java/com/example/architecture/test/server/ResponseStore.kt") @@ -2634,7 +2954,14 @@ abstract class ResponseStore { val enableDetekt = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose, enableKtlint, enableDetekt) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableHilt = true, + enableCompose = enableCompose, + enableKtlint = enableKtlint, + enableDetekt = enableDetekt + ) // Then val buildGradleFile = File(architectureRoot, "domain/build.gradle.kts") @@ -2672,7 +2999,14 @@ dependencies { val enableDetekt = false // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose, enableKtlint, enableDetekt) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableHilt = true, + enableCompose = enableCompose, + enableKtlint = enableKtlint, + enableDetekt = enableDetekt + ) // Then val buildGradleFile = File(architectureRoot, "domain/build.gradle.kts") @@ -2699,7 +3033,14 @@ dependencies { val enableDetekt = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose, enableKtlint, enableDetekt) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableHilt = true, + enableCompose = enableCompose, + enableKtlint = enableKtlint, + enableDetekt = enableDetekt + ) // Then val buildGradleFile = File(architectureRoot, "presentation/build.gradle.kts") @@ -2744,7 +3085,14 @@ dependencies { val enableDetekt = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose, enableKtlint, enableDetekt) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableHilt = true, + enableCompose = enableCompose, + enableKtlint = enableKtlint, + enableDetekt = enableDetekt + ) // Then val buildGradleFile = File(architectureRoot, "ui/build.gradle.kts") @@ -2816,7 +3164,14 @@ dependencies { val enableDetekt = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose, enableKtlint, enableDetekt) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableHilt = true, + enableCompose = enableCompose, + enableKtlint = enableKtlint, + enableDetekt = enableDetekt + ) // Then val buildGradleFile = File(architectureRoot, "presentation-test/build.gradle.kts") @@ -2862,7 +3217,14 @@ dependencies { val enableDetekt = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose, enableKtlint, enableDetekt) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableHilt = true, + enableCompose = enableCompose, + enableKtlint = enableKtlint, + enableDetekt = enableDetekt + ) // Then val buildGradleFile = File(architectureRoot, "instrumentation-test/build.gradle.kts") @@ -2951,7 +3313,14 @@ dependencies { val enableDetekt = false // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose, enableKtlint, enableDetekt) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableHilt = true, + enableCompose = enableCompose, + enableKtlint = enableKtlint, + enableDetekt = enableDetekt + ) // Then val buildGradleFile = File(architectureRoot, "domain/build.gradle.kts") @@ -2984,7 +3353,14 @@ dependencies { val enableDetekt = true // When - classUnderTest.generate(architectureRoot, architecturePackageName, enableCompose, enableKtlint, enableDetekt) + classUnderTest.generate( + architectureRoot = architectureRoot, + architecturePackageName = architecturePackageName, + enableHilt = true, + enableCompose = enableCompose, + enableKtlint = enableKtlint, + enableDetekt = enableDetekt + ) // Then val buildGradleFile = File(architectureRoot, "domain/build.gradle.kts") diff --git a/core/src/test/kotlin/com/mitteloupe/cag/core/generation/gradle/GradleFileCreatorTest.kt b/core/src/test/kotlin/com/mitteloupe/cag/core/generation/gradle/GradleFileCreatorTest.kt index fcf1f38..e0bd0f0 100644 --- a/core/src/test/kotlin/com/mitteloupe/cag/core/generation/gradle/GradleFileCreatorTest.kt +++ b/core/src/test/kotlin/com/mitteloupe/cag/core/generation/gradle/GradleFileCreatorTest.kt @@ -15,11 +15,12 @@ import org.junit.Test import java.io.File import kotlin.io.path.createTempDirectory +private const val ALIAS_HILT = "alias(libs.plugins.hilt)" private const val DEFAULT_PLUGINS = """alias(libs.plugins.android.application) apply false alias(libs.plugins.android.library) apply false alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.kotlin.jvm) apply false - alias(libs.plugins.hilt) apply false + $ALIAS_HILT apply false alias(libs.plugins.ksp) apply false""" class GradleFileCreatorTest { @@ -83,7 +84,7 @@ class GradleFileCreatorTest { } @Test - fun `Given no compose when writeAppGradleFile then generates app gradle file`() { + fun `Given no compose when writeAppGradleFile then generates app gradle file without compose`() { // Given val projectRoot = createTempDirectory(prefix = "featureRoot3").toFile() val packageName = "com.brand.app" @@ -99,7 +100,7 @@ class GradleFileCreatorTest { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) alias(libs.plugins.ksp) - alias(libs.plugins.hilt) + $ALIAS_HILT } kotlin { @@ -170,6 +171,103 @@ class GradleFileCreatorTest { classUnderTest.writeAppGradleFile( projectRoot = projectRoot, packageName = packageName, + enableHilt = true, + enableCompose = false, + catalog = catalog + ) + + // Then + assertEquals(expectedContent, targetFile.readText()) + } + + @Test + fun `Given no hilt when writeAppGradleFile then generates app gradle file without hilt`() { + // Given + val projectRoot = createTempDirectory(prefix = "featureRoot3").toFile() + val packageName = "com.brand.app" + val moduleDirectory = File(projectRoot, "app") + moduleDirectory.mkdirs() + val targetFile = File(moduleDirectory, "build.gradle.kts") + val catalog = VersionCatalogUpdater(fileCreator) + val expectedContent = + """ + import org.jetbrains.kotlin.gradle.dsl.JvmTarget + + plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.ksp) + } + + kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + } + } + + android { + namespace = "com.brand.app" + compileSdk = libs.versions.compileSdk.get().toInt() + + defaultConfig { + applicationId = "com.brand.app" + minSdk = libs.versions.minSdk.get().toInt() + targetSdk = libs.versions.targetSdk.get().toInt() + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + packaging { + resources.pickFirsts += "META-INF/versions/9/OSGI-INF/MANIFEST.MF" + } + } + + dependencies { + implementation(libs.material) + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.hilt.android) + ksp(libs.hilt.android.compiler) + implementation(libs.androidx.appcompat) + implementation(libs.androidx.constraintlayout) + implementation(libs.material) + + implementation(projects.architecture.ui) + implementation(projects.architecture.presentation) + implementation(projects.architecture.domain) + implementation(projects.features.samplefeature.ui) + implementation(projects.features.samplefeature.presentation) + implementation(projects.features.samplefeature.domain) + implementation(projects.features.samplefeature.data) + implementation(projects.datasource.source) + implementation(projects.datasource.implementation) + + testImplementation(libs.test.junit) + androidTestImplementation(libs.test.androidx.junit) + androidTestImplementation(libs.test.androidx.espresso.core) + } + """.trimIndent() + + // When + classUnderTest.writeAppGradleFile( + projectRoot = projectRoot, + packageName = packageName, + enableHilt = false, enableCompose = false, catalog = catalog ) @@ -195,7 +293,7 @@ class GradleFileCreatorTest { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) alias(libs.plugins.ksp) - alias(libs.plugins.hilt) + $ALIAS_HILT alias(libs.plugins.compose.compiler) } @@ -274,6 +372,7 @@ class GradleFileCreatorTest { classUnderTest.writeAppGradleFile( projectRoot = projectRoot, packageName = packageName, + enableHilt = true, enableCompose = true, catalog = catalog ) @@ -317,6 +416,56 @@ subprojects { // When classUnderTest.writeProjectGradleFile( projectRoot = projectRoot, + enableHilt = true, + enableKtlint = false, + enableDetekt = false, + catalog = catalog + ) + + // Then + assertEquals(expectedContent, targetFile.readText()) + } + + @Test + fun `Given no hilt when writeProjectGradleFile then generates app gradle file without hilt`() { + // Given + val projectRoot = createTempDirectory(prefix = "featureRoot").toFile() + val targetFile = File(projectRoot, "build.gradle.kts") + val catalog = VersionCatalogUpdater(fileCreator) + val expectedContent = + """// Top-level build file where you can add configuration options common to all sub-projects/modules. +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + alias(libs.plugins.android.application) apply false + alias(libs.plugins.android.library) apply false + alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.kotlin.jvm) apply false + alias(libs.plugins.ksp) apply false +} + +tasks { + withType { + sourceCompatibility = JavaVersion.VERSION_17.toString() + targetCompatibility = JavaVersion.VERSION_17.toString() + } +} + +subprojects { + tasks.withType { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + freeCompilerArgs.add("-Xskip-prerelease-check") + } + } +} +""" + + // When + classUnderTest.writeProjectGradleFile( + projectRoot = projectRoot, + enableHilt = false, enableKtlint = false, enableDetekt = false, catalog = catalog @@ -362,6 +511,7 @@ subprojects { // When classUnderTest.writeProjectGradleFile( projectRoot = projectRoot, + enableHilt = true, enableKtlint = true, enableDetekt = false, catalog = catalog @@ -407,6 +557,7 @@ subprojects { // When classUnderTest.writeProjectGradleFile( projectRoot = projectRoot, + enableHilt = true, enableKtlint = false, enableDetekt = true, catalog = catalog @@ -453,6 +604,7 @@ subprojects { // When classUnderTest.writeProjectGradleFile( projectRoot = projectRoot, + enableHilt = true, enableKtlint = true, enableDetekt = true, catalog = catalog diff --git a/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/CreateCleanArchitecturePackageAction.kt b/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/CreateCleanArchitecturePackageAction.kt index c87548a..2f41dd5 100644 --- a/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/CreateCleanArchitecturePackageAction.kt +++ b/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/CreateCleanArchitecturePackageAction.kt @@ -35,6 +35,7 @@ class CreateCleanArchitecturePackageAction : AnAction() { destinationRootDirectory = projectRootDir, architecturePackageName = architecturePackageName, enableCompose = dialog.isComposeEnabled(), + enableHilt = true, enableKtlint = dialog.isKtlintEnabled(), enableDetekt = dialog.isDetektEnabled() ) diff --git a/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/projectwizard/CleanArchitectureWizardTemplateProvider.kt b/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/projectwizard/CleanArchitectureWizardTemplateProvider.kt index 70be66e..ff312f2 100644 --- a/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/projectwizard/CleanArchitectureWizardTemplateProvider.kt +++ b/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/projectwizard/CleanArchitectureWizardTemplateProvider.kt @@ -164,6 +164,7 @@ class CleanArchitectureWizardTemplateProvider : WizardTemplateProvider() { packageName = data.packageName, overrideMinimumAndroidSdk = selectedMinSdk, overrideAndroidGradlePluginVersion = overrideAndroidGradlePluginVersion, + enableHilt = true, enableCompose = enableCompose.value, enableKtlint = enableKtlint.value, enableDetekt = enableDetekt.value,