Gradle, JS: rework NpmResolver
Now resolving works per compilation, so transitive dependency between compilations in same project can be resolved (KT-31917). Resolving gradle configurations now occurs in separate per-project `KotlinPackageJsonTask`s. Global install called in `KotlinNpmInstallTask`. Tasks inputs configured, so tasks now reported as UP-TO-DATE if nothing was changed. #KT-31565 Fixed #KT-32015 Fixed #KT-31917 Fixed
This commit is contained in:
+15
-1
@@ -11,7 +11,10 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinTargetConfigurator
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinPackageJsonTask
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.createOrRegisterTask
|
||||||
|
|
||||||
open class KotlinJsTargetConfigurator(kotlinPluginVersion: String) :
|
open class KotlinJsTargetConfigurator(kotlinPluginVersion: String) :
|
||||||
KotlinTargetConfigurator<KotlinJsCompilation>(true, true, kotlinPluginVersion) {
|
KotlinTargetConfigurator<KotlinJsCompilation>(true, true, kotlinPluginVersion) {
|
||||||
@@ -22,7 +25,18 @@ open class KotlinJsTargetConfigurator(kotlinPluginVersion: String) :
|
|||||||
super.configureTarget(target)
|
super.configureTarget(target)
|
||||||
|
|
||||||
target.compilations.forEach {
|
target.compilations.forEach {
|
||||||
it.compileKotlinTask.dependsOn(target.project.nodeJs.root.npmResolveTask)
|
val npmResolveTask = target.project.nodeJs.root.npmInstallTask
|
||||||
|
val npmProject = it.npmProject
|
||||||
|
|
||||||
|
val packageJsonTaskName = npmProject.packageJsonTaskName
|
||||||
|
npmResolveTask.dependsOn(packageJsonTaskName)
|
||||||
|
|
||||||
|
target.project.createOrRegisterTask<KotlinPackageJsonTask>(packageJsonTaskName) { task ->
|
||||||
|
task.compilation = it
|
||||||
|
task.description = "Create package.json file for $it"
|
||||||
|
}
|
||||||
|
|
||||||
|
it.compileKotlinTask.dependsOn(npmResolveTask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import org.gradle.api.tasks.AbstractExecTask
|
|||||||
open class NodeJsExec : AbstractExecTask<NodeJsExec>(NodeJsExec::class.java) {
|
open class NodeJsExec : AbstractExecTask<NodeJsExec>(NodeJsExec::class.java) {
|
||||||
init {
|
init {
|
||||||
val nodeJs = NodeJsPlugin.apply(project).root
|
val nodeJs = NodeJsPlugin.apply(project).root
|
||||||
dependsOn(nodeJs.npmResolveTask)
|
dependsOn(nodeJs.npmInstallTask)
|
||||||
|
|
||||||
executable = nodeJs.environment.nodeExecutable
|
executable = nodeJs.environment.nodeExecutable
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -5,7 +5,7 @@ import org.gradle.api.Project
|
|||||||
import org.gradle.api.plugins.BasePlugin
|
import org.gradle.api.plugins.BasePlugin
|
||||||
import org.gradle.api.tasks.Delete
|
import org.gradle.api.tasks.Delete
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension.Companion.EXTENSION_NAME
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension.Companion.EXTENSION_NAME
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolveTask
|
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask
|
||||||
|
|
||||||
open class NodeJsPlugin : Plugin<Project> {
|
open class NodeJsPlugin : Plugin<Project> {
|
||||||
override fun apply(project: Project): Unit = project.run {
|
override fun apply(project: Project): Unit = project.run {
|
||||||
@@ -20,7 +20,7 @@ open class NodeJsPlugin : Plugin<Project> {
|
|||||||
it.description = "Download and install a local node/npm version"
|
it.description = "Download and install a local node/npm version"
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.create(NpmResolveTask.NAME, NpmResolveTask::class.java) {
|
tasks.create(KotlinNpmInstallTask.NAME, KotlinNpmInstallTask::class.java) {
|
||||||
it.dependsOn(setupTask)
|
it.dependsOn(setupTask)
|
||||||
it.outputs.upToDateWhen { false }
|
it.outputs.upToDateWhen { false }
|
||||||
it.group = TASKS_GROUP_NAME
|
it.group = TASKS_GROUP_NAME
|
||||||
|
|||||||
+3
-3
@@ -3,7 +3,7 @@ package org.jetbrains.kotlin.gradle.targets.js.nodejs
|
|||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
|
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolveTask
|
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.Yarn
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.Yarn
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -25,8 +25,8 @@ open class NodeJsRootExtension(project: Project) : NodeJsExtension(project) {
|
|||||||
val nodeJsSetupTask: NodeJsSetupTask
|
val nodeJsSetupTask: NodeJsSetupTask
|
||||||
get() = project.tasks.getByName(NodeJsSetupTask.NAME) as NodeJsSetupTask
|
get() = project.tasks.getByName(NodeJsSetupTask.NAME) as NodeJsSetupTask
|
||||||
|
|
||||||
val npmResolveTask: NpmResolveTask
|
val npmInstallTask: KotlinNpmInstallTask
|
||||||
get() = project.tasks.getByName(NpmResolveTask.NAME) as NpmResolveTask
|
get() = project.tasks.getByName(KotlinNpmInstallTask.NAME) as KotlinNpmInstallTask
|
||||||
|
|
||||||
val rootPackageDir: File
|
val rootPackageDir: File
|
||||||
get() = project.buildDir.resolve("js")
|
get() = project.buildDir.resolve("js")
|
||||||
|
|||||||
+12
-40
@@ -23,53 +23,25 @@ internal class GradleNodeModulesCache(val project: Project) : AutoCloseable {
|
|||||||
|
|
||||||
internal val dir = project.nodeJs.root.nodeModulesGradleCacheDir
|
internal val dir = project.nodeJs.root.nodeModulesGradleCacheDir
|
||||||
private val cache = ProcessedFilesCache(project, dir, STATE_FILE_NAME, "8")
|
private val cache = ProcessedFilesCache(project, dir, STATE_FILE_NAME, "8")
|
||||||
private val visited = mutableSetOf<ResolvedDependency>()
|
|
||||||
|
|
||||||
fun collectDependenciesFromConfiguration(configuration: Configuration, result: NpmGradleDependencies) {
|
fun ensureImported(
|
||||||
if (configuration.isCanBeResolved) {
|
artifact: ResolvedArtifact,
|
||||||
configuration.resolvedConfiguration.firstLevelModuleDependencies.forEach {
|
|
||||||
visitDependency(it, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun visitDependency(dependency: ResolvedDependency, result: NpmGradleDependencies) {
|
|
||||||
if (!visited.add(dependency)) return
|
|
||||||
|
|
||||||
visitArtifacts(dependency, dependency.moduleArtifacts, result)
|
|
||||||
|
|
||||||
dependency.children.forEach {
|
|
||||||
visitDependency(it, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun visitArtifacts(
|
|
||||||
dependency: ResolvedDependency,
|
dependency: ResolvedDependency,
|
||||||
artifacts: MutableSet<ResolvedArtifact>,
|
artifacts: MutableSet<ResolvedArtifact>,
|
||||||
result: NpmGradleDependencies
|
result: NpmGradleDependencies
|
||||||
) {
|
) {
|
||||||
artifacts.forEach { artifact ->
|
val key = cache.getOrCompute(artifact.file) {
|
||||||
val componentIdentifier = artifact.id.componentIdentifier
|
val module = GradleNodeModuleBuilder(project, dependency, artifacts, this)
|
||||||
if (componentIdentifier is ProjectComponentIdentifier) {
|
module.visitArtifacts()
|
||||||
val dependentProject = project.findProject(componentIdentifier.projectPath)
|
module.rebuild()?.let {
|
||||||
?: error("Cannot find project ${componentIdentifier.projectPath}")
|
it.name + ":" + it.version
|
||||||
|
|
||||||
result.internalModules.add(dependentProject)
|
|
||||||
} else {
|
|
||||||
val key = cache.getOrCompute(artifact.file) {
|
|
||||||
val module = GradleNodeModuleBuilder(project, dependency, artifacts, this)
|
|
||||||
module.visitArtifacts()
|
|
||||||
module.rebuild()?.let {
|
|
||||||
it.name + ":" + it.version
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key != null) {
|
|
||||||
val (name, version) = key.split(":")
|
|
||||||
result.externalModules.add(GradleNodeModule(name, version, importedPackageDir(dir, name, version)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key != null) {
|
||||||
|
val (name, version) = key.split(":")
|
||||||
|
result.externalModules.add(GradleNodeModule(name, version, importedPackageDir(dir, name, version)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
|
|||||||
+2
-1
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.gradle.targets.js.npm
|
package org.jetbrains.kotlin.gradle.targets.js.npm
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.NpmProjectPackage
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NodeJS package manager API
|
* NodeJS package manager API
|
||||||
@@ -17,7 +18,7 @@ interface NpmApi {
|
|||||||
|
|
||||||
fun resolveRootProject(
|
fun resolveRootProject(
|
||||||
rootProject: Project,
|
rootProject: Project,
|
||||||
subProjects: MutableList<NpmProjectPackage>
|
subProjects: Collection<NpmProjectPackage>
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+9
-10
@@ -16,7 +16,9 @@ import org.gradle.api.internal.artifacts.dependencies.SelfResolvingDependencyInt
|
|||||||
import org.gradle.api.tasks.TaskDependency
|
import org.gradle.api.tasks.TaskDependency
|
||||||
import org.gradle.internal.component.local.model.DefaultLibraryBinaryIdentifier
|
import org.gradle.internal.component.local.model.DefaultLibraryBinaryIdentifier
|
||||||
import org.jetbrains.kotlin.gradle.internal.isInIdeaSync
|
import org.jetbrains.kotlin.gradle.internal.isInIdeaSync
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolver.ResolutionCallResult.*
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinProjectNpmResolution
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.NpmProjectPackage
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinNpmResolver
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
data class NpmDependency(
|
data class NpmDependency(
|
||||||
@@ -82,20 +84,17 @@ data class NpmDependency(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveProject(): NpmProjectPackage? {
|
private fun resolveProject(): NpmProjectPackage? {
|
||||||
val result =
|
val resolvedProject =
|
||||||
if (isInIdeaSync) NpmResolver.resolveIfNeeded(project)
|
if (isInIdeaSync) KotlinNpmResolver.resolveIfNeeded(project)
|
||||||
else NpmResolver.getAlreadyResolvedOrNull(project)
|
else KotlinNpmResolver.getAlreadyResolvedOrNull(project)
|
||||||
|
|
||||||
return when (result) {
|
return when (resolvedProject) {
|
||||||
null -> null
|
null -> null
|
||||||
is AlreadyInProgress -> null
|
else -> findIn(resolvedProject) ?: error("Project hierarchy is already resolved in NPM without $this")
|
||||||
is AlreadyResolved -> findIn(result.resolution)
|
|
||||||
?: error("Project hierarchy is already resolved in NPM without $this")
|
|
||||||
is ResolvedNow -> findIn(result.resolution) ?: error("Cannot find $this after NPM project resolve")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findIn(npmProjects: NpmProjects) =
|
private fun findIn(npmProjects: KotlinProjectNpmResolution) =
|
||||||
npmProjects.npmProjectsByNpmDependency[this]
|
npmProjects.npmProjectsByNpmDependency[this]
|
||||||
|
|
||||||
val key: String = if (org == null) name else "@$org/$name"
|
val key: String = if (org == null) name else "@$org/$name"
|
||||||
|
|||||||
+6
-1
@@ -10,7 +10,9 @@ import org.gradle.process.ExecSpec
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinNpmResolver
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
val KotlinJsCompilation.npmProject: NpmProject
|
val KotlinJsCompilation.npmProject: NpmProject
|
||||||
@@ -41,6 +43,9 @@ open class NpmProject(val compilation: KotlinJsCompilation) {
|
|||||||
val packageJsonFile: File
|
val packageJsonFile: File
|
||||||
get() = dir.resolve(PACKAGE_JSON)
|
get() = dir.resolve(PACKAGE_JSON)
|
||||||
|
|
||||||
|
val packageJsonTaskName: String
|
||||||
|
get() = compilation.disambiguateName("packageJson")
|
||||||
|
|
||||||
val main: String
|
val main: String
|
||||||
get() = "kotlin/$name.js"
|
get() = "kotlin/$name.js"
|
||||||
|
|
||||||
@@ -61,7 +66,7 @@ open class NpmProject(val compilation: KotlinJsCompilation) {
|
|||||||
* Require [request] nodejs module and return canonical path to it's main js file.
|
* Require [request] nodejs module and return canonical path to it's main js file.
|
||||||
*/
|
*/
|
||||||
fun require(request: String): String {
|
fun require(request: String): String {
|
||||||
NpmResolver.requireResolved(project)
|
KotlinNpmResolver.requireResolved(project)
|
||||||
return modules.require(request)
|
return modules.require(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-180
@@ -1,180 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.artifacts.Configuration
|
|
||||||
import org.gradle.api.attributes.Usage
|
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
|
|
||||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtensionOrNull
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
|
||||||
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.RequiredKotlinJsDependency
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Visits given gradle [project] for all of its [NpmProject],
|
|
||||||
* creates `package.json` for them ([NpmProjectPackage]) and runs
|
|
||||||
* selected [NodeJsRootExtension.packageManager] to download and install all of it's dependencies.
|
|
||||||
*/
|
|
||||||
internal class NpmProjectVisitor(val resolver: NpmResolver, val project: Project) {
|
|
||||||
private val npmProjects = mutableListOf<NpmProjectPackage>()
|
|
||||||
private val byCompilation = mutableMapOf<KotlinJsCompilation, NpmProjectPackage>()
|
|
||||||
private val byNpmDependency = mutableMapOf<NpmDependency, NpmProjectPackage>()
|
|
||||||
private val taskRequirements = mutableMapOf<RequiresNpmDependencies, Collection<RequiredKotlinJsDependency>>()
|
|
||||||
private val requiredFromTasksByCompilation = mutableMapOf<KotlinJsCompilation, MutableList<RequiresNpmDependencies>>()
|
|
||||||
|
|
||||||
private fun addTaskRequirements(task: RequiresNpmDependencies) {
|
|
||||||
val requirements = task.requiredNpmDependencies.toList()
|
|
||||||
|
|
||||||
taskRequirements[task] = requirements
|
|
||||||
|
|
||||||
requiredFromTasksByCompilation
|
|
||||||
.getOrPut(task.compilation) { mutableListOf() }
|
|
||||||
.add(task)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addNpmProject(resolved: NpmProjectPackage) {
|
|
||||||
val compilation = resolved.npmProject.compilation
|
|
||||||
byCompilation[compilation] = resolved
|
|
||||||
resolved.npmDependencies.forEach {
|
|
||||||
byNpmDependency[it] = resolved
|
|
||||||
}
|
|
||||||
npmProjects.add(resolved)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun visitProject(): NpmProjects {
|
|
||||||
visitTasksRequiredDependencies()
|
|
||||||
|
|
||||||
val kotlin = project.kotlinExtensionOrNull
|
|
||||||
|
|
||||||
if (kotlin != null) {
|
|
||||||
when (kotlin) {
|
|
||||||
is KotlinSingleTargetExtension -> visitTarget(kotlin.target)
|
|
||||||
is KotlinMultiplatformExtension -> kotlin.targets.forEach {
|
|
||||||
visitTarget(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NpmProjects(
|
|
||||||
project,
|
|
||||||
npmProjects,
|
|
||||||
byCompilation,
|
|
||||||
byNpmDependency,
|
|
||||||
taskRequirements
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun visitTasksRequiredDependencies() {
|
|
||||||
project.tasks.toList().forEach { task ->
|
|
||||||
if (task.enabled && task is RequiresNpmDependencies) {
|
|
||||||
addTaskRequirements(task)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun visitTarget(target: KotlinTarget) {
|
|
||||||
if (target.platformType == KotlinPlatformType.js) {
|
|
||||||
target.compilations.toList().forEach { compilation ->
|
|
||||||
if (compilation is KotlinJsCompilation) {
|
|
||||||
// compilation may be KotlinWithJavaTarget for old Kotlin2JsPlugin
|
|
||||||
visitCompilation(compilation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun visitCompilation(compilation: KotlinJsCompilation) {
|
|
||||||
val project = compilation.target.project
|
|
||||||
val npmProject = compilation.npmProject
|
|
||||||
val name = npmProject.name
|
|
||||||
val packageJson = PackageJson(
|
|
||||||
name,
|
|
||||||
fixSemver(project.version.toString())
|
|
||||||
)
|
|
||||||
val npmDependencies = mutableSetOf<NpmDependency>()
|
|
||||||
val gradleDeps = NpmGradleDependencies()
|
|
||||||
|
|
||||||
val aggregateConfiguration = project.configurations.create("$name-npm") {
|
|
||||||
it.usesPlatformOf(compilation.target)
|
|
||||||
it.attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.consumerRuntimeUsage(compilation.target))
|
|
||||||
it.isVisible = false
|
|
||||||
it.isCanBeConsumed = false
|
|
||||||
it.isCanBeResolved = true
|
|
||||||
it.description = "NPM configuration for $compilation."
|
|
||||||
}
|
|
||||||
|
|
||||||
compilation.allKotlinSourceSets.forEach { sourceSet ->
|
|
||||||
sourceSet.relatedConfigurationNames.forEach { configurationName ->
|
|
||||||
val configuration = project.configurations.getByName(configurationName)
|
|
||||||
aggregateConfiguration.extendsFrom(configuration)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
packageJson.main = npmProject.main
|
|
||||||
|
|
||||||
val requiredByTasks = requiredFromTasksByCompilation[compilation]
|
|
||||||
var nodeModulesRequired = false
|
|
||||||
if (requiredByTasks != null && requiredByTasks.isNotEmpty()) {
|
|
||||||
val toolsConfiguration = project.configurations.create("$name-jsTools")
|
|
||||||
requiredByTasks.forEach {
|
|
||||||
if (it.nodeModulesRequired) nodeModulesRequired = true
|
|
||||||
it.requiredNpmDependencies.forEach { requirement ->
|
|
||||||
toolsConfiguration.dependencies.add(requirement.createDependency(project))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
aggregateConfiguration.extendsFrom(toolsConfiguration)
|
|
||||||
}
|
|
||||||
|
|
||||||
visitConfiguration(aggregateConfiguration, npmDependencies, gradleDeps)
|
|
||||||
|
|
||||||
npmDependencies.forEach {
|
|
||||||
packageJson.dependencies[it.key] = resolver.chooseVersion(packageJson.dependencies[it.key], it.version)
|
|
||||||
}
|
|
||||||
|
|
||||||
gradleDeps.externalModules.forEach {
|
|
||||||
packageJson.dependencies[it.name] = it.version
|
|
||||||
}
|
|
||||||
|
|
||||||
gradleDeps.internalModules.forEach { target ->
|
|
||||||
val resolvedTarget = resolver.findDependentResolvedNpmProject(project, target)
|
|
||||||
if (resolvedTarget != null) {
|
|
||||||
packageJson.dependencies[resolvedTarget.packageJson.name] = resolvedTarget.packageJson.version
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
project.nodeJs.packageJsonHandlers.forEach {
|
|
||||||
it(packageJson)
|
|
||||||
}
|
|
||||||
|
|
||||||
val npmPackage = NpmProjectPackage(project, npmProject, npmDependencies, gradleDeps, packageJson, nodeModulesRequired)
|
|
||||||
npmPackage.packageJson.saveTo(npmProject.packageJsonFile)
|
|
||||||
|
|
||||||
resolver.packageManager.resolveProject(npmPackage)
|
|
||||||
|
|
||||||
addNpmProject(npmPackage)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun visitConfiguration(
|
|
||||||
configuration: Configuration,
|
|
||||||
npmDependencies: MutableSet<NpmDependency>,
|
|
||||||
gradleDependencies: NpmGradleDependencies
|
|
||||||
) {
|
|
||||||
resolver.gradleNodeModules.collectDependenciesFromConfiguration(configuration, gradleDependencies)
|
|
||||||
|
|
||||||
configuration.allDependencies.forEach { dependency ->
|
|
||||||
when (dependency) {
|
|
||||||
is NpmDependency -> npmDependencies.add(dependency)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-20
@@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
|
|
||||||
import org.gradle.api.internal.AbstractTask
|
|
||||||
import org.gradle.api.tasks.TaskAction
|
|
||||||
|
|
||||||
open class NpmResolveTask : AbstractTask() {
|
|
||||||
@TaskAction
|
|
||||||
fun resolve() {
|
|
||||||
NpmResolver.resolveIfNeeded(project)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val NAME = "kotlinNpmResolve"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-151
@@ -1,151 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2019 JetBrains s.r.o. 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
|
|
||||||
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolver.ResolutionCallResult.*
|
|
||||||
import java.nio.file.Files
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates `package.json` file for [NpmProject] with npm or js dependencies and
|
|
||||||
* runs selected [NodeJsRootExtension.packageManager] to download and install all of it's dependencies.
|
|
||||||
*
|
|
||||||
* All [NpmDependency] for configurations related to kotlin/js will be added to `package.json`.
|
|
||||||
* For external gradle modules, fake npm packages will be created and added to `package.json`
|
|
||||||
* as path to directory.
|
|
||||||
*/
|
|
||||||
internal class NpmResolver private constructor(val rootProject: Project) {
|
|
||||||
companion object {
|
|
||||||
fun resolveIfNeeded(project: Project): ResolutionCallResult {
|
|
||||||
val process = ProjectData[project]
|
|
||||||
|
|
||||||
if (process != null && process.visit == null) return AlreadyInProgress
|
|
||||||
|
|
||||||
val resolved = process?.visit
|
|
||||||
|
|
||||||
return if (resolved != null) AlreadyResolved(resolved)
|
|
||||||
else {
|
|
||||||
run(project.rootProject)
|
|
||||||
ResolvedNow(ProjectData[project]!!.visit!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun run(rootProject: Project) {
|
|
||||||
NpmResolver(rootProject).resolve()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getAlreadyResolvedOrNull(project: Project): ResolutionCallResult? {
|
|
||||||
val rootProject = project.rootProject
|
|
||||||
val process = ProjectData[rootProject]
|
|
||||||
if (process != null && process.visit == null) return AlreadyInProgress
|
|
||||||
val resolved = process?.visit
|
|
||||||
if (resolved != null) return AlreadyResolved(ProjectData[project]!!.visit!!)
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun requireResolved(project: Project, reason: String = ""): NpmProjects =
|
|
||||||
ProjectData[project]?.visit ?: error("NPM dependencies should be resolved $reason")
|
|
||||||
|
|
||||||
fun checkRequiredDependencies(project: Project, target: RequiresNpmDependencies) {
|
|
||||||
val requestedTaskDependencies = requireResolved(project, "before $target execution").taskRequirements
|
|
||||||
val targetRequired = requestedTaskDependencies[target]?.toSet() ?: setOf()
|
|
||||||
|
|
||||||
target.requiredNpmDependencies.forEach {
|
|
||||||
check(it in targetRequired) {
|
|
||||||
"$it required by $target was not found resolved at the time of nodejs package manager call. " +
|
|
||||||
"This may be caused by changing $target configuration after npm dependencies resolution."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class ResolutionCallResult {
|
|
||||||
object AlreadyInProgress : ResolutionCallResult()
|
|
||||||
class AlreadyResolved(val resolution: NpmProjects) : ResolutionCallResult()
|
|
||||||
class ResolvedNow(val resolution: NpmProjects) : ResolutionCallResult()
|
|
||||||
}
|
|
||||||
|
|
||||||
val gradleNodeModules = GradleNodeModulesCache(rootProject)
|
|
||||||
val nodeJs = NodeJsPlugin.apply(rootProject).root
|
|
||||||
val packageManager
|
|
||||||
get() = nodeJs.packageManager
|
|
||||||
|
|
||||||
private val allNpmPackages = mutableListOf<NpmProjectPackage>()
|
|
||||||
|
|
||||||
class ProjectData(var visit: NpmProjects? = null) {
|
|
||||||
companion object {
|
|
||||||
private const val KEY = "npmResolverData"
|
|
||||||
operator fun get(project: Project) = project.extensions.findByName(KEY) as ProjectData?
|
|
||||||
operator fun set(project: Project, value: ProjectData) = project.extensions.add(KEY, value)
|
|
||||||
fun getOrPut(project: Project) = this[project] ?: ProjectData().also { this[project] = it }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun resolve() {
|
|
||||||
resolve(rootProject)
|
|
||||||
removeOutdatedPackages()
|
|
||||||
gradleNodeModules.close()
|
|
||||||
|
|
||||||
if (allNpmPackages.any { it.npmDependencies.isNotEmpty() }) {
|
|
||||||
packageManager.resolveRootProject(rootProject, allNpmPackages)
|
|
||||||
} else if (allNpmPackages.any { it.hasNodeModulesDependentTasks }) {
|
|
||||||
NpmSimpleLinker(rootProject).link(allNpmPackages)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun removeOutdatedPackages() {
|
|
||||||
val packages = allNpmPackages.mapTo(mutableSetOf()) { it.npmProject.name }
|
|
||||||
nodeJs.projectPackagesDir.listFiles()?.forEach {
|
|
||||||
if (it.name !in packages) {
|
|
||||||
it.deleteRecursively()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getOrResolve(project: Project): NpmProjects {
|
|
||||||
return ProjectData[project]?.visit ?: resolve(project)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resolve(project: Project): NpmProjects {
|
|
||||||
val data = ProjectData.getOrPut(project)
|
|
||||||
|
|
||||||
project.subprojects.forEach {
|
|
||||||
getOrResolve(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
val visited = NpmProjectVisitor(this, project).visitProject()
|
|
||||||
data.visit = visited
|
|
||||||
|
|
||||||
allNpmPackages.addAll(visited.npmProjects)
|
|
||||||
|
|
||||||
return visited
|
|
||||||
}
|
|
||||||
|
|
||||||
fun findDependentResolvedNpmProject(src: Project, target: Project): NpmProjectPackage? {
|
|
||||||
// todo: proper finding using KotlinTargetComponent.findUsageContext
|
|
||||||
val resolvedTarget = getOrResolve(target)
|
|
||||||
val mainCompilations = resolvedTarget.npmProjectsByCompilation.entries.filter { it.key.name == KotlinCompilation.MAIN_COMPILATION_NAME }
|
|
||||||
|
|
||||||
return if (mainCompilations.isNotEmpty()) {
|
|
||||||
if (mainCompilations.size > 1) {
|
|
||||||
error(
|
|
||||||
"Cannot resolve project dependency $src -> $target." +
|
|
||||||
"Dependency to project with multiple js compilation not supported yet."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
mainCompilations.single().value
|
|
||||||
} else null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun chooseVersion(oldVersion: String?, newVersion: String): String =
|
|
||||||
oldVersion ?: newVersion // todo: real versions conflict resolution
|
|
||||||
}
|
|
||||||
+1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.targets.js.npm
|
|||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.NpmProjectPackage
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* 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.resolved
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
class KotlinNpmResolution(private val projects: Map<Project, KotlinProjectNpmResolution>) {
|
||||||
|
operator fun get(project: Project) = projects[project] ?: KotlinProjectNpmResolution.empty(project)
|
||||||
|
}
|
||||||
+19
-7
@@ -3,21 +3,33 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* 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
|
package org.jetbrains.kotlin.gradle.targets.js.npm.resolved
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
|
import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Info about NPM projects inside particular gradle [project].
|
* Info about NPM projects inside particular gradle [project].
|
||||||
*/
|
*/
|
||||||
class NpmProjects(
|
class KotlinProjectNpmResolution(
|
||||||
val project: Project,
|
val project: Project,
|
||||||
|
|
||||||
val npmProjects: List<NpmProjectPackage>,
|
val npmProjects: List<NpmProjectPackage>,
|
||||||
val npmProjectsByCompilation: Map<KotlinJsCompilation, NpmProjectPackage>,
|
|
||||||
val npmProjectsByNpmDependency: Map<NpmDependency, NpmProjectPackage>,
|
|
||||||
|
|
||||||
val taskRequirements: Map<RequiresNpmDependencies, Collection<RequiredKotlinJsDependency>>
|
val taskRequirements: Map<RequiresNpmDependencies, Collection<RequiredKotlinJsDependency>>
|
||||||
)
|
) {
|
||||||
|
val npmProjectsByCompilation: Map<KotlinJsCompilation, NpmProjectPackage> = npmProjects.associateBy { it.npmProject.compilation }
|
||||||
|
val npmProjectsByNpmDependency: Map<NpmDependency, NpmProjectPackage> =
|
||||||
|
mutableMapOf<NpmDependency, NpmProjectPackage>().also { result ->
|
||||||
|
npmProjects.forEach { npmPackage ->
|
||||||
|
npmPackage.npmDependencies.forEach { npmDependency ->
|
||||||
|
result[npmDependency] = npmPackage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun empty(project: Project) = KotlinProjectNpmResolution(project, listOf(), mapOf())
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-3
@@ -3,9 +3,13 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* 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
|
package org.jetbrains.kotlin.gradle.targets.js.npm.resolved
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmGradleDependencies
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.PackageJson
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [NpmProject] full package info
|
* [NpmProject] full package info
|
||||||
@@ -15,6 +19,5 @@ class NpmProjectPackage(
|
|||||||
val npmProject: NpmProject,
|
val npmProject: NpmProject,
|
||||||
val npmDependencies: Collection<NpmDependency>,
|
val npmDependencies: Collection<NpmDependency>,
|
||||||
val gradleDependencies: NpmGradleDependencies,
|
val gradleDependencies: NpmGradleDependencies,
|
||||||
val packageJson: PackageJson,
|
val packageJson: PackageJson
|
||||||
val hasNodeModulesDependentTasks: Boolean
|
|
||||||
)
|
)
|
||||||
+169
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* 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.resolver
|
||||||
|
|
||||||
|
import org.gradle.api.artifacts.Configuration
|
||||||
|
import org.gradle.api.artifacts.ResolvedArtifact
|
||||||
|
import org.gradle.api.artifacts.ResolvedDependency
|
||||||
|
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
||||||
|
import org.gradle.api.attributes.Usage
|
||||||
|
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.nodejs.nodeJs
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.NpmProjectPackage
|
||||||
|
|
||||||
|
internal class KotlinCompilationNpmResolver(
|
||||||
|
val projectResolver: KotlinProjectNpmResolver,
|
||||||
|
val compilation: KotlinJsCompilation
|
||||||
|
) {
|
||||||
|
val resolver = projectResolver.resolver
|
||||||
|
val target get() = compilation.target
|
||||||
|
val project get() = target.project
|
||||||
|
|
||||||
|
val aggregatedConfiguration: Configuration by lazy {
|
||||||
|
createAggregatedConfiguration()
|
||||||
|
}
|
||||||
|
|
||||||
|
val projectPackage by lazy {
|
||||||
|
createPackageJson(aggregatedConfiguration)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createAggregatedConfiguration(): Configuration {
|
||||||
|
val all = project.configurations.create("${compilation.name}Npm")
|
||||||
|
|
||||||
|
all.usesPlatformOf(target)
|
||||||
|
all.attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.consumerRuntimeUsage(target))
|
||||||
|
all.isVisible = false
|
||||||
|
all.isCanBeConsumed = false
|
||||||
|
all.isCanBeResolved = true
|
||||||
|
all.description = "NPM configuration for $compilation."
|
||||||
|
|
||||||
|
compilation.allKotlinSourceSets.forEach { sourceSet ->
|
||||||
|
sourceSet.relatedConfigurationNames.forEach { configurationName ->
|
||||||
|
val configuration = project.configurations.getByName(configurationName)
|
||||||
|
all.extendsFrom(configuration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createNpmToolsConfiguration()?.let { tools ->
|
||||||
|
all.extendsFrom(tools)
|
||||||
|
}
|
||||||
|
|
||||||
|
return all
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createNpmToolsConfiguration(): Configuration? {
|
||||||
|
val taskRequirements = projectResolver.requiredFromTasksByCompilation[compilation]
|
||||||
|
?.takeIf { it.isNotEmpty() } ?: return null
|
||||||
|
|
||||||
|
val toolsConfiguration = project.configurations.create("${compilation.name}NpmTools")
|
||||||
|
|
||||||
|
toolsConfiguration.isVisible = false
|
||||||
|
toolsConfiguration.isCanBeConsumed = false
|
||||||
|
toolsConfiguration.isCanBeResolved = true
|
||||||
|
toolsConfiguration.description = "NPM Tools configuration for $compilation."
|
||||||
|
|
||||||
|
taskRequirements.forEach { requirement ->
|
||||||
|
requirement.requiredNpmDependencies.forEach { requiredNpmDependency ->
|
||||||
|
toolsConfiguration.dependencies.add(requiredNpmDependency.createDependency(project))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return toolsConfiguration
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createPackageJson(configuration: Configuration): NpmProjectPackage {
|
||||||
|
val npmProject = compilation.npmProject
|
||||||
|
val name = npmProject.name
|
||||||
|
val packageJson = PackageJson(
|
||||||
|
name,
|
||||||
|
fixSemver(project.version.toString())
|
||||||
|
)
|
||||||
|
val npmDependencies = mutableSetOf<NpmDependency>()
|
||||||
|
val gradleDependencies = NpmGradleDependencies()
|
||||||
|
|
||||||
|
packageJson.main = npmProject.main
|
||||||
|
|
||||||
|
collectDependenciesFromConfiguration(configuration, gradleDependencies)
|
||||||
|
|
||||||
|
configuration.allDependencies.forEach { dependency ->
|
||||||
|
when (dependency) {
|
||||||
|
is NpmDependency -> npmDependencies.add(dependency)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
npmDependencies.forEach {
|
||||||
|
packageJson.dependencies[it.key] = chooseVersion(packageJson.dependencies[it.key], it.version)
|
||||||
|
}
|
||||||
|
|
||||||
|
gradleDependencies.externalModules.forEach {
|
||||||
|
packageJson.dependencies[it.name] = it.version
|
||||||
|
}
|
||||||
|
|
||||||
|
gradleDependencies.internalModules.forEach { target ->
|
||||||
|
val targetResolver = resolver.findDependentResolver(project, target)
|
||||||
|
if (targetResolver != null) {
|
||||||
|
val targetPackageJson = targetResolver.projectPackage.packageJson
|
||||||
|
packageJson.dependencies[targetPackageJson.name] = targetPackageJson.version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.nodeJs.packageJsonHandlers.forEach {
|
||||||
|
it(packageJson)
|
||||||
|
}
|
||||||
|
|
||||||
|
val npmPackage = NpmProjectPackage(
|
||||||
|
project,
|
||||||
|
npmProject,
|
||||||
|
npmDependencies,
|
||||||
|
gradleDependencies,
|
||||||
|
packageJson
|
||||||
|
)
|
||||||
|
npmPackage.packageJson.saveTo(npmProject.packageJsonFile)
|
||||||
|
|
||||||
|
return npmPackage
|
||||||
|
}
|
||||||
|
|
||||||
|
fun chooseVersion(oldVersion: String?, newVersion: String): String =
|
||||||
|
oldVersion ?: newVersion // todo: real versions conflict resolution
|
||||||
|
|
||||||
|
|
||||||
|
private fun collectDependenciesFromConfiguration(configuration: Configuration, result: NpmGradleDependencies) {
|
||||||
|
if (configuration.isCanBeResolved) {
|
||||||
|
configuration.resolvedConfiguration.firstLevelModuleDependencies.forEach {
|
||||||
|
visitDependency(it, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visitDependency(dependency: ResolvedDependency, result: NpmGradleDependencies) {
|
||||||
|
visitArtifacts(dependency, dependency.moduleArtifacts, result)
|
||||||
|
|
||||||
|
dependency.children.forEach {
|
||||||
|
visitDependency(it, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visitArtifacts(
|
||||||
|
dependency: ResolvedDependency,
|
||||||
|
artifacts: MutableSet<ResolvedArtifact>,
|
||||||
|
result: NpmGradleDependencies
|
||||||
|
) {
|
||||||
|
artifacts.forEach { artifact ->
|
||||||
|
val componentIdentifier = artifact.id.componentIdentifier
|
||||||
|
if (componentIdentifier is ProjectComponentIdentifier) {
|
||||||
|
val dependentProject = project.findProject(componentIdentifier.projectPath)
|
||||||
|
?: error("Cannot find project ${componentIdentifier.projectPath}")
|
||||||
|
|
||||||
|
result.internalModules.add(dependentProject)
|
||||||
|
} else {
|
||||||
|
resolver.gradleNodeModules.ensureImported(artifact, dependency, artifacts, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+160
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* 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.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.nodejs.NodeJsPlugin
|
||||||
|
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.resolved.KotlinNpmResolution
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinProjectNpmResolution
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.NpmProjectPackage
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates `package.json` file for [NpmProject] with npm or js dependencies and
|
||||||
|
* runs selected [NodeJsRootExtension.packageManager] to download and install all of it's dependencies.
|
||||||
|
*
|
||||||
|
* All [NpmDependency] for configurations related to kotlin/js will be added to `package.json`.
|
||||||
|
* For external gradle modules, fake npm packages will be created and added to `package.json`
|
||||||
|
* as path to directory.
|
||||||
|
*/
|
||||||
|
internal class KotlinNpmResolver private constructor(val rootProject: Project) {
|
||||||
|
companion object {
|
||||||
|
private sealed class State {
|
||||||
|
class Resolving(val resolver: KotlinNpmResolver) : State()
|
||||||
|
class Resolved(val resolved: KotlinNpmResolution) : State()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
private var initializedRootProject: Project? = null
|
||||||
|
private var state: State? = null
|
||||||
|
|
||||||
|
private fun getState(rootProject: Project): State {
|
||||||
|
check(rootProject == rootProject.rootProject)
|
||||||
|
|
||||||
|
if (initializedRootProject == null) {
|
||||||
|
synchronized(this) {
|
||||||
|
if (initializedRootProject == null) {
|
||||||
|
initializedRootProject = rootProject
|
||||||
|
state = State.Resolving(KotlinNpmResolver(rootProject))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check(initializedRootProject == rootProject)
|
||||||
|
|
||||||
|
return state!!
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setResolution(resolution: KotlinNpmResolution) {
|
||||||
|
state = State.Resolved(resolution)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getResolver(rootProject: Project): KotlinNpmResolver =
|
||||||
|
(getState(rootProject) as? State.Resolving ?: error("NPM Dependencies already resolved and installed"))
|
||||||
|
.resolver
|
||||||
|
|
||||||
|
fun resolveIfNeeded(project: Project): KotlinProjectNpmResolution {
|
||||||
|
val state = getState(project.rootProject)
|
||||||
|
val resolution = when (state) {
|
||||||
|
is State.Resolved -> state.resolved
|
||||||
|
is State.Resolving -> state.resolver.installAndClose()
|
||||||
|
}
|
||||||
|
return resolution[project]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAlreadyResolvedOrNull(project: Project): KotlinProjectNpmResolution? {
|
||||||
|
val state = getState(project.rootProject)
|
||||||
|
return when (state) {
|
||||||
|
is State.Resolved -> state.resolved[project]
|
||||||
|
is State.Resolving -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requireResolved(project: Project, reason: String = ""): KotlinProjectNpmResolution =
|
||||||
|
getAlreadyResolvedOrNull(project) ?: error("NPM dependencies should be resolved $reason")
|
||||||
|
|
||||||
|
fun checkRequiredDependencies(project: Project, target: RequiresNpmDependencies) {
|
||||||
|
val requestedTaskDependencies = requireResolved(
|
||||||
|
project,
|
||||||
|
"before $target execution"
|
||||||
|
).taskRequirements
|
||||||
|
val targetRequired = requestedTaskDependencies[target]?.toSet() ?: setOf()
|
||||||
|
|
||||||
|
target.requiredNpmDependencies.forEach {
|
||||||
|
check(it in targetRequired) {
|
||||||
|
"$it required by $target was not found resolved at the time of nodejs package manager call. " +
|
||||||
|
"This may be caused by changing $target configuration after npm dependencies resolution."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val gradleNodeModules = GradleNodeModulesCache(rootProject)
|
||||||
|
val projectResolvers = mutableMapOf<Project, KotlinProjectNpmResolver>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (rootProject.logger.isDebugEnabled) {
|
||||||
|
rootProject.logger.debug("KotlinNpmResolver initialization triggered at: ${Thread.currentThread().stackTrace.joinToString("\n")}")
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.allprojects.toList().forEach {
|
||||||
|
projectResolvers[it] = KotlinProjectNpmResolver(it, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun installAndClose(): KotlinNpmResolution {
|
||||||
|
if (rootProject.logger.isDebugEnabled) {
|
||||||
|
rootProject.logger.debug("KotlinNpmResolver installation triggered at: ${Thread.currentThread().stackTrace.joinToString("\n")}")
|
||||||
|
}
|
||||||
|
|
||||||
|
val nodeJs = NodeJsPlugin.apply(rootProject).root
|
||||||
|
val packageManager = nodeJs.packageManager
|
||||||
|
val allNpmPackages = projectResolvers.values.flatMap { it.byCompilation.values.map { it.projectPackage } }
|
||||||
|
|
||||||
|
removeOutdatedPackages(nodeJs, allNpmPackages)
|
||||||
|
gradleNodeModules.close()
|
||||||
|
|
||||||
|
if (allNpmPackages.any { it.npmDependencies.isNotEmpty() }) {
|
||||||
|
packageManager.resolveRootProject(rootProject, allNpmPackages)
|
||||||
|
} else if (projectResolvers.values.any { it.hasNodeModulesDependentTasks }) {
|
||||||
|
NpmSimpleLinker(rootProject).link(allNpmPackages)
|
||||||
|
}
|
||||||
|
|
||||||
|
val resolution = KotlinNpmResolution(projectResolvers.values.map { it.toResolved() }.associateBy { it.project })
|
||||||
|
setResolution(resolution)
|
||||||
|
return resolution
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeOutdatedPackages(nodeJs: NodeJsRootExtension, allNpmPackages: List<NpmProjectPackage>) {
|
||||||
|
val packages = allNpmPackages.mapTo(mutableSetOf()) { it.npmProject.name }
|
||||||
|
nodeJs.projectPackagesDir.listFiles()?.forEach {
|
||||||
|
if (it.name !in packages) {
|
||||||
|
it.deleteRecursively()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findDependentResolver(src: Project, target: Project): KotlinCompilationNpmResolver? {
|
||||||
|
// todo: proper finding using KotlinTargetComponent.findUsageContext
|
||||||
|
val targetResolver = getResolver(target.rootProject).projectResolvers[target] ?: return null
|
||||||
|
val mainCompilations =
|
||||||
|
targetResolver.byCompilation.entries.filter { it.key.name == KotlinCompilation.MAIN_COMPILATION_NAME }
|
||||||
|
|
||||||
|
return if (mainCompilations.isNotEmpty()) {
|
||||||
|
if (mainCompilations.size > 1) {
|
||||||
|
error(
|
||||||
|
"Cannot resolve project dependency $src -> $target." +
|
||||||
|
"Dependency to project with multiple js compilation not supported yet."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
mainCompilations.single().value
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
}
|
||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* 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.resolver
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtensionOrNull
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||||
|
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
|
||||||
|
|
||||||
|
internal class KotlinProjectNpmResolver(
|
||||||
|
val project: Project,
|
||||||
|
val resolver: KotlinNpmResolver
|
||||||
|
) {
|
||||||
|
val byCompilation = mutableMapOf<KotlinJsCompilation, KotlinCompilationNpmResolver>()
|
||||||
|
|
||||||
|
private val taskRequirements = mutableMapOf<RequiresNpmDependencies, Collection<RequiredKotlinJsDependency>>()
|
||||||
|
val requiredFromTasksByCompilation = mutableMapOf<KotlinJsCompilation, MutableList<RequiresNpmDependencies>>()
|
||||||
|
var hasNodeModulesDependentTasks = false
|
||||||
|
private set
|
||||||
|
|
||||||
|
init {
|
||||||
|
visit()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun visit() {
|
||||||
|
project.tasks.toList().forEach { task ->
|
||||||
|
if (task.enabled && task is RequiresNpmDependencies) {
|
||||||
|
addTaskRequirements(task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val kotlin = project.kotlinExtensionOrNull
|
||||||
|
|
||||||
|
if (kotlin != null) {
|
||||||
|
when (kotlin) {
|
||||||
|
is KotlinSingleTargetExtension -> visitTarget(kotlin.target)
|
||||||
|
is KotlinMultiplatformExtension -> kotlin.targets.forEach {
|
||||||
|
visitTarget(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visitTarget(target: KotlinTarget) {
|
||||||
|
if (target.platformType == KotlinPlatformType.js) {
|
||||||
|
target.compilations.toList().forEach { compilation ->
|
||||||
|
if (compilation is KotlinJsCompilation) {
|
||||||
|
// compilation may be KotlinWithJavaTarget for old Kotlin2JsPlugin
|
||||||
|
visitCompilation(compilation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visitCompilation(compilation: KotlinJsCompilation) {
|
||||||
|
byCompilation[compilation] = KotlinCompilationNpmResolver(this, compilation)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addTaskRequirements(task: RequiresNpmDependencies) {
|
||||||
|
if (!hasNodeModulesDependentTasks && task.nodeModulesRequired) {
|
||||||
|
hasNodeModulesDependentTasks = true
|
||||||
|
}
|
||||||
|
|
||||||
|
val requirements = task.requiredNpmDependencies.toList()
|
||||||
|
|
||||||
|
taskRequirements[task] = requirements
|
||||||
|
|
||||||
|
requiredFromTasksByCompilation
|
||||||
|
.getOrPut(task.compilation) { mutableListOf() }
|
||||||
|
.add(task)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toResolved() = KotlinProjectNpmResolution(
|
||||||
|
project,
|
||||||
|
byCompilation.values.map { it.projectPackage },
|
||||||
|
taskRequirements
|
||||||
|
)
|
||||||
|
}
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.tasks
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.tasks.InputFiles
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinNpmResolver
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
open class KotlinNpmInstallTask : DefaultTask() {
|
||||||
|
private val resolver: KotlinNpmResolver
|
||||||
|
get() = KotlinNpmResolver.getResolver(project)
|
||||||
|
|
||||||
|
init {
|
||||||
|
check(project == project.rootProject)
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:InputFiles
|
||||||
|
val packageJsonFiles: Collection<File>
|
||||||
|
get() = resolver.projectResolvers.values.flatMap { projectResolver ->
|
||||||
|
projectResolver.byCompilation.keys.map { compilation ->
|
||||||
|
compilation.npmProject.packageJsonFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun resolve() {
|
||||||
|
resolver.installAndClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val NAME = "kotlinNpmInstall"
|
||||||
|
}
|
||||||
|
}
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.tasks
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.artifacts.Configuration
|
||||||
|
import org.gradle.api.tasks.InputFiles
|
||||||
|
import org.gradle.api.tasks.Internal
|
||||||
|
import org.gradle.api.tasks.OutputFile
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinCompilationNpmResolver
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinNpmResolver
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class KotlinPackageJsonTask : DefaultTask() {
|
||||||
|
@Internal
|
||||||
|
lateinit var compilation: KotlinJsCompilation
|
||||||
|
|
||||||
|
private val compilationResolver: KotlinCompilationNpmResolver
|
||||||
|
get() = KotlinNpmResolver.getResolver(project.rootProject).projectResolvers[project]!!.byCompilation[compilation]!!
|
||||||
|
|
||||||
|
@get:InputFiles
|
||||||
|
val configuration: Configuration
|
||||||
|
get() = compilationResolver.aggregatedConfiguration
|
||||||
|
|
||||||
|
@get:OutputFile
|
||||||
|
val packageJson: File
|
||||||
|
get() = compilation.npmProject.packageJsonFile
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
fun resolve() {
|
||||||
|
compilationResolver.projectPackage
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -44,7 +44,7 @@ class KotlinBrowserJs(target: KotlinJsTarget) :
|
|||||||
project.createOrRegisterTask<KotlinWebpack>(disambiguateCamelCased("webpack")) {
|
project.createOrRegisterTask<KotlinWebpack>(disambiguateCamelCased("webpack")) {
|
||||||
val compileKotlinTask = compilation.compileKotlinTask
|
val compileKotlinTask = compilation.compileKotlinTask
|
||||||
it.dependsOn(
|
it.dependsOn(
|
||||||
target.project.nodeJs.root.npmResolveTask,
|
target.project.nodeJs.root.npmInstallTask,
|
||||||
compileKotlinTask
|
compileKotlinTask
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ class KotlinBrowserJs(target: KotlinJsTarget) :
|
|||||||
val run = project.createOrRegisterTask<KotlinWebpack>(disambiguateCamelCased("run")) {
|
val run = project.createOrRegisterTask<KotlinWebpack>(disambiguateCamelCased("run")) {
|
||||||
val compileKotlinTask = compilation.compileKotlinTask
|
val compileKotlinTask = compilation.compileKotlinTask
|
||||||
it.dependsOn(
|
it.dependsOn(
|
||||||
target.project.nodeJs.root.npmResolveTask,
|
target.project.nodeJs.root.npmInstallTask,
|
||||||
compileKotlinTask,
|
compileKotlinTask,
|
||||||
compilation.processResourcesTaskName
|
compilation.processResourcesTaskName
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -74,7 +74,7 @@ abstract class KotlinJsSubTarget(
|
|||||||
testJs.group = LifecycleBasePlugin.VERIFICATION_GROUP
|
testJs.group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||||
testJs.description = testTaskDescription
|
testJs.description = testTaskDescription
|
||||||
|
|
||||||
testJs.dependsOn(target.project.nodeJs.root.npmResolveTask, compileTask, nodeJs.nodeJsSetupTask)
|
testJs.dependsOn(target.project.nodeJs.root.npmInstallTask, compileTask, nodeJs.nodeJsSetupTask)
|
||||||
|
|
||||||
testJs.onlyIf {
|
testJs.onlyIf {
|
||||||
compileTask.outputFile.exists()
|
compileTask.outputFile.exists()
|
||||||
|
|||||||
+2
-2
@@ -39,7 +39,7 @@ class KotlinNodeJs(target: KotlinJsTarget) :
|
|||||||
runTask.description = "run compiled js in nodejs"
|
runTask.description = "run compiled js in nodejs"
|
||||||
|
|
||||||
val compileKotlinTask = compilation.compileKotlinTask
|
val compileKotlinTask = compilation.compileKotlinTask
|
||||||
runTask.dependsOn(target.project.nodeJs.root.npmResolveTask, compileKotlinTask)
|
runTask.dependsOn(target.project.nodeJs.root.npmInstallTask, compileKotlinTask)
|
||||||
|
|
||||||
runTask.args(compileKotlinTask.outputFile)
|
runTask.args(compileKotlinTask.outputFile)
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ class KotlinNodeJs(target: KotlinJsTarget) :
|
|||||||
runtimeOnly(kotlin("test-nodejs-runner"))
|
runtimeOnly(kotlin("test-nodejs-runner"))
|
||||||
}
|
}
|
||||||
|
|
||||||
target.project.nodeJs.root.npmResolveTask.doLast {
|
target.project.nodeJs.root.npmInstallTask.doLast {
|
||||||
runTaskHolder.configure { runTask ->
|
runTaskHolder.configure { runTask ->
|
||||||
runTask.args(
|
runTask.args(
|
||||||
"--require",
|
"--require",
|
||||||
|
|||||||
+2
-3
@@ -13,7 +13,7 @@ import org.gradle.util.ConfigureUtil
|
|||||||
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec
|
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolver
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinNpmResolver
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
|
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.RequiresNpmDependencies
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
|
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
|
||||||
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KotlinKarma
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.mocha.KotlinMocha
|
import org.jetbrains.kotlin.gradle.targets.js.testing.mocha.KotlinMocha
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.nodejs.KotlinNodeJsTestRunner
|
import org.jetbrains.kotlin.gradle.targets.js.testing.nodejs.KotlinNodeJsTestRunner
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinTest
|
import org.jetbrains.kotlin.gradle.tasks.KotlinTest
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
open class KotlinJsTest : KotlinTest(), RequiresNpmDependencies {
|
open class KotlinJsTest : KotlinTest(), RequiresNpmDependencies {
|
||||||
@get:Internal
|
@get:Internal
|
||||||
@@ -93,7 +92,7 @@ open class KotlinJsTest : KotlinTest(), RequiresNpmDependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun executeTests() {
|
override fun executeTests() {
|
||||||
NpmResolver.checkRequiredDependencies(project, this)
|
KotlinNpmResolver.checkRequiredDependencies(project, this)
|
||||||
super.executeTests()
|
super.executeTests()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -17,7 +17,7 @@ import org.gradle.process.internal.ExecHandleFactory
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.NpmPackageVersion
|
import org.jetbrains.kotlin.gradle.targets.js.NpmPackageVersion
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolver
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinNpmResolver
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies
|
import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
|
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
|
||||||
import org.jetbrains.kotlin.gradle.testing.internal.reportsDir
|
import org.jetbrains.kotlin.gradle.testing.internal.reportsDir
|
||||||
@@ -127,7 +127,7 @@ open class KotlinWebpack : DefaultTask(), RequiresNpmDependencies {
|
|||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun doExecute() {
|
fun doExecute() {
|
||||||
NpmResolver.checkRequiredDependencies(project, this)
|
KotlinNpmResolver.checkRequiredDependencies(project, this)
|
||||||
|
|
||||||
val runner = createRunner()
|
val runner = createRunner()
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn
|
|||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProjectPackage
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.NpmProjectPackage
|
||||||
|
|
||||||
object Yarn : NpmApi {
|
object Yarn : NpmApi {
|
||||||
private fun getDelegate(project: Project): NpmApi =
|
private fun getDelegate(project: Project): NpmApi =
|
||||||
@@ -20,6 +20,6 @@ object Yarn : NpmApi {
|
|||||||
override fun resolveProject(resolvedNpmProject: NpmProjectPackage) =
|
override fun resolveProject(resolvedNpmProject: NpmProjectPackage) =
|
||||||
getDelegate(resolvedNpmProject.project).resolveProject(resolvedNpmProject)
|
getDelegate(resolvedNpmProject.project).resolveProject(resolvedNpmProject)
|
||||||
|
|
||||||
override fun resolveRootProject(rootProject: Project, subProjects: MutableList<NpmProjectPackage>) =
|
override fun resolveRootProject(rootProject: Project, subProjects: Collection<NpmProjectPackage>) =
|
||||||
getDelegate(rootProject.project).resolveRootProject(rootProject, subProjects)
|
getDelegate(rootProject.project).resolveRootProject(rootProject, subProjects)
|
||||||
}
|
}
|
||||||
+2
-2
@@ -9,13 +9,13 @@ import com.google.gson.Gson
|
|||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.GradleNodeModule
|
import org.jetbrains.kotlin.gradle.targets.js.npm.GradleNodeModule
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProjectPackage
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.NpmProjectPackage
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.PackageJson
|
import org.jetbrains.kotlin.gradle.targets.js.npm.PackageJson
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class YarnImportedPackagesVersionResolver(
|
class YarnImportedPackagesVersionResolver(
|
||||||
private val rootProject: Project,
|
private val rootProject: Project,
|
||||||
private val npmProjects: MutableList<NpmProjectPackage>,
|
private val npmProjects: Collection<NpmProjectPackage>,
|
||||||
private val nodeJsWorldDir: File
|
private val nodeJsWorldDir: File
|
||||||
) {
|
) {
|
||||||
private val resolvedVersion = mutableMapOf<String, String>()
|
private val resolvedVersion = mutableMapOf<String, String>()
|
||||||
|
|||||||
+2
-2
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn
|
|||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProjectPackage
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.NpmProjectPackage
|
||||||
|
|
||||||
object YarnSimple : YarnBasics() {
|
object YarnSimple : YarnBasics() {
|
||||||
override fun resolveProject(resolvedNpmProject: NpmProjectPackage) {
|
override fun resolveProject(resolvedNpmProject: NpmProjectPackage) {
|
||||||
@@ -21,5 +21,5 @@ object YarnSimple : YarnBasics() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resolveRootProject(rootProject: Project, subProjects: MutableList<NpmProjectPackage>) = Unit
|
override fun resolveRootProject(rootProject: Project, subProjects: Collection<NpmProjectPackage>) = Unit
|
||||||
}
|
}
|
||||||
+4
-3
@@ -8,12 +8,13 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn
|
|||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.nodeJs
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.NpmProjectPackage
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
object YarnWorkspaces : YarnBasics() {
|
object YarnWorkspaces : YarnBasics() {
|
||||||
override fun resolveProject(resolvedNpmProject: NpmProjectPackage) = Unit
|
override fun resolveProject(resolvedNpmProject: NpmProjectPackage) = Unit
|
||||||
|
|
||||||
override fun resolveRootProject(rootProject: Project, subProjects: MutableList<NpmProjectPackage>) {
|
override fun resolveRootProject(rootProject: Project, subProjects: Collection<NpmProjectPackage>) {
|
||||||
check(rootProject == rootProject.rootProject)
|
check(rootProject == rootProject.rootProject)
|
||||||
setup(rootProject)
|
setup(rootProject)
|
||||||
resolveWorkspaces(rootProject, subProjects)
|
resolveWorkspaces(rootProject, subProjects)
|
||||||
@@ -21,7 +22,7 @@ object YarnWorkspaces : YarnBasics() {
|
|||||||
|
|
||||||
private fun resolveWorkspaces(
|
private fun resolveWorkspaces(
|
||||||
rootProject: Project,
|
rootProject: Project,
|
||||||
npmProjects: MutableList<NpmProjectPackage>
|
npmProjects: Collection<NpmProjectPackage>
|
||||||
) {
|
) {
|
||||||
val upToDateChecks = npmProjects.map {
|
val upToDateChecks = npmProjects.map {
|
||||||
YarnUpToDateCheck(it.npmProject)
|
YarnUpToDateCheck(it.npmProject)
|
||||||
@@ -43,7 +44,7 @@ object YarnWorkspaces : YarnBasics() {
|
|||||||
|
|
||||||
private fun saveRootProjectWorkspacesPackageJson(
|
private fun saveRootProjectWorkspacesPackageJson(
|
||||||
rootProject: Project,
|
rootProject: Project,
|
||||||
npmProjects: MutableList<NpmProjectPackage>,
|
npmProjects: Collection<NpmProjectPackage>,
|
||||||
nodeJsWorldDir: File
|
nodeJsWorldDir: File
|
||||||
) {
|
) {
|
||||||
val rootPackageJson = PackageJson(rootProject.name, rootProject.version.toString())
|
val rootPackageJson = PackageJson(rootProject.name, rootProject.version.toString())
|
||||||
|
|||||||
Reference in New Issue
Block a user