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 af4045e..00da664 100644 --- a/cli/src/main/kotlin/com/mitteloupe/cag/cli/AppArgumentProcessor.kt +++ b/cli/src/main/kotlin/com/mitteloupe/cag/cli/AppArgumentProcessor.kt @@ -57,7 +57,9 @@ class AppArgumentProcessor(private val argumentParser: ArgumentParser = Argument ) { secondaries -> FeatureRequest( featureName = secondaries[SecondaryFlagConstants.NAME].orEmpty(), - packageName = secondaries[SecondaryFlagConstants.PACKAGE] + packageName = secondaries[SecondaryFlagConstants.PACKAGE], + 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 87e8087..db41352 100644 --- a/cli/src/main/kotlin/com/mitteloupe/cag/cli/Main.kt +++ b/cli/src/main/kotlin/com/mitteloupe/cag/cli/Main.kt @@ -37,7 +37,8 @@ import kotlin.system.exitProcess private const val USAGE_SYNTAX = "usage: cag [--new-project --name=ProjectName --package=PackageName [--no-compose] [--ktlint] [--detekt] [--ktor] [--retrofit]]... " + - "[--new-architecture [--no-compose] [--ktlint] [--detekt]]... [--new-feature --name=FeatureName [--package=PackageName]]... " + + "[--new-architecture [--no-compose] [--ktlint] [--detekt]]... " + + "[--new-feature --name=FeatureName [--package=PackageName] [--ktlint] [--detekt]]... " + "[--new-datasource --name=DataSourceName [--with=ktor|retrofit|ktor,retrofit]]... " + "[--new-use-case --name=UseCaseName [--path=TargetPath]]... [--new-view-model --name=ViewModelName [--path=TargetPath]]..." @@ -122,7 +123,7 @@ fun main(arguments: Array) { featureRequests.forEach { requestFeature -> val packageName = - requestFeature.packageName ?: basePackage?.let { "$it${requestFeature.featureName.lowercase()}" } + requestFeature.packageName ?: basePackage?.let { "${'$'}it${'$'}{requestFeature.featureName.lowercase()}" } val request = GenerateFeatureRequestBuilder( @@ -131,6 +132,8 @@ fun main(arguments: Array) { featureName = requestFeature.featureName ).featurePackageName(packageName) .enableCompose(true) + .enableKtlint(requestFeature.enableKtlint) + .enableDetekt(requestFeature.enableDetekt) .build() executeAndReport { generator.generateFeature(request) @@ -246,6 +249,10 @@ private fun printHelpMessage() { 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 diff --git a/cli/src/main/kotlin/com/mitteloupe/cag/cli/flag/PrimaryFlag.kt b/cli/src/main/kotlin/com/mitteloupe/cag/cli/flag/PrimaryFlag.kt index da1a48a..0393fdd 100644 --- a/cli/src/main/kotlin/com/mitteloupe/cag/cli/flag/PrimaryFlag.kt +++ b/cli/src/main/kotlin/com/mitteloupe/cag/cli/flag/PrimaryFlag.kt @@ -61,7 +61,9 @@ interface PrimaryFlag { isMandatory = true, missingErrorMessage = "Feature name is required. Use --name=FeatureName or -n=FeatureName" ), - SecondaryFlag(SecondaryFlagConstants.PACKAGE, "-p") + SecondaryFlag(SecondaryFlagConstants.PACKAGE, "-p"), + SecondaryFlag(SecondaryFlagConstants.KTLINT, "-kl", isBoolean = true), + SecondaryFlag(SecondaryFlagConstants.DETEKT, "-d", isBoolean = true) ) } diff --git a/cli/src/main/kotlin/com/mitteloupe/cag/cli/request/FeatureRequest.kt b/cli/src/main/kotlin/com/mitteloupe/cag/cli/request/FeatureRequest.kt index 3adfb35..15087ad 100644 --- a/cli/src/main/kotlin/com/mitteloupe/cag/cli/request/FeatureRequest.kt +++ b/cli/src/main/kotlin/com/mitteloupe/cag/cli/request/FeatureRequest.kt @@ -1,3 +1,8 @@ package com.mitteloupe.cag.cli.request -data class FeatureRequest(val featureName: String, val packageName: String?) +data class FeatureRequest( + val featureName: String, + val packageName: String?, + val enableKtlint: Boolean, + val enableDetekt: 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 0e01de2..207769c 100644 --- a/cli/src/test/kotlin/com/mitteloupe/cag/cli/AppArgumentProcessorTest.kt +++ b/cli/src/test/kotlin/com/mitteloupe/cag/cli/AppArgumentProcessorTest.kt @@ -56,6 +56,48 @@ class AppArgumentProcessorTest { // Then assertEquals(true, result) } + + @Test + fun `Given --new-feature with --ktlint when getNewFeatures then returns FeatureRequest with ktlint enabled`() { + // Given + val givenArguments = arrayOf("--new-feature", "--name=Quality", "--ktlint") + val expectedRequests = + listOf( + FeatureRequest( + featureName = "Quality", + packageName = null, + enableKtlint = true, + enableDetekt = false + ) + ) + + // When + val result = classUnderTest.getNewFeatures(givenArguments) + + // Then + assertEquals(expectedRequests, result) + } + + @Test + fun `Given short flags -nf -kl -d when getNewFeatures then returns FeatureRequest with both enabled`() { + // Given + val givenArguments = arrayOf("-nf", "-n=Quality", "-kl", "-d") + val expectedRequests = + listOf( + FeatureRequest( + featureName = "Quality", + packageName = null, + enableKtlint = true, + enableDetekt = true + ) + ) + + // When + val result = classUnderTest.getNewFeatures(givenArguments) + + // Then + assertEquals(expectedRequests, result) + } } class Features { @@ -71,24 +113,54 @@ class AppArgumentProcessorTest { // Given val givenArguments = arrayOf("--new-feature", "--name=First", "--package=com.first", "--new-feature", "--name=Second") + val expectedRequests = + listOf( + FeatureRequest( + featureName = "First", + packageName = "com.first", + enableKtlint = false, + enableDetekt = false + ), + FeatureRequest( + featureName = "Second", + packageName = null, + enableKtlint = false, + enableDetekt = false + ) + ) // When val result = classUnderTest.getNewFeatures(givenArguments) // Then - assertEquals(listOf(FeatureRequest("First", "com.first"), FeatureRequest("Second", null)), result) + assertEquals(expectedRequests, result) } @Test fun `Given short flags when getNewFeatures then parses correctly`() { // Given val givenArguments = arrayOf("-nf", "-nThird", "-p", "com.third", "-nf", "-n=Fourth", "-pcom.fourth") + val expectedRequests = + listOf( + FeatureRequest( + featureName = "Third", + packageName = "com.third", + enableKtlint = false, + enableDetekt = false + ), + FeatureRequest( + featureName = "Fourth", + packageName = "com.fourth", + enableKtlint = false, + enableDetekt = false + ) + ) // When val result = classUnderTest.getNewFeatures(givenArguments) // Then - assertEquals(listOf(FeatureRequest("Third", "com.third"), FeatureRequest("Fourth", "com.fourth")), result) + assertEquals(expectedRequests, result) } @Test diff --git a/cli/src/test/kotlin/com/mitteloupe/cag/cli/MainTest.kt b/cli/src/test/kotlin/com/mitteloupe/cag/cli/MainTest.kt index e01ca90..417f1e8 100644 --- a/cli/src/test/kotlin/com/mitteloupe/cag/cli/MainTest.kt +++ b/cli/src/test/kotlin/com/mitteloupe/cag/cli/MainTest.kt @@ -15,6 +15,14 @@ import java.io.OutputStream import java.io.PrintStream import java.nio.file.Files +private const val SHORT_USAGE = + "usage: cag [--new-project --name=ProjectName --package=PackageName [--no-compose] [--ktlint] [--detekt] [--ktor] [--retrofit]]... " + + "[--new-architecture [--no-compose] [--ktlint] [--detekt]]... " + + "[--new-feature --name=FeatureName [--package=PackageName] [--ktlint] [--detekt]]... " + + "[--new-datasource --name=DataSourceName [--with=ktor|retrofit|ktor,retrofit]]... " + + "[--new-use-case --name=UseCaseName [--path=TargetPath]]... " + + "[--new-view-model --name=ViewModelName [--path=TargetPath]]..." + @RunWith(Enclosed::class) @SuiteClasses( MainTest.NoArguments::class, @@ -60,22 +68,16 @@ class MainTest { class NoArguments : BaseMainTest() { @Test fun `Given no args when main then prints updated usage`() { + // Give + val expected = + "$SHORT_USAGE\n\n" + + "Run with --help or -h for more options.\n" + // When main(emptyArray()) // Then - assertEquals( - "usage: cag [--new-project --name=ProjectName --package=PackageName " + - "[--no-compose] [--ktlint] [--detekt] [--ktor] [--retrofit]]... " + - "[--new-architecture [--no-compose] [--ktlint] [--detekt]]... " + - "[--new-feature --name=FeatureName [--package=PackageName]]... " + - "[--new-datasource --name=DataSourceName [--with=ktor|retrofit|ktor,retrofit]]... " + - "[--new-use-case --name=UseCaseName [--path=TargetPath]]... " + - "[--new-view-model --name=ViewModelName [--path=TargetPath]]...\n" + - "\n" + - "Run with --help or -h for more options.\n", - output.toString() - ) + assertEquals(expected, output.toString()) } } @@ -100,7 +102,7 @@ class MainTest { companion object { private const val EXPECTED_HELP = - """usage: cag [--new-project --name=ProjectName --package=PackageName [--no-compose] [--ktlint] [--detekt] [--ktor] [--retrofit]]... [--new-architecture [--no-compose] [--ktlint] [--detekt]]... [--new-feature --name=FeatureName [--package=PackageName]]... [--new-datasource --name=DataSourceName [--with=ktor|retrofit|ktor,retrofit]]... [--new-use-case --name=UseCaseName [--path=TargetPath]]... [--new-view-model --name=ViewModelName [--path=TargetPath]]... + """$SHORT_USAGE Note: You must use either long form (--flag) or short form (-f) arguments consistently throughout your command. Mixing both forms is not allowed. @@ -135,6 +137,10 @@ Options: 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 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 419d91c..77696ab 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/Generator.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/Generator.kt @@ -78,6 +78,12 @@ class Generator( if (request.enableCompose) { addAll(VersionCatalogConstants.COMPOSE_VERSIONS) } + if (request.enableKtlint) { + addAll(VersionCatalogConstants.KTLINT_VERSIONS) + } + if (request.enableDetekt) { + addAll(VersionCatalogConstants.DETEKT_VERSIONS) + } }, libraries = if (request.enableCompose) LibraryConstants.COMPOSE_LIBRARIES else emptyList(), plugins = @@ -86,6 +92,12 @@ class Generator( if (request.enableCompose) { add(PluginConstants.COMPOSE_COMPILER) } + if (request.enableKtlint) { + add(PluginConstants.KTLINT) + } + if (request.enableDetekt) { + add(PluginConstants.DETEKT) + } } ) catalogUpdater.updateVersionCatalogIfPresent( @@ -170,6 +182,12 @@ class Generator( featurePackageName = featurePackageName, featureName = request.featureName ) + if (request.enableDetekt) { + configurationFileCreator.writeDetektConfigurationFile(request.destinationRootDirectory) + } + if (request.enableKtlint) { + configurationFileCreator.writeEditorConfigFile(request.destinationRootDirectory) + } settingsFileUpdater.updateProjectSettingsIfPresent( request.destinationRootDirectory, featureNameLowerCase @@ -518,6 +536,8 @@ class Generator( featurePackageName = "$packageName.${featureName.lowercase()}", projectNamespace = packageName, enableCompose = request.enableCompose, + enableKtlint = request.enableKtlint, + enableDetekt = request.enableDetekt, appModuleDirectory = null ) generateFeature(featureRequest) diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/content/DataGradleScriptBuilder.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/content/DataGradleScriptBuilder.kt index 606d47e..5a300f2 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/content/DataGradleScriptBuilder.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/content/DataGradleScriptBuilder.kt @@ -1,5 +1,6 @@ package com.mitteloupe.cag.core.content +import com.mitteloupe.cag.core.content.gradle.GradleFileExtender import com.mitteloupe.cag.core.generation.versioncatalog.PluginConstants import com.mitteloupe.cag.core.generation.versioncatalog.VersionCatalogReader import com.mitteloupe.cag.core.generation.versioncatalog.asAccessor @@ -10,11 +11,23 @@ fun buildDataGradleScript( ): String { val aliasKotlinJvm = catalog.getResolvedPluginAliasFor(PluginConstants.KOTLIN_JVM).asAccessor + val gradleFileExtender = GradleFileExtender() + val ktlintPluginLine = gradleFileExtender.buildKtlintPluginLine(catalog) + val detektPluginLine = gradleFileExtender.buildDetektPluginLine(catalog) + val ktlintConfiguration = gradleFileExtender.buildKtlintConfiguration(catalog) + val detektConfiguration = gradleFileExtender.buildDetektConfiguration(catalog, "../../../detekt.yml") + + val configurations = "$ktlintConfiguration$detektConfiguration".trimIndent() return """plugins { id("project-java-library") - alias(libs.plugins.$aliasKotlinJvm) + alias(libs.plugins.$aliasKotlinJvm)$ktlintPluginLine$detektPluginLine } - +${ if (configurations.isEmpty()) { + "" + } else { + "\n$configurations\n" + } + } dependencies { implementation(projects.features.$featureNameLowerCase.domain) implementation(projects.architecture.domain) diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/content/DomainGradleScriptBuilder.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/content/DomainGradleScriptBuilder.kt index 9ea57b8..4417dd3 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/content/DomainGradleScriptBuilder.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/content/DomainGradleScriptBuilder.kt @@ -1,5 +1,6 @@ package com.mitteloupe.cag.core.content +import com.mitteloupe.cag.core.content.gradle.GradleFileExtender import com.mitteloupe.cag.core.generation.versioncatalog.PluginConstants import com.mitteloupe.cag.core.generation.versioncatalog.VersionCatalogReader import com.mitteloupe.cag.core.generation.versioncatalog.asAccessor @@ -7,11 +8,23 @@ import com.mitteloupe.cag.core.generation.versioncatalog.asAccessor fun buildDomainGradleScript(catalog: VersionCatalogReader): String { val aliasKotlinJvm = catalog.getResolvedPluginAliasFor(PluginConstants.KOTLIN_JVM).asAccessor + val gradleFileExtender = GradleFileExtender() + val ktlintPluginLine = gradleFileExtender.buildKtlintPluginLine(catalog) + val detektPluginLine = gradleFileExtender.buildDetektPluginLine(catalog) + val ktlintConfiguration = gradleFileExtender.buildKtlintConfiguration(catalog) + val detektConfiguration = gradleFileExtender.buildDetektConfiguration(catalog, "../../../detekt.yml") + + val configurations = "$ktlintConfiguration$detektConfiguration".trimIndent() return """plugins { id("project-java-library") - alias(libs.plugins.$aliasKotlinJvm) + alias(libs.plugins.$aliasKotlinJvm)$ktlintPluginLine$detektPluginLine } - +${ if (configurations.isEmpty()) { + "" + } else { + "\n$configurations\n" + } + } dependencies { implementation(projects.architecture.domain) } diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/content/PresentationGradleScriptBuilder.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/content/PresentationGradleScriptBuilder.kt index 4a7d887..110c4d4 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/content/PresentationGradleScriptBuilder.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/content/PresentationGradleScriptBuilder.kt @@ -1,5 +1,6 @@ package com.mitteloupe.cag.core.content +import com.mitteloupe.cag.core.content.gradle.GradleFileExtender import com.mitteloupe.cag.core.generation.versioncatalog.PluginConstants import com.mitteloupe.cag.core.generation.versioncatalog.VersionCatalogReader import com.mitteloupe.cag.core.generation.versioncatalog.asAccessor @@ -10,11 +11,23 @@ fun buildPresentationGradleScript( ): String { val aliasKotlinJvm = catalog.getResolvedPluginAliasFor(PluginConstants.KOTLIN_JVM).asAccessor + val gradleFileExtender = GradleFileExtender() + val ktlintPluginLine = gradleFileExtender.buildKtlintPluginLine(catalog) + val detektPluginLine = gradleFileExtender.buildDetektPluginLine(catalog) + val ktlintConfiguration = gradleFileExtender.buildKtlintConfiguration(catalog) + val detektConfiguration = gradleFileExtender.buildDetektConfiguration(catalog, "../../../detekt.yml") + + val configurations = "$ktlintConfiguration$detektConfiguration".trimIndent() return """plugins { id("project-java-library") - alias(libs.plugins.$aliasKotlinJvm) + alias(libs.plugins.$aliasKotlinJvm)$ktlintPluginLine$detektPluginLine } - +${ if (configurations.isEmpty()) { + "" + } else { + "\n$configurations\n" + } + } dependencies { implementation(projects.features.$featureNameLowerCase.domain) implementation(projects.architecture.presentation) diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/content/UiGradleScriptBuilder.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/content/UiGradleScriptBuilder.kt index dc6a53d..be2a150 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/content/UiGradleScriptBuilder.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/content/UiGradleScriptBuilder.kt @@ -1,5 +1,6 @@ package com.mitteloupe.cag.core.content +import com.mitteloupe.cag.core.content.gradle.GradleFileExtender import com.mitteloupe.cag.core.generation.versioncatalog.LibraryConstants import com.mitteloupe.cag.core.generation.versioncatalog.PluginConstants import com.mitteloupe.cag.core.generation.versioncatalog.VersionCatalogReader @@ -29,6 +30,11 @@ fun buildUiGradleScript( } else { "" } + val gradleFileExtender = GradleFileExtender() + val ktlintPluginLine = gradleFileExtender.buildKtlintPluginLine(catalog) + val detektPluginLine = gradleFileExtender.buildDetektPluginLine(catalog) + val ktlintConfiguration = gradleFileExtender.buildKtlintConfiguration(catalog) + val detektConfiguration = gradleFileExtender.buildDetektConfiguration(catalog, "../../../detekt.yml") val composeBuildFeaturesSection = if (enableCompose) { """ @@ -55,9 +61,10 @@ fun buildUiGradleScript( "" } + val configurations = "$ktlintConfiguration$detektConfiguration".trimIndent() return """plugins { alias(libs.plugins.$pluginAliasAndroidLibrary) - alias(libs.plugins.$pluginAliasKotlinAndroid)$composePluginLine + alias(libs.plugins.$pluginAliasKotlinAndroid)$composePluginLine$ktlintPluginLine$detektPluginLine } android { @@ -82,12 +89,18 @@ android { ) } } + compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } $composeBuildFeaturesSection} - +${ if (configurations.isEmpty()) { + "" + } else { + "\n$configurations\n" + } + } dependencies { implementation(projects.features.$featureNameLowerCase.presentation) implementation(projects.architecture.ui) diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/content/gradle/GradleFileExtender.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/content/gradle/GradleFileExtender.kt index 27b11c4..76cdb10 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/content/gradle/GradleFileExtender.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/content/gradle/GradleFileExtender.kt @@ -47,11 +47,14 @@ class GradleFileExtender internal constructor() { "" } - fun buildDetektConfiguration(catalog: VersionCatalogReader): String = + fun buildDetektConfiguration( + catalog: VersionCatalogReader, + configRelativePathFromModule: String = "../../detekt.yml" + ): String = if (catalog.isPluginAvailable(PluginConstants.DETEKT)) { """ detekt { - config.setFrom("${'$'}projectDir/../../detekt.yml") + config.setFrom("${'$'}projectDir/$configRelativePathFromModule") } """ } else { diff --git a/core/src/main/kotlin/com/mitteloupe/cag/core/request/GenerateFeatureRequest.kt b/core/src/main/kotlin/com/mitteloupe/cag/core/request/GenerateFeatureRequest.kt index 749c3e1..bf1b998 100644 --- a/core/src/main/kotlin/com/mitteloupe/cag/core/request/GenerateFeatureRequest.kt +++ b/core/src/main/kotlin/com/mitteloupe/cag/core/request/GenerateFeatureRequest.kt @@ -8,6 +8,8 @@ data class GenerateFeatureRequest( val projectNamespace: String, val destinationRootDirectory: File, val enableCompose: Boolean, + val enableKtlint: Boolean, + val enableDetekt: Boolean, val appModuleDirectory: File? ) @@ -19,6 +21,8 @@ class GenerateFeatureRequestBuilder( private var featurePackageName: String? = null private var enableCompose: Boolean = false private var appModuleDirectory: File? = null + private var enableKtlint: Boolean = false + private var enableDetekt: Boolean = false fun featurePackageName(featurePackageName: String?) = apply { @@ -35,6 +39,16 @@ class GenerateFeatureRequestBuilder( this.appModuleDirectory = appModuleDirectory } + fun enableKtlint(enable: Boolean) = + apply { + this.enableKtlint = enable + } + + fun enableDetekt(enable: Boolean) = + apply { + this.enableDetekt = enable + } + fun build(): GenerateFeatureRequest = GenerateFeatureRequest( featureName = featureName, @@ -42,6 +56,8 @@ class GenerateFeatureRequestBuilder( projectNamespace = projectNamespace, destinationRootDirectory = destinationRootDir, enableCompose = enableCompose, + enableKtlint = enableKtlint, + enableDetekt = enableDetekt, appModuleDirectory = appModuleDirectory ) } 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 31c8ed9..c87c39c 100644 --- a/core/src/test/kotlin/com/mitteloupe/cag/core/GeneratorTest.kt +++ b/core/src/test/kotlin/com/mitteloupe/cag/core/GeneratorTest.kt @@ -34,11 +34,12 @@ import kotlin.io.path.createTempDirectory class GeneratorTest { private lateinit var classUnderTest: Generator - private lateinit var tempDirectory: File + + private lateinit var temporaryDirectory: File @Before fun setUp() { - tempDirectory = createTempDirectory(prefix = "test").toFile() + temporaryDirectory = createTempDirectory(prefix = "test").toFile() classUnderTest = produceGenerator() } @@ -49,9 +50,11 @@ class GeneratorTest { GenerateFeatureRequest( featureName = "TestFeature", featurePackageName = "", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, projectNamespace = "com.example", enableCompose = true, + enableKtlint = false, + enableDetekt = false, appModuleDirectory = null ) @@ -68,9 +71,11 @@ class GeneratorTest { GenerateFeatureRequest( featureName = "TestFeature", featurePackageName = null, - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, projectNamespace = "com.example", enableCompose = true, + enableKtlint = false, + enableDetekt = false, appModuleDirectory = null ) @@ -87,9 +92,11 @@ class GeneratorTest { GenerateFeatureRequest( featureName = "TestFeature", featurePackageName = "...", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, projectNamespace = "com.example", enableCompose = true, + enableKtlint = false, + enableDetekt = false, appModuleDirectory = null ) @@ -102,15 +109,17 @@ class GeneratorTest { @Test(expected = GenerationException::class) fun `Given existing feature directory when generateFeature then throws exception`() { // Given - val existingFeatureDir = File(tempDirectory, "features/testfeature") + val existingFeatureDir = File(temporaryDirectory, "features/testfeature") existingFeatureDir.mkdirs() val request = GenerateFeatureRequest( featureName = "TestFeature", featurePackageName = "com.example.feature", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, projectNamespace = "com.example", enableCompose = true, + enableKtlint = false, + enableDetekt = false, appModuleDirectory = null ) @@ -123,7 +132,7 @@ class GeneratorTest { @Test(expected = GenerationException::class) fun `Given existing file with feature name when generateFeature then throws exception`() { // Given - val featuresDirectory = File(tempDirectory, "features") + val featuresDirectory = File(temporaryDirectory, "features") featuresDirectory.mkdirs() val existingFeatureFile = File(featuresDirectory, "testfeature") existingFeatureFile.createNewFile() @@ -131,9 +140,11 @@ class GeneratorTest { GenerateFeatureRequest( featureName = "TestFeature", featurePackageName = "com.example.feature", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, projectNamespace = "com.example", enableCompose = true, + enableKtlint = false, + enableDetekt = false, appModuleDirectory = null ) @@ -150,9 +161,11 @@ class GeneratorTest { GenerateFeatureRequest( featureName = "TestFeature", featurePackageName = "com.example.feature", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, projectNamespace = "com.example", enableCompose = true, + enableKtlint = false, + enableDetekt = false, appModuleDirectory = null ) @@ -160,7 +173,7 @@ class GeneratorTest { classUnderTest.generateFeature(request) // Then - val featureRoot = File(tempDirectory, "features/testfeature") + val featureRoot = File(temporaryDirectory, "features/testfeature") assertTrue(featureRoot.exists()) assertTrue(featureRoot.isDirectory) @@ -174,7 +187,7 @@ class GeneratorTest { @Test fun `Given valid use case request when generateUseCase then returns success`() { // Given - val useCaseDir = File(tempDirectory, "src/main/java/com/example/feature/domain/usecase") + val useCaseDir = File(temporaryDirectory, "src/main/java/com/example/feature/domain/usecase") useCaseDir.mkdirs() val request = GenerateUseCaseRequest( @@ -193,7 +206,7 @@ class GeneratorTest { @Test fun `Given existing directory when generateViewModel then returns success`() { // Given - val viewModelDirectory = File(tempDirectory, "src/main/java/com/example/featurepresentation/viewmodel") + val viewModelDirectory = File(temporaryDirectory, "src/main/java/com/example/featurepresentation/viewmodel") viewModelDirectory.mkdirs() val request = GenerateViewModelRequest( @@ -216,7 +229,7 @@ class GeneratorTest { @Test fun `Given new directory when generateViewModel then creates ViewModel in correct presentation layer structure`() { // Given - val targetDirectory = File(tempDirectory, "features/samplefeature") + val targetDirectory = File(temporaryDirectory, "features/samplefeature") val request = GenerateViewModelRequest( viewModelName = "SampleViewModel", @@ -241,12 +254,14 @@ class GeneratorTest { GenerateFeatureRequest( featureName = "TestFeature", featurePackageName = "com.example.app.testfeature", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, projectNamespace = "com.example.app", enableCompose = true, + enableKtlint = false, + enableDetekt = false, appModuleDirectory = null ) - val featureRoot = File(tempDirectory, "features/testfeature") + val featureRoot = File(temporaryDirectory, "features/testfeature") val expectedPresentationModelFile = File( featureRoot, @@ -267,12 +282,14 @@ class GeneratorTest { GenerateFeatureRequest( featureName = "TestFeature", featurePackageName = "com.example.app.testfeature", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, projectNamespace = "com.example.app", enableCompose = true, + enableKtlint = false, + enableDetekt = false, appModuleDirectory = null ) - val featureRoot = File(tempDirectory, "features/testfeature") + val featureRoot = File(temporaryDirectory, "features/testfeature") val expectedPresentationMapperFile = File( featureRoot, @@ -292,7 +309,7 @@ class GeneratorTest { val request = GenerateArchitectureRequest( architecturePackageName = "", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, enableCompose = true ) @@ -308,7 +325,7 @@ class GeneratorTest { val request = GenerateArchitectureRequest( architecturePackageName = "...", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, enableCompose = true ) @@ -321,12 +338,12 @@ class GeneratorTest { @Test(expected = GenerationException::class) fun `Given existing architecture directory when generateArchitecture then throws exception`() { // Given - val existingArchitectureDir = File(tempDirectory, "architecture") + val existingArchitectureDir = File(temporaryDirectory, "architecture") existingArchitectureDir.mkdirs() val request = GenerateArchitectureRequest( architecturePackageName = "com.example.architecture", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, enableCompose = true ) @@ -342,7 +359,7 @@ class GeneratorTest { val request = GenerateArchitectureRequest( architecturePackageName = "com.example.architecture", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, enableCompose = true ) @@ -350,7 +367,7 @@ class GeneratorTest { classUnderTest.generateArchitecture(request) // Then - val architectureRoot = File(tempDirectory, "architecture") + val architectureRoot = File(temporaryDirectory, "architecture") assertTrue(architectureRoot.isDirectory) val layers = listOf("domain", "presentation", "ui") @@ -366,12 +383,12 @@ class GeneratorTest { val request = GenerateArchitectureRequest( architecturePackageName = "com.example.architecture", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, enableCompose = true, enableKtlint = true, enableDetekt = true ) - val architectureRoot = File(tempDirectory, "architecture") + val architectureRoot = File(temporaryDirectory, "architecture") // When classUnderTest.generateArchitecture(request) @@ -396,7 +413,7 @@ class GeneratorTest { // When classUnderTest.generateDataSource( - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, dataSourceName = dataSourceName, projectNamespace = projectNamespace, useKtor = useKtor, @@ -405,7 +422,7 @@ class GeneratorTest { // Then - val datasourceRoot = File(tempDirectory, "datasource") + val datasourceRoot = File(temporaryDirectory, "datasource") assertTrue(datasourceRoot.exists()) val sourceModule = File(datasourceRoot, "source") @@ -416,7 +433,7 @@ class GeneratorTest { @Test fun `Given existing version catalog without compose versions when generateFeature with compose enabled then adds compose versions`() { - val gradleDirectory = File(tempDirectory, "gradle") + val gradleDirectory = File(temporaryDirectory, "gradle") gradleDirectory.mkdirs() val catalogFile = File(gradleDirectory, "libs.versions.toml") val existingVersions = """kotlin = "2.2.10" @@ -439,9 +456,11 @@ class GeneratorTest { GenerateFeatureRequest( featureName = "TestFeature", featurePackageName = "com.example.feature", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, projectNamespace = "com.example", enableCompose = true, + enableKtlint = false, + enableDetekt = false, appModuleDirectory = null ) val expectedContent = @@ -491,12 +510,14 @@ class GeneratorTest { GenerateFeatureRequest( featureName = "TestFeature", featurePackageName = "com.example.feature", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, projectNamespace = "com.example", enableCompose = false, + enableKtlint = false, + enableDetekt = false, appModuleDirectory = null ) - val catalogFile = File(tempDirectory, "gradle/libs.versions.toml") + val catalogFile = File(temporaryDirectory, "gradle/libs.versions.toml") // When classUnderTest.generateFeature(request) @@ -538,7 +559,7 @@ class GeneratorTest { @Suppress("MaxLineLength", "ktlint:standard:max-line-length") fun `Given existing version catalog, no compose versions, compose disabled when generateFeature then does not add compose versions`() { // Given - val gradleDirectory = File(tempDirectory, "gradle") + val gradleDirectory = File(temporaryDirectory, "gradle") gradleDirectory.mkdirs() val catalogFile = File(gradleDirectory, "libs.versions.toml") val existingVersions = """kotlin = "2.2.10" @@ -561,9 +582,11 @@ class GeneratorTest { GenerateFeatureRequest( featureName = "TestFeature", featurePackageName = "com.example.feature", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, projectNamespace = "com.example", enableCompose = false, + enableKtlint = false, + enableDetekt = false, appModuleDirectory = null ) val expectedContent = @@ -596,18 +619,20 @@ class GeneratorTest { @Test fun `Given explicit app module directory when generateFeature then updates only specified module`() { // Given - val appModuleA = File(tempDirectory, "appA").apply { mkdirs() } + val appModuleA = File(temporaryDirectory, "appA").apply { mkdirs() } File(appModuleA, "build.gradle.kts").writeText("") - val appModuleB = File(tempDirectory, "appB").apply { mkdirs() } + val appModuleB = File(temporaryDirectory, "appB").apply { mkdirs() } File(appModuleB, "build.gradle.kts").writeText("") val request = GenerateFeatureRequest( featureName = "TestFeature", featurePackageName = "com.example.app.testfeature", - destinationRootDirectory = tempDirectory, + destinationRootDirectory = temporaryDirectory, projectNamespace = "com.example.app", enableCompose = true, + enableKtlint = false, + enableDetekt = false, appModuleDirectory = appModuleB ) @@ -624,6 +649,232 @@ class GeneratorTest { assertFalse("DI module should not be created in non-selected module", unexpectedDiFileInModuleA.exists()) } + @Test + fun `Given ktlint, detekt enabled when generateFeature then generates domain Gradle file`() { + // Given + val request = + GenerateFeatureRequest( + featureName = "Sample", + featurePackageName = "com.example.sample", + projectNamespace = "com.example", + destinationRootDirectory = temporaryDirectory, + enableCompose = true, + enableKtlint = true, + enableDetekt = true, + appModuleDirectory = null + ) + val featureRoot = File(temporaryDirectory, "features/sample") + val expectedContent = """plugins { + id("project-java-library") + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.ktlint) + alias(libs.plugins.detekt) +} + +ktlint { + version.set("1.7.1") + android.set(true) +} + +detekt { + config.setFrom("${'$'}projectDir/../../../detekt.yml") +} + +dependencies { + implementation(projects.architecture.domain) +} +""" + + // When + classUnderTest.generateFeature(request) + val domainGradle = File(featureRoot, "domain/build.gradle.kts").readText() + + // Then + assertEquals(expectedContent, domainGradle) + } + + @Test + fun `Given ktlint, detekt enabled when generateFeature then generates presentation Gradle file`() { + // Given + val request = + GenerateFeatureRequest( + featureName = "Sample", + featurePackageName = "com.example.sample", + projectNamespace = "com.example", + destinationRootDirectory = temporaryDirectory, + enableCompose = true, + enableKtlint = true, + enableDetekt = true, + appModuleDirectory = null + ) + val featureRoot = File(temporaryDirectory, "features/sample") + val expectedContent = """plugins { + id("project-java-library") + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.ktlint) + alias(libs.plugins.detekt) +} + +ktlint { + version.set("1.7.1") + android.set(true) +} + +detekt { + config.setFrom("${'$'}projectDir/../../../detekt.yml") +} + +dependencies { + implementation(projects.features.sample.domain) + implementation(projects.architecture.presentation) + implementation(projects.architecture.domain) +} +""" + + // When + classUnderTest.generateFeature(request) + val presentationGradle = File(featureRoot, "presentation/build.gradle.kts").readText() + + // Then + assertEquals(expectedContent, presentationGradle) + } + + @Test + fun `Given ktlint, detekt enabled when generateFeature then generates data Gradle file`() { + // Given + val request = + GenerateFeatureRequest( + featureName = "Sample", + featurePackageName = "com.example.sample", + projectNamespace = "com.example", + destinationRootDirectory = temporaryDirectory, + enableCompose = true, + enableKtlint = true, + enableDetekt = true, + appModuleDirectory = null + ) + val featureRoot = File(temporaryDirectory, "features/sample") + val expectedContent = """plugins { + id("project-java-library") + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.ktlint) + alias(libs.plugins.detekt) +} + +ktlint { + version.set("1.7.1") + android.set(true) +} + +detekt { + config.setFrom("${'$'}projectDir/../../../detekt.yml") +} + +dependencies { + implementation(projects.features.sample.domain) + implementation(projects.architecture.domain) + + implementation(projects.datasource.source) +} +""" + + // When + classUnderTest.generateFeature(request) + val dataGradle = File(featureRoot, "data/build.gradle.kts").readText() + + // Then + assertEquals(expectedContent, dataGradle) + } + + @Test + fun `Given ktlint, detekt enabled when generateFeature then generates UI Gradle file`() { + // Given + val request = + GenerateFeatureRequest( + featureName = "Sample", + featurePackageName = "com.example.sample", + projectNamespace = "com.example", + destinationRootDirectory = temporaryDirectory, + enableCompose = true, + enableKtlint = true, + enableDetekt = true, + appModuleDirectory = null + ) + val featureRoot = File(temporaryDirectory, "features/sample") + val expectedContent = """plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.compose.compiler) + + alias(libs.plugins.ktlint) + alias(libs.plugins.detekt) +} + +android { + namespace = "com.example.sample.ui" + compileSdk = libs.versions.compileSdk.get().toInt() + + defaultConfig { + minSdk = libs.versions.minSdk.get().toInt() + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + } + + 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 + } +} + +ktlint { + version.set("1.7.1") + android.set(true) +} + +detekt { + config.setFrom("${'$'}projectDir/../../../detekt.yml") +} + +dependencies { + implementation(projects.features.sample.presentation) + implementation(projects.architecture.ui) + implementation(projects.architecture.presentation) + + implementation(platform(libs.compose.bom)) + implementation(libs.compose.ui) + implementation(libs.compose.material3) + implementation(libs.compose.ui.graphics) + implementation(libs.compose.ui.tooling) + implementation(libs.compose.navigation) + implementation(libs.compose.ui.tooling.preview) +} +""" + + // When + classUnderTest.generateFeature(request) + val uiGradle = File(featureRoot, "ui/build.gradle.kts").readText() + + // Then + assertEquals(expectedContent, uiGradle) + } + private fun produceGenerator(): Generator { val fileCreator = FileCreator(FakeFileSystemBridge()) val directoryFinder = DirectoryFinder() diff --git a/core/src/test/kotlin/com/mitteloupe/cag/core/content/FeatureGradleScriptBuildersTest.kt b/core/src/test/kotlin/com/mitteloupe/cag/core/content/FeatureGradleScriptBuildersTest.kt new file mode 100644 index 0000000..4cbff2b --- /dev/null +++ b/core/src/test/kotlin/com/mitteloupe/cag/core/content/FeatureGradleScriptBuildersTest.kt @@ -0,0 +1,204 @@ +package com.mitteloupe.cag.core.content + +import com.mitteloupe.cag.core.generation.versioncatalog.SectionEntryRequirement.LibraryRequirement +import com.mitteloupe.cag.core.generation.versioncatalog.SectionEntryRequirement.PluginRequirement +import com.mitteloupe.cag.core.generation.versioncatalog.VersionCatalogReader +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test + +class FeatureGradleScriptBuildersTest { + private lateinit var catalog: VersionCatalogReader + + @Before + fun setUp() { + catalog = FakeVersionCatalogReader() + } + + @Test + fun `Given catalog with ktlint, detekt when buildDomainGradleScript then generates domain Gradle script`() { + // Given + val expected = """plugins { + id("project-java-library") + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.ktlint) + alias(libs.plugins.detekt) +} + +ktlint { + version.set("1.7.1") + android.set(true) +} + +detekt { + config.setFrom("${'$'}projectDir/../../../detekt.yml") +} + +dependencies { + implementation(projects.architecture.domain) +} +""" + + // When + val actualContent = buildDomainGradleScript(catalog) + + // Then + assertEquals(expected, actualContent) + } + + @Test + fun `Given catalog with ktlint, detekt when buildPresentationGradleScript then generates presentation Gradle script`() { + val expected = """plugins { + id("project-java-library") + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.ktlint) + alias(libs.plugins.detekt) +} + +ktlint { + version.set("1.7.1") + android.set(true) +} + +detekt { + config.setFrom("${'$'}projectDir/../../../detekt.yml") +} + +dependencies { + implementation(projects.features.samplefeature.domain) + implementation(projects.architecture.presentation) + implementation(projects.architecture.domain) +} +""" + + // When + val actualContent = buildPresentationGradleScript(featureNameLowerCase = "samplefeature", catalog = catalog) + + // Then + assertEquals(expected, actualContent) + } + + @Test + fun `Given catalog with ktlint, detekt when buildDataGradleScript then generates data Gradle script`() { + // Given + val expected = """plugins { + id("project-java-library") + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.ktlint) + alias(libs.plugins.detekt) +} + +ktlint { + version.set("1.7.1") + android.set(true) +} + +detekt { + config.setFrom("${'$'}projectDir/../../../detekt.yml") +} + +dependencies { + implementation(projects.features.samplefeature.domain) + implementation(projects.architecture.domain) + + implementation(projects.datasource.source) +} +""" + + // When + val actualContent = buildDataGradleScript(featureNameLowerCase = "samplefeature", catalog = catalog) + + // Then + assertEquals(expected, actualContent) + } + + @Test + fun `Given catalog with ktlint, detekt when buildUiGradleScript then generates UI Gradle script`() { + // Given + val expected = """plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.compose.compiler) + + alias(libs.plugins.ktlint) + alias(libs.plugins.detekt) +} + +android { + namespace = "com.example.samplefeature.ui" + compileSdk = libs.versions.compileSdk.get().toInt() + + defaultConfig { + minSdk = libs.versions.minSdk.get().toInt() + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + } + + 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 + } +} + +ktlint { + version.set("1.7.1") + android.set(true) +} + +detekt { + config.setFrom("${'$'}projectDir/../../../detekt.yml") +} + +dependencies { + implementation(projects.features.samplefeature.presentation) + implementation(projects.architecture.ui) + implementation(projects.architecture.presentation) + + implementation(platform(libs.compose.bom)) + implementation(libs.compose.ui) + implementation(libs.compose.material3) + implementation(libs.compose.ui.graphics) + implementation(libs.compose.ui.tooling) + implementation(libs.compose.navigation) + implementation(libs.compose.ui.tooling.preview) +} +""" + + // When + val actualContent = + buildUiGradleScript( + featurePackageName = "com.example.samplefeature", + featureNameLowerCase = "samplefeature", + enableCompose = true, + catalog = catalog + ) + + // Then + assertEquals(expected, actualContent) + } + + private class FakeVersionCatalogReader : VersionCatalogReader { + override fun getResolvedPluginAliasFor(requirement: PluginRequirement): String = requirement.key + + override fun isPluginAvailable(requirement: PluginRequirement): Boolean = true + + override fun getResolvedLibraryAliasForModule(requirement: LibraryRequirement): String = requirement.key + } +} diff --git a/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/CreateCleanArchitectureFeatureAction.kt b/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/CreateCleanArchitectureFeatureAction.kt index 2d76ecf..080065b 100644 --- a/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/CreateCleanArchitectureFeatureAction.kt +++ b/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/CreateCleanArchitectureFeatureAction.kt @@ -26,6 +26,8 @@ class CreateCleanArchitectureFeatureAction : AnAction() { val featurePackageName = dialog.featurePackageName val generator = GeneratorProvider().generator(project) val selectedAppModule = dialog.selectedAppModuleDirectory + val enableKtlint = dialog.enableKtlint + val enableDetekt = dialog.enableDetekt val request = GenerateFeatureRequestBuilder( destinationRootDir = projectRootDirectory, @@ -34,6 +36,8 @@ class CreateCleanArchitectureFeatureAction : AnAction() { ).featurePackageName(featurePackageName) .enableCompose(true) .appModuleDirectory(selectedAppModule) + .enableKtlint(enableKtlint) + .enableDetekt(enableDetekt) .build() try { generator.generateFeature(request) diff --git a/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/CreateCleanArchitectureFeatureDialog.kt b/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/CreateCleanArchitectureFeatureDialog.kt index 57068be..7530724 100644 --- a/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/CreateCleanArchitectureFeatureDialog.kt +++ b/plugin/src/main/kotlin/com/mitteloupe/cag/cleanarchitecturegenerator/CreateCleanArchitectureFeatureDialog.kt @@ -9,6 +9,7 @@ import com.intellij.ui.dsl.builder.panel import com.mitteloupe.cag.cleanarchitecturegenerator.form.OnChangeDocumentListener import com.mitteloupe.cag.cleanarchitecturegenerator.form.PredicateDocumentFilter import java.io.File +import javax.swing.JCheckBox import javax.swing.JComponent import javax.swing.text.AbstractDocument @@ -23,6 +24,8 @@ class CreateCleanArchitectureFeatureDialog( private val featurePackageTextField = JBTextField() private var lastFeatureName: String = PLACEHOLDER private val appModuleComboBox = ComboBox(appModuleDirectories.map { it.name }.toTypedArray()) + private val ktlintCheckBox = JCheckBox("ktlint") + private val detektCheckBox = JCheckBox("detekt") val featureName: String get() = featureNameTextField.text @@ -43,6 +46,12 @@ class CreateCleanArchitectureFeatureDialog( } } + val enableKtlint: Boolean + get() = ktlintCheckBox.isSelected + + val enableDetekt: Boolean + get() = detektCheckBox.isSelected + init { title = CleanArchitectureGeneratorBundle.message("info.feature.generator.title") init() @@ -101,6 +110,10 @@ class CreateCleanArchitectureFeatureDialog( row(CleanArchitectureGeneratorBundle.message("dialog.feature.package.label")) { cell(featurePackageTextField) } + row(CleanArchitectureGeneratorBundle.message("dialog.feature.code.quality.label")) { + cell(ktlintCheckBox) + cell(detektCheckBox) + } } override fun doValidate(): ValidationInfo? = diff --git a/plugin/src/main/resources/messages/CleanArchitectureGeneratorBundle.properties b/plugin/src/main/resources/messages/CleanArchitectureGeneratorBundle.properties index 9e5410b..24c40c3 100644 --- a/plugin/src/main/resources/messages/CleanArchitectureGeneratorBundle.properties +++ b/plugin/src/main/resources/messages/CleanArchitectureGeneratorBundle.properties @@ -3,6 +3,7 @@ action.com.mitteloupe.cag.cleanarchitecturegenerator.CreateCleanArchitectureFeat info.feature.generator.title=New Clean Architecture Feature dialog.feature.name.label=Feature name: dialog.feature.package.label=Feature package: +dialog.feature.code.quality.label=Code quality dialog.feature.app.module.label=App module: validation.feature.name.required=Please enter a feature name. info.feature.generator.confirmation=Generated feature: {0}\n{1}