All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.javiersc.hubdle.project.extensions.kotlin._internal.configureKotlinSourceSets.kt Maven / Gradle / Ivy

There is a newer version: 0.7.18
Show newest version
package com.javiersc.hubdle.project.extensions.kotlin._internal

import com.android.build.api.dsl.AndroidSourceDirectorySet
import com.android.build.api.dsl.AndroidSourceSet
import com.android.build.gradle.internal.tasks.factory.dependsOn
import com.javiersc.gradle.properties.extensions.setProperty
import com.javiersc.hubdle.project.extensions._internal.ApplicablePlugin.Scope
import com.javiersc.hubdle.project.extensions._internal.COMMON_MAIN
import com.javiersc.hubdle.project.extensions._internal.MAIN
import com.javiersc.hubdle.project.extensions._internal.TEST_FIXTURES
import com.javiersc.hubdle.project.extensions._internal.TEST_FUNCTIONAL
import com.javiersc.hubdle.project.extensions._internal.TEST_INTEGRATION
import com.javiersc.hubdle.project.extensions.android._internal.findAndroidCommonExtension
import com.javiersc.hubdle.project.extensions.apis.HubdleConfigurableExtension
import com.javiersc.hubdle.project.extensions.apis.HubdleSourceSetConfigurableExtension as HubdleSrcSetConfExt
import com.javiersc.hubdle.project.extensions.kotlin.multiplatform.hubdleKotlinMultiplatform
import com.javiersc.hubdle.project.extensions.shared.PluginId
import com.javiersc.hubdle.project.tasks.lifecycle.TestsTask
import com.javiersc.kotlin.stdlib.decapitalize
import java.io.File
import org.gradle.api.Project
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.provider.Provider
import org.gradle.api.provider.SetProperty
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.testing.Test
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.findByType
import org.gradle.kotlin.dsl.register
import org.gradle.language.base.plugins.LifecycleBasePlugin.CHECK_TASK_NAME
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget

internal fun HubdleSrcSetConfExt<*>.configurableTestFixtures() {
    applicablePlugin(
        isEnabled = isTestFixturesFullEnabled,
        scope = Scope.CurrentProject,
        pluginId = PluginId.JavaTestFixtures,
    )
    lazyConfigurable(isEnabled = isTestFixturesFullEnabled) {
        configure {
            targets.map { target ->
                val testFixturesCompilation = target.testFixturesCompilation
                val mainCompilation = target.mainCompilation
                if (testFixturesCompilation != null && mainCompilation != null) {
                    testFixturesCompilation.associateWith(mainCompilation)
                }
            }
        }
    }
}

internal fun HubdleSrcSetConfExt<*>.configurableTestIntegrationSourceSets() =
    lazyConfigurable(isEnabled = isTestFunctionalFullEnabled) {
        val testIntegrationSourceSet = the().maybeCreate(TEST_INTEGRATION)

        val integrationTestTask: TaskProvider =
            tasks.register("integrationTest") {
                testClassesDirs = testIntegrationSourceSet.output.classesDirs
                classpath = testIntegrationSourceSet.runtimeClasspath
                mustRunAfter(tasks.findByName("test"))
            }

        tasks.named(CHECK_TASK_NAME).dependsOn(integrationTestTask)

        tasks.named(TestsTask.NAME).dependsOn(integrationTestTask)

        project.dependencies {
            "testIntegrationImplementation"(project)
            if (isTestFixturesFullEnabled.get()) {
                "testIntegrationImplementation"(project.dependencies.testFixtures(project))
            }
        }
    }

internal fun HubdleSrcSetConfExt.configurableKotlinTestIntegrationSourceSets() {
    lazyConfigurable(isEnabled = isTestIntegrationEnabled) {
        configure {
            sourceSets.maybeCreate(TEST_INTEGRATION)
            targets.forEach { target ->
                target.configureAdditionalTestCompilations(TEST_INTEGRATION)
            }
        }
        testIntegration.configure {
            it.dependencies {
                implementation(project)
                if (isTestFixturesFullEnabled.get()) {
                    implementation(project.dependencies.testFixtures(project))
                }
            }
        }
    }
}

internal fun HubdleSrcSetConfExt<*>.configurableTestFunctionalSourceSets() {
    lazyConfigurable(isEnabled = isTestFunctionalFullEnabled) {
        val testFunctionalSourceSet = the().maybeCreate(TEST_FUNCTIONAL)

        val functionalTestTask: TaskProvider =
            tasks.register("functionalTest") {
                testClassesDirs = testFunctionalSourceSet.output.classesDirs
                classpath = testFunctionalSourceSet.runtimeClasspath
                mustRunAfter(tasks.findByName("test"))
            }

        tasks.named(CHECK_TASK_NAME).dependsOn(functionalTestTask)

        tasks.named(TestsTask.NAME).dependsOn(functionalTestTask)

        project.dependencies {
            "testFunctionalImplementation"(project)
            if (isTestFixturesFullEnabled.get()) {
                "testFunctionalImplementation"(project.dependencies.testFixtures(project))
            }
        }
    }
}

internal fun HubdleSrcSetConfExt.configurableKotlinTestFunctionalSourceSets() {
    lazyConfigurable(isEnabled = isTestFunctionalFullEnabled) {
        configure {
            sourceSets.maybeCreate(TEST_FUNCTIONAL)
            targets.forEach { target ->
                target.configureAdditionalTestCompilations(TEST_FUNCTIONAL)
            }
        }
        testFunctional.configure {
            it.dependencies {
                implementation(project)
                if (isTestFixturesFullEnabled.get()) {
                    implementation(project.dependencies.testFixtures(project))
                }
            }
        }
    }
}

internal fun HubdleConfigurableExtension.configurableSrcDirs(
    targets: SetProperty = setProperty { emptySet() }
) = beforeConfigurable {
    fun AndroidSourceDirectorySet.setSrc(name: Provider, dirName: String) {
        setSrcDirs(emptySet())
        srcDirs(project.normalAndGeneratedDirs(name.map { "$it/$dirName" }))
    }
    fun SourceDirectorySet.setSrc(name: Provider, dirName: String) {
        setSrcDirs(emptySet())
        srcDirs(project.normalAndGeneratedDirs(name.map { "$it/$dirName" }))
    }

    project.findAndroidCommonExtension()?.sourceSets?.configureEach { set: AndroidSourceSet ->
        val name: Provider = project.calculateKmpSourceSetDirectory(set.name, targets)
        val manifestPath: Provider = name.map { name -> "$name/AndroidManifest.xml" }
        if (!hubdleKotlinMultiplatform.isFullEnabled.get()) {
            set.assets.setSrc(name, "assets")
            set.java.setSrc(name, "java")
            set.kotlin.setSrc(name, "kotlin")
            set.res.setSrc(name, "res")
            set.resources.setSrc(name, "resources")
            set.manifest.srcFile(manifestPath)
        } else {
            set.manifest.srcFile(manifestPath)
        }
    }

    project.extensions.findByType()?.sourceSets?.configureEach { set ->
        val name: Provider = project.calculateKmpSourceSetDirectory(set.name, targets)
        set.java.setSrc(name, "java")
        set.kotlin.setSrc(name, "kotlin")
        set.resources.setSrc(name, "resources")
    }

    project.extensions.findByType()?.sourceSets?.configureEach { set ->
        val name: Provider = project.calculateKmpSourceSetDirectory(set.name, targets)
        set.kotlin.setSrc(name, "kotlin")
        set.resources.setSrc(name, "resources")
    }
}

internal fun Project.normalAndGeneratedDirs(dir: Provider): SetProperty =
    setProperty {
        setOf(
            projectDir.resolve(dir.get()),
            layout.buildDirectory.asFile.get().resolve("generated").resolve(dir.get()),
        )
    }

private fun Project.calculateKmpSourceSetDirectory(
    name: String,
    targetsProp: SetProperty,
): Provider =
    project.provider {
        val targets: Set = targetsProp.get().toSet()
        val target: String? =
            targets
                .filter { target -> name.startsWith(target) }
                .maxByOrNull { target -> target.count() }

        val directory: String =
            when {
                name.startsWith("androidNative") && target == "android" -> {
                    val type = name.substringAfter("androidNative").decapitalize()
                    "androidNative/$type"
                }
                target != null -> {
                    val type = name.substringAfter(target).decapitalize()
                    "$target/$type"
                }
                else -> name
            }
        directory
    }

private val SourceSet.kotlin: SourceDirectorySet
    get() = (this as ExtensionAware).extensions.getByName("kotlin") as SourceDirectorySet

private fun KotlinTarget.configureAdditionalTestCompilations(name: String) {
    val additionalTestCompilation = compilation(name)
    val testFixturesCompilation = testFixturesCompilation
    val mainCompilation = mainCompilation

    if (additionalTestCompilation != null) {
        mainCompilation?.let(additionalTestCompilation::associateWith)
        testFixturesCompilation?.let(additionalTestCompilation::associateWith)
    }
}

private val KotlinTarget.mainCompilation: KotlinCompilation?
    get() = compilation(COMMON_MAIN) ?: compilation(MAIN)

private val KotlinTarget.testFixturesCompilation: KotlinCompilation?
    get() = compilation(TEST_FIXTURES)

private fun KotlinTarget.compilation(name: String): KotlinCompilation<*>? =
    compilations.findByName(name)

private val KotlinProjectExtension.targets: Iterable
    get() =
        when (this) {
            is KotlinSingleTargetExtension<*> -> listOf(this.target)
            is KotlinMultiplatformExtension -> targets
            else -> error("Unexpected 'kotlin' extension $this")
        }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy