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

org.jetbrains.kotlin.gradle.targets.js.dukat.DukatCompilationResolverPlugin.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-Beta1
Show newest version
/*
 * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.gradle.targets.js.dukat

import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject
import org.jetbrains.kotlin.gradle.targets.js.npm.isCompatibleArchive
import org.jetbrains.kotlin.gradle.targets.js.npm.plugins.CompilationResolverPlugin
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinRootNpmResolution
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinCompilationNpmResolver
import org.jetbrains.kotlin.gradle.tasks.dependsOn
import org.jetbrains.kotlin.gradle.tasks.registerTask

internal class DukatCompilationResolverPlugin(
    @Transient
    private val resolver: KotlinCompilationNpmResolver
) : CompilationResolverPlugin {
    val project get() = resolver.project
    val nodeJs get() = resolver.nodeJs
    val versions by lazy { nodeJs.versions }
    val npmProject by lazy { resolver.npmProject }
    val compilation get() = npmProject.compilation
    val compilationName by lazy {
        compilation.disambiguatedName
    }
    val legacyTargetReuseIrTask by lazy {
        val target = compilation.target
        target is KotlinJsTarget && (target.irTarget != null && externalsOutputFormat == ExternalsOutputFormat.SOURCE)
    }
    val externalsOutputFormat by lazy {
        compilation.externalsOutputFormat
    }
    val integratedTaskName = npmProject.compilation.disambiguateName(GENERATE_EXTERNALS_INTEGRATED_TASK_SIMPLE_NAME)
    val separateTaskName = npmProject.compilation.disambiguateName(GENERATE_EXTERNALS_TASK_SIMPLE_NAME)

    private fun registerIntegratedTask(): TaskProvider {
        return project.registerTask(
            integratedTaskName,
            listOf(compilation)
        ) {
            it.group = DUKAT_TASK_GROUP
            it.description = "Integrated generation Kotlin/JS external declarations for .d.ts files in $compilation"
            it.externalsOutputFormat = externalsOutputFormat
            it.dependsOn(nodeJs.npmInstallTaskProvider, npmProject.packageJsonTask)
        }
    }

    init {
        val externalsOutputFormat = compilation.externalsOutputFormat

        gradleModelPostProcess(externalsOutputFormat, npmProject)

        var integratedTask: TaskProvider? = null
        if (compilation.shouldDependOnDukatIntegrationTask()) {
            val task = integratedTask ?: registerIntegratedTask().also { integratedTask = it }
            compilation.compileKotlinTaskProvider.dependsOn(task)
        }

        if (compilation.shouldLegacyUseIrTargetDukatIntegrationTask()) {
            (compilation.target as KotlinJsIrTarget).legacyTarget?.compilations?.named(compilation.name) {
                val task = integratedTask ?: registerIntegratedTask()
                if (it.externalsOutputFormat == ExternalsOutputFormat.SOURCE) {
                    it.compileKotlinTaskProvider.dependsOn(task)
                }
            }
        }

        project.registerTask(
            separateTaskName,
            listOf(compilation)
        ) {
            it.group = DUKAT_TASK_GROUP
            it.description = "Generate Kotlin/JS external declarations for .d.ts files of all NPM dependencies in ${compilation}"
            it.dependsOn(nodeJs.npmInstallTaskProvider, npmProject.packageJsonTask)
        }
    }

    override fun hookDependencies(
        internalDependencies: Set,
        internalCompositeDependencies: Set,
        externalGradleDependencies: Set,
        externalNpmDependencies: Set,
        fileCollectionDependencies: Set
    ) {
        if (nodeJs.experimental.discoverTypes) {
            // todo: discoverTypes
        }
    }

    fun executeDukatIfNeeded(
        packageJsonIsUpdated: Boolean,
        resolution: KotlinRootNpmResolution
    ) {
        val externalNpmDependencies = resolution[project.path][compilationName].externalNpmDependencies



        if (legacyTargetReuseIrTask) {
            return
        }

        DukatExecutor(
            versions,
            DtsResolver(npmProject).getAllDts(externalNpmDependencies),
            externalsOutputFormat,
            npmProject,
            packageJsonIsUpdated,
            operation = compilation.name + " > " + DukatExecutor.OPERATION,
            compareInputs = true
        ).execute((project as ProjectInternal).services)
    }

    companion object {
        const val VERSION = "3"
        internal const val GENERATE_EXTERNALS_INTEGRATED_TASK_SIMPLE_NAME = "generateExternalsIntegrated"
        internal const val GENERATE_EXTERNALS_TASK_SIMPLE_NAME = "generateExternals"

        internal fun KotlinJsCompilation.shouldDependOnDukatIntegrationTask(): Boolean = with(target) {
            this is KotlinJsIrTarget ||
                (this is KotlinJsTarget &&
                    (irTarget == null || externalsOutputFormat != ExternalsOutputFormat.SOURCE)
                    )
        }

        internal fun KotlinJsCompilation.shouldLegacyUseIrTargetDukatIntegrationTask(): Boolean =
            with(target) {
                this is KotlinJsIrTarget && legacyTarget != null
            }
    }
}

internal fun gradleModelPostProcess(
    externalsOutputFormat: ExternalsOutputFormat,
    npmProject: NpmProject
) {
    val compilation = npmProject.compilation
    val project = npmProject.project
    when (externalsOutputFormat) {
        ExternalsOutputFormat.SOURCE -> compilation.defaultSourceSet.kotlin.srcDir(npmProject.externalsDir)
        ExternalsOutputFormat.BINARY -> {
            project.dependencies.add(
                compilation.compileDependencyConfigurationName,
                project.fileTree(npmProject.externalsDir).include {
                    it.file.isCompatibleArchive
                }
            )
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy