Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class AppArgumentProcessor(
.parsePrimaryWithSecondaries(arguments = arguments, primaryFlag = NewArchitecturePrimary)
.map { secondaries ->
ArchitectureRequest(
appModuleDirectory = null,
dependencyInjection = DependencyInjection.Hilt,
enableCompose = !secondaries.containsKey(SecondaryFlagConstants.NO_COMPOSE),
enableKtlint = secondaries.containsKey(SecondaryFlagConstants.KTLINT),
Expand Down
2 changes: 2 additions & 0 deletions cli/src/main/kotlin/com/mitteloupe/cag/cli/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ fun main(arguments: Array<String>) {
val architecturePackageName = basePackage?.let { "$it.architecture" } ?: "com.unknown.app.architecture"
val architectureRequest =
GenerateArchitectureRequest(
projectNamespace = projectNamespace,
destinationRootDirectory = destinationRootDirectory,
appModuleDirectory = request.appModuleDirectory,
architecturePackageName = architecturePackageName,
dependencyInjection = request.dependencyInjection,
enableCompose = request.enableCompose,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.mitteloupe.cag.cli.request

import com.mitteloupe.cag.core.option.DependencyInjection
import java.io.File

data class ArchitectureRequest(
val appModuleDirectory: File?,
val dependencyInjection: DependencyInjection,
val enableCompose: Boolean,
val enableKtlint: Boolean,
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/kotlin/com/mitteloupe/cag/core/Generator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class Generator(
projectNamespace = request.projectNamespace,
destinationRootDirectory = request.destinationRootDirectory,
appModuleDirectory = request.appModuleDirectory,
dependencyInjection = request.dependencyInjection,
enableCompose = request.enableCompose,
enableKtlint = request.enableKtlint,
enableDetekt = request.enableDetekt
Expand Down Expand Up @@ -81,7 +82,9 @@ class Generator(

fun generateArchitecture(request: GenerateArchitectureRequest) {
architectureFilesGenerator.generateArchitecture(
projectNamespace = request.projectNamespace,
destinationRootDirectory = request.destinationRootDirectory,
appModuleDirectory = request.appModuleDirectory,
architecturePackageName = request.architecturePackageName,
dependencyInjection = request.dependencyInjection,
enableCompose = request.enableCompose,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ class GeneratorFactory(
architectureModulesContentGenerator,
settingsFileUpdater,
buildSrcContentCreator,
configurationFileCreator
configurationFileCreator,
appModuleContentGenerator
)
val featureFilesGenerator =
FeatureFilesGenerator(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
package com.mitteloupe.cag.core.content

import com.mitteloupe.cag.core.generation.format.optimizeImports
import com.mitteloupe.cag.core.option.DependencyInjection

fun buildAppFeatureModuleKotlinFile(
fun buildAppFeatureDependencyInjectionModuleKotlinFile(
projectNamespace: String,
featurePackageName: String,
featureName: String
featureName: String,
dependencyInjection: DependencyInjection
): String {
val className = featureName.capitalized
val variableName = className.replaceFirstChar { it.lowercase() }
return """package $projectNamespace.di

${
"""
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import $featurePackageName.data.repository.${className}Repository
val providedImports = """import $featurePackageName.data.repository.${className}Repository
import $featurePackageName.domain.repository.PerformActionRepository
import $featurePackageName.domain.usecase.PerformActionUseCase
import $featurePackageName.presentation.mapper.StubDomainMapper
import $featurePackageName.presentation.mapper.StubPresentationMapper
import $featurePackageName.presentation.viewmodel.${className}ViewModel
import $featurePackageName.presentation.navigation.${className}PresentationNavigationEvent
import $featurePackageName.ui.di.${className}Dependencies
import $featurePackageName.ui.mapper.StubUiMapper
"""
return when (dependencyInjection) {
DependencyInjection.Hilt -> {
"""package $projectNamespace.di

${
"""import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import $projectNamespace.architecture.domain.UseCaseExecutor
import $projectNamespace.architecture.presentation.notification.PresentationNotification
import $projectNamespace.architecture.ui.navigation.mapper.NavigationEventDestinationMapper
import $projectNamespace.architecture.ui.notification.mapper.NotificationUiMapper
""".optimizeImports()
}
import $featurePackageName.presentation.navigation.${className}PresentationNavigationEvent
$providedImports""".optimizeImports()
}
@Module
@InstallIn(SingletonComponent::class)
object ${className}Module {
Expand Down Expand Up @@ -75,4 +79,26 @@ object ${className}Module {
)
}
"""
}
DependencyInjection.Koin -> {
"""package $projectNamespace.di

${
"""import org.koin.core.module.dsl.factoryOf
import org.koin.dsl.module
$providedImports""".optimizeImports()
}
val ${className.first().lowercase() + className.substring(1)}Module = module {
factory { StubDomainMapper() }
factory { StubPresentationMapper() }
factory<PerformActionRepository> { ${className}Repository() }
factoryOf(::PerformActionUseCase)
factoryOf(::${className}ViewModel)
factory { StubUiMapper() }
factoryOf(::${className}Dependencies)
}
"""
}
DependencyInjection.None -> error("Unexpected dependency injection option: $dependencyInjection")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ fun buildApplicationKotlinFile(
DependencyInjection.Koin -> {
val optimizedImports =
"""import $projectNamespace.di.architectureModule
import $projectNamespace.di.sampleFeatureModule
import android.app.Application
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
Expand All @@ -40,7 +41,7 @@ class ${appName}Application : Application() {
private fun initKoin(config : KoinAppDeclaration? = null){
startKoin {
includes(config)
modules(architectureModule)
modules(architectureModule, sampleFeatureModule)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.mitteloupe.cag.core.content

import com.mitteloupe.cag.core.generation.format.optimizeImports
import com.mitteloupe.cag.core.option.DependencyInjection

fun buildArchitectureDependencyInjectionModuleKotlinFile(
projectNamespace: String,
dependencyInjection: DependencyInjection
): String {
val commonImports =
"""import $projectNamespace.architecture.domain.UseCaseExecutor
"""
return when (dependencyInjection) {
DependencyInjection.Hilt -> {
"""package $projectNamespace.di

${
"""
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
$commonImports
""".optimizeImports()
}
@Module
@InstallIn(SingletonComponent::class)
object ArchitectureModule {
@Provides
fun providesUseCaseExecutor(): UseCaseExecutor = UseCaseExecutor()
}
"""
}
DependencyInjection.Koin -> {
"""package $projectNamespace.di

${
"""import org.koin.dsl.module
$commonImports
""".optimizeImports()
}
val architectureModule = module {
single { UseCaseExecutor() }
}
"""
}
DependencyInjection.None -> error("Unexpected dependency injection option: $dependencyInjection")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package com.mitteloupe.cag.core.generation.app
import com.mitteloupe.cag.core.AppModuleDirectoryFinder
import com.mitteloupe.cag.core.DirectoryFinder
import com.mitteloupe.cag.core.content.buildAndroidManifest
import com.mitteloupe.cag.core.content.buildAppFeatureModuleKotlinFile
import com.mitteloupe.cag.core.content.buildAppFeatureDependencyInjectionModuleKotlinFile
import com.mitteloupe.cag.core.content.buildApplicationKotlinFile
import com.mitteloupe.cag.core.content.buildArchitectureDependencyInjectionModuleKotlinFile
import com.mitteloupe.cag.core.content.buildBackupRulesXml
import com.mitteloupe.cag.core.content.buildColorsKt
import com.mitteloupe.cag.core.content.buildDataExtractionRulesXml
Expand All @@ -26,13 +27,50 @@ class AppModuleContentGenerator(
private val fileCreator: FileCreator,
private val directoryFinder: DirectoryFinder
) {
fun writeFeatureModuleIfPossible(
fun writeArchitectureDependencyInjectionModuleIfPossible(
startDirectory: File,
projectNamespace: String,
appModuleDirectory: File?,
dependencyInjection: DependencyInjection
) {
if (dependencyInjection is DependencyInjection.None) {
return
}

val rootDirectory =
appModuleDirectory ?: run {
val projectRoot = findGradleProjectRoot(startDirectory, directoryFinder) ?: startDirectory
val appModuleDirectories =
AppModuleDirectoryFinder(directoryFinder).findAndroidAppModuleDirectories(projectRoot)
if (appModuleDirectories.isEmpty()) {
return
} else {
appModuleDirectories.first()
}
}
val sourceRoot = File(rootDirectory, "src/main/java")
val basePackageDirectory = buildPackageDirectory(sourceRoot, projectNamespace.toSegments())
val dependencyInjectionDirectory = createDirectoryIfNotExists(basePackageDirectory, "di")
createFileIfNotExists(dependencyInjectionDirectory, "ArchitectureModule.kt") {
buildArchitectureDependencyInjectionModuleKotlinFile(
projectNamespace = projectNamespace,
dependencyInjection = dependencyInjection
)
}
}

fun writeFeatureDependencyInjectionModuleIfPossible(
startDirectory: File,
projectNamespace: String,
featureName: String,
featurePackageName: String,
appModuleDirectory: File?
appModuleDirectory: File?,
dependencyInjection: DependencyInjection
) {
if (dependencyInjection is DependencyInjection.None) {
return
}

val rootDirectory =
appModuleDirectory ?: run {
val projectRoot = findGradleProjectRoot(startDirectory, directoryFinder) ?: startDirectory
Expand All @@ -48,7 +86,12 @@ class AppModuleContentGenerator(
val basePackageDirectory = buildPackageDirectory(sourceRoot, projectNamespace.toSegments())
val dependencyInjectionDirectory = createDirectoryIfNotExists(basePackageDirectory, "di")
createFileIfNotExists(dependencyInjectionDirectory, "${featureName.capitalized}Module.kt") {
buildAppFeatureModuleKotlinFile(projectNamespace, featurePackageName, featureName)
buildAppFeatureDependencyInjectionModuleKotlinFile(
projectNamespace = projectNamespace,
featurePackageName = featurePackageName,
featureName = featureName,
dependencyInjection = dependencyInjection
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class ArchitectureModulesContentGenerator(
)
if (dependencyInjection == DependencyInjection.Hilt) {
addAll(LibraryConstants.HILT_LIBRARIES)
add(LibraryConstants.TEST_ANDROID_HILT)
}
addAll(
if (enableCompose) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.mitteloupe.cag.core.GenerationException
import com.mitteloupe.cag.core.generation.BuildSrcContentCreator
import com.mitteloupe.cag.core.generation.ConfigurationFileCreator
import com.mitteloupe.cag.core.generation.SettingsFileUpdater
import com.mitteloupe.cag.core.generation.app.AppModuleContentGenerator
import com.mitteloupe.cag.core.generation.architecture.ArchitectureModulesContentGenerator
import com.mitteloupe.cag.core.generation.architecture.CoroutineModuleContentGenerator
import com.mitteloupe.cag.core.kotlinpackage.toSegments
Expand All @@ -15,10 +16,13 @@ class ArchitectureFilesGenerator(
private val architectureModulesContentGenerator: ArchitectureModulesContentGenerator,
private val settingsFileUpdater: SettingsFileUpdater,
private val buildSrcContentCreator: BuildSrcContentCreator,
private val configurationFileCreator: ConfigurationFileCreator
private val configurationFileCreator: ConfigurationFileCreator,
private val appModuleContentGenerator: AppModuleContentGenerator
) {
fun generateArchitecture(
projectNamespace: String,
destinationRootDirectory: File,
appModuleDirectory: File?,
architecturePackageName: String,
dependencyInjection: DependencyInjection,
enableCompose: Boolean,
Expand Down Expand Up @@ -79,5 +83,12 @@ class ArchitectureFilesGenerator(
if (enableKtlint) {
configurationFileCreator.writeEditorConfigFile(destinationRootDirectory)
}

appModuleContentGenerator.writeArchitectureDependencyInjectionModuleIfPossible(
startDirectory = destinationRootDirectory,
projectNamespace = projectNamespace,
appModuleDirectory = appModuleDirectory,
dependencyInjection = dependencyInjection
)
}
}
Loading