diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/NpmVersions.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/NpmVersions.kt index dc40267111e..e80a9e4f095 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/NpmVersions.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/NpmVersions.kt @@ -13,6 +13,8 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency * Package versions used by tasks */ class NpmVersions { + val dukat = NpmPackageVersion("dukat", "0.0.10") + val webpack = NpmPackageVersion("webpack", "4.29.6") val webpackCli = NpmPackageVersion("webpack-cli", "3.3.0") val webpackBundleAnalyzer = NpmPackageVersion("webpack-bundle-analyzer", "3.3.2") diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DtsResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DtsResolver.kt new file mode 100644 index 00000000000..bf634148f09 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DtsResolver.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2019 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.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency +import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject +import java.io.File + +class DtsResolver(val npmProject: NpmProject) { + private val typeModules = npmProject.modules.copy( + packageJsonEntries = listOf("types"), + indexFileSuffixes = listOf(".d.ts") + ) + + fun getAllDts(externalNpmDependencies: Collection): List = externalNpmDependencies + .filter { it.scope != NpmDependency.Scope.DEV } + .flatMap { it.getDependenciesRecursively() } + .mapNotNullTo(mutableSetOf()) { typeModules.resolve(it.key)?.let { file -> Dts(file, it) } } + .sortedBy { it.inputKey } + + class Dts(val file: File, val npmDependency: NpmDependency) { + val inputKey: String + get() = npmDependency.key + "@" + npmDependency.resolvedVersion + "#" + npmDependency.integrity + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as Dts + + if (file != other.file) return false + + return true + } + + override fun hashCode(): Int { + return file.hashCode() + } + + override fun toString(): String = inputKey + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatCompilationResolverPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatCompilationResolverPlugin.kt new file mode 100644 index 00000000000..0de4b92f846 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatCompilationResolverPlugin.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2019 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.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin +import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency +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.createOrRegisterTask + +internal class DukatCompilationResolverPlugin( + private val resolver: KotlinCompilationNpmResolver +) : CompilationResolverPlugin { + val project get() = resolver.project + val nodeJs get() = resolver.nodeJs + val npmProject get() = resolver.npmProject + val compilation get() = npmProject.compilation + val taskName = npmProject.compilation.disambiguateName("generateExternals") + + init { + compilation.defaultSourceSet.kotlin.srcDir(npmProject.externalsDir) + + val task = project.createOrRegisterTask(taskName) { + it.compilation = compilation + it.group = NodeJsRootPlugin.TASKS_GROUP_NAME + it.description = "Generate Kotlin/JS external declarations for .d.ts files in ${compilation}" + it.dependsOn(nodeJs.npmInstallTask, npmProject.packageJsonTask) + } + + compilation.compileKotlinTask.dependsOn(task.getTaskOrProvider()) + } + + override fun hookDependencies( + internalDependencies: MutableSet, + externalGradleDependencies: MutableSet, + externalNpmDependencies: MutableSet + ) { + if (nodeJs.experimental.discoverTypes) { + // todo: discoverTypes + } + } + + fun executeDukatIfNeeded( + packageJsonIsUpdated: Boolean, + resolution: KotlinRootNpmResolution + ) { + val externalNpmDependencies = resolution[project][compilation].externalNpmDependencies + + PackageJsonDukatExecutor( + nodeJs, + DtsResolver(npmProject).getAllDts(externalNpmDependencies), + npmProject, + packageJsonIsUpdated, + operation = compilation.name + " > " + PackageJsonDukatExecutor.OPERATION, + compareInputs = true + ).execute() + } + + companion object { + const val VERSION = "2" + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatExecutor.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatExecutor.kt new file mode 100644 index 00000000000..304a048ff74 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatExecutor.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2019 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.jetbrains.kotlin.gradle.internal.execWithProgress +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation +import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject +import java.io.File + +class DukatExecutor( + val compilation: KotlinJsCompilation, + val dTsFiles: Collection, + val destDir: File, + val qualifiedPackageName: String? = null, + val jsInteropJvmEngine: String? = null, + val operation: String = "Generating Kotlin/JS external declarations" +) { + fun execute() { + compilation.target.project.execWithProgress(operation) { exec -> + val args = mutableListOf() + + val qualifiedPackageName = qualifiedPackageName + if (qualifiedPackageName != null) { + args.add("-p") + args.add(qualifiedPackageName) + } + + args.add("-d") + args.add(destDir.absolutePath) + + val jsInteropJvmEngine = jsInteropJvmEngine + if (jsInteropJvmEngine != null) { + args.add("-js") + args.add(jsInteropJvmEngine) + } + + args.addAll(dTsFiles.map { it.absolutePath }) + + compilation.npmProject.useTool(exec, ".bin/dukat", *args.toTypedArray()) + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatRootResolverPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatRootResolverPlugin.kt new file mode 100644 index 00000000000..33ed24807f9 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatRootResolverPlugin.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2019 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.jetbrains.kotlin.gradle.targets.js.npm.plugins.RootResolverPlugin +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.targets.js.npm.resolver.KotlinRootNpmResolver + +internal class DukatRootResolverPlugin(val resolver: KotlinRootNpmResolver) : RootResolverPlugin { + val compilations = mutableListOf() + + override fun createCompilationResolverPlugins(resolver: KotlinCompilationNpmResolver): List { + val plugin = DukatCompilationResolverPlugin(resolver) + compilations.add(plugin) + return listOf(plugin) + } + + override fun close(resolution: KotlinRootNpmResolution) { + println("tests") + if (resolver.forceFullResolve) { + // inside idea import + compilations.forEach { + it.executeDukatIfNeeded(true, resolution) + } + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatTask.kt new file mode 100644 index 00000000000..f2e916deb77 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/DukatTask.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2019 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.AbstractTask +import org.gradle.api.tasks.* +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation +import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin +import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies +import java.io.File + +abstract class AbstractDukatTask : AbstractTask(), RequiresNpmDependencies { + private val nodeJs get() = NodeJsRootPlugin.apply(project.rootProject) + + override lateinit var compilation: KotlinJsCompilation + + override val nodeModulesRequired: Boolean + get() = true + + override val requiredNpmDependencies: Collection + get() = listOf(nodeJs.versions.dukat) + + /** + * Package name for the generated file (by default filename.d.ts renamed to filename.d.kt) + */ + @Input + @Optional + var qualifiedPackageName: String? = null + + /** + * Collection of d.ts files + */ + abstract val dTsFiles: List + + /** + * Destination directory for files with converted declarations + */ + @get:OutputDirectory + abstract val destDir: File + + val operation: String = "Generating Kotlin/JS external declarations" + + @TaskAction + open fun run() { + nodeJs.npmResolutionManager.checkRequiredDependencies(this) + + DukatExecutor( + compilation, + dTsFiles, + destDir, + qualifiedPackageName, + null, + operation + ).execute() + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/PackageJsonDukatExecutor.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/PackageJsonDukatExecutor.kt new file mode 100644 index 00000000000..4e33546250e --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/PackageJsonDukatExecutor.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2019 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.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension +import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject +import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinRootNpmResolution + +class PackageJsonDukatExecutor( + val nodeJs: NodeJsRootExtension, + val typeDefinitions: List, + val npmProject: NpmProject, + val packageJsonIsUpdated: Boolean, + val operation: String = OPERATION, + val compareInputs: Boolean = true +) { + companion object { + const val OPERATION = "Generating Kotlin/JS external declarations" + } + + val versionFile = npmProject.externalsDirRoot.resolve("version.txt") + val version = DukatCompilationResolverPlugin.VERSION + ", " + nodeJs.versions.dukat.version + val prevVersion = if (versionFile.exists()) versionFile.readText() else null + + val inputsFile = npmProject.externalsDirRoot.resolve("inputs.txt") + + val shouldSkip: Boolean + get() = inputsFile.isFile && prevVersion == version && !packageJsonIsUpdated + + fun execute() { + // delete file to run visit on error even without package.json updates + versionFile.delete() + + npmProject.externalsDirRoot.mkdirs() + val inputs = typeDefinitions.joinToString("\n") { it.inputKey } + + if (!compareInputs || !inputsFile.isFile || inputsFile.readText() != inputs) { + // delete file to run visit on error even without package.json updates + inputsFile.delete() + + npmProject.externalsDir.deleteRecursively() + DukatExecutor( + npmProject.compilation, + typeDefinitions.map { it.file }, + npmProject.externalsDir, + operation = operation + ).execute() + + inputsFile.writeText(inputs) + } + + versionFile.writeText(version) + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/PackageJsonDukatTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/PackageJsonDukatTask.kt new file mode 100644 index 00000000000..c9445112fd3 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/dukat/PackageJsonDukatTask.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2019 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.tasks.Input +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputDirectory +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin +import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject +import java.io.File + +open class PackageJsonDukatTask : AbstractDukatTask() { + private val nodeJs get() = NodeJsRootPlugin.apply(project.rootProject) + + val dts by lazy { + val resolvedCompilation = nodeJs.npmResolutionManager.requireInstalled()[project][compilation] + val dtsResolver = DtsResolver(resolvedCompilation.npmProject) + dtsResolver.getAllDts(resolvedCompilation.externalNpmDependencies) + } + + @get:Internal + override val dTsFiles: List + get() = dts.map { it.file } + + @get:Input + val inputs + get() = dts.map { it.inputKey } + + @get:OutputDirectory + override val destDir: File + get() = compilation.npmProject.externalsDir + + private val executer by lazy { + PackageJsonDukatExecutor(nodeJs, dts, compilation.npmProject, true, compareInputs = false) + } + + override fun run() { + executer.execute() + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension.kt index 6d06ffad561..9d2f7f79e6d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension.kt @@ -36,6 +36,13 @@ open class NodeJsRootExtension(val rootProject: Project) { var packageManager: NpmApi = Yarn + class Experimental { + var generateKotlinExternals: Boolean = false + var discoverTypes: Boolean = false + } + + val experimental = Experimental() + val nodeJsSetupTask: NodeJsSetupTask get() = rootProject.tasks.getByName(NodeJsSetupTask.NAME) as NodeJsSetupTask diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/KotlinNpmResolutionManager.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/KotlinNpmResolutionManager.kt index 89ae2239863..ddbef7c1c8e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/KotlinNpmResolutionManager.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/KotlinNpmResolutionManager.kt @@ -131,6 +131,7 @@ class KotlinNpmResolutionManager(val nodeJsSettings: NodeJsRootExtension) { val forceUpToDate = upToDate && !forceFullResolve state1.resolver.close(forceUpToDate).also { this.state = ResolutionState.Installed(it) + state1.resolver.closePlugins(it) } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmProject.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmProject.kt index 3bd82fde71b..95450898369 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmProject.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmProject.kt @@ -55,7 +55,13 @@ open class NpmProject(val compilation: KotlinJsCompilation) { val main: String get() = "kotlin/$name.js" - private val modules = object : NpmProjectModules(dir, nodeModulesDir) { + val externalsDirRoot: File + get() = project.buildDir.resolve("externals").resolve(name) + + val externalsDir: File + get() = externalsDirRoot.resolve("src") + + internal val modules = object : NpmProjectModules(dir, nodeModulesDir) { override val parent get() = rootNodeModules } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/plugins/CompilationResolverPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/plugins/CompilationResolverPlugin.kt new file mode 100644 index 00000000000..de1f137fd4f --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/plugins/CompilationResolverPlugin.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2019 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.npm.plugins + +import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency +import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinCompilationNpmResolver + +internal interface CompilationResolverPlugin { + fun hookDependencies( + internalDependencies: MutableSet, + externalGradleDependencies: MutableSet, + externalNpmDependencies: MutableSet + ) +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/plugins/RootResolverPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/plugins/RootResolverPlugin.kt new file mode 100644 index 00000000000..55391fbe0e7 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/plugins/RootResolverPlugin.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2010-2019 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.npm.plugins + +import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinRootNpmResolution +import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinCompilationNpmResolver + +internal interface RootResolverPlugin { + fun createCompilationResolverPlugins(resolver: KotlinCompilationNpmResolver): List + fun close(resolution: KotlinRootNpmResolution) +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt index 61badc7e0e9..5405dd65b2d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages import org.jetbrains.kotlin.gradle.plugin.usesPlatformOf +import org.jetbrains.kotlin.gradle.targets.js.dukat.DukatCompilationResolverPlugin import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency import org.jetbrains.kotlin.gradle.targets.js.npm.PackageJson import org.jetbrains.kotlin.gradle.targets.js.npm.fixSemver @@ -23,6 +24,7 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinPackageJsonTask import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency.Scope.* +import org.jetbrains.kotlin.gradle.targets.js.npm.plugins.CompilationResolverPlugin import java.io.File import java.io.Serializable @@ -39,6 +41,9 @@ internal class KotlinCompilationNpmResolver( val target get() = compilation.target val project get() = target.project val packageJsonTaskHolder = KotlinPackageJsonTask.create(compilation) + val plugins: List = projectResolver.resolver.plugins.flatMap { + it.createCompilationResolverPlugins(this) + } override fun toString(): String = "KotlinCompilationNpmResolver(${npmProject.name})" @@ -151,6 +156,14 @@ internal class KotlinCompilationNpmResolver( val main = compilation.target.compilations.findByName(KotlinCompilation.MAIN_COMPILATION_NAME) as KotlinJsCompilation internalDependencies.add(projectResolver[main]) } + + plugins.forEach { + it.hookDependencies( + internalDependencies, + externalGradleDependencies, + externalNpmDependencies + ) + } } private fun visitDependency(dependency: ResolvedDependency) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinProjectNpmResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinProjectNpmResolver.kt index 7661b0db15b..a65d6a91c50 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinProjectNpmResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinProjectNpmResolver.kt @@ -6,10 +6,8 @@ package org.jetbrains.kotlin.gradle.targets.js.npm.resolver import org.gradle.api.Project -import org.gradle.api.Task import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension -import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.dsl.kotlinExtensionOrNull import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinTarget @@ -17,7 +15,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinProjectNpmResolution -import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinPackageJsonTask /** * See [KotlinNpmResolutionManager] for details about resolution process. diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinRootNpmResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinRootNpmResolver.kt index 0ea857fb862..ffde5d50dcf 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinRootNpmResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinRootNpmResolver.kt @@ -8,9 +8,11 @@ package org.jetbrains.kotlin.gradle.targets.js.npm.resolver import org.gradle.api.Project import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation +import org.jetbrains.kotlin.gradle.targets.js.dukat.DukatRootResolverPlugin import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.npm.* import org.jetbrains.kotlin.gradle.targets.js.npm.GradleNodeModulesCache +import org.jetbrains.kotlin.gradle.targets.js.npm.plugins.RootResolverPlugin import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinRootNpmResolution @@ -24,6 +26,12 @@ internal class KotlinRootNpmResolver internal constructor( val rootProject: Project get() = nodeJs.rootProject + val plugins = mutableListOf().also { + if (nodeJs.experimental.generateKotlinExternals) { + it.add(DukatRootResolverPlugin(this)) + } + } + private var closed: Boolean = false val gradleNodeModules = GradleNodeModulesCache(nodeJs) @@ -92,7 +100,15 @@ internal class KotlinRootNpmResolver internal constructor( upToDateChecks.forEach { it.commit() } - return KotlinRootNpmResolution(rootProject, projectResolutions) + val resolution = KotlinRootNpmResolution(rootProject, projectResolutions) + + return resolution + } + + fun closePlugins(resolution: KotlinRootNpmResolution) { + plugins.forEach { + it.close(resolution) + } } private fun removeOutdatedPackages(nodeJs: NodeJsRootExtension, allNpmPackages: List) {