[Gradle, JS] Remove requireNodeModules
[Gradle, JS] Remove 4 major webpack [Gradle, JS] Remove webpack 4 related dependencies [Gradle, JS] How want to see npm dependency [JS IR] Object factory and remove forceResolve [Gradle, JS] Object factory to package json producer [Gradle, JS] Only npm dependencies as required [Gradle, JS] NodeJsRootPlugin applied once [Gradle, JS] NodeJsRootPlugin applied once #2 [Gradle, JS] Divide task providers from NodeJsRootExtension [Gradle, JS] Remove redundant [Gradle, JS] Fix #1 [Gradle, JS] Fix #2 [Gradle, JS] Fix #3 [Gradle, JS] Fix #4 [Gradle, JS] Fix #5 [Gradle, JS] Fix tests [Gradle, JS] No objectFactory [Gradle, JS] Remove archive compat and fs compat [Gradle, JS] Build service kotlin npm resolution manager [JS] Build servicify Build servicify Build servicify Fix internal Tasks requirements as build service ~ try to move from build service [JS] no nested [JS] Configuration resolver inside input files Revert "[JS] Configuration resolver inside input files" This reverts commit 48536e011a8a341e9cb62fbf8e03a09f2ba115ba. [JS] nested but only configuration [JS] packageJsonHandlers serializable [JS] packageJsonProducer as part of task inputs [JS] packageJsonProducer ~1 ~2 ~3 ~4 ~5 ~6 ~7 ~8 ~9 ~10 Remove comments [Gradle, JS] Remove comments [Gradle, JS] Fix internals and test [Gradle, JS] Input package json files for root package json [Gradle, JS] Kotlin npm install always tracked externally [Gradle, JS] Rename resolution items [Gradle, JS] Build service with new scheme
This commit is contained in:
committed by
Space Team
parent
7fa7118325
commit
b2f416dbbe
+1
-3
@@ -86,7 +86,6 @@ abstract class AbstractJsConfigurationCacheIT(protected val irBackend: Boolean)
|
|||||||
":packageJson",
|
":packageJson",
|
||||||
":publicPackageJson",
|
":publicPackageJson",
|
||||||
":rootPackageJson",
|
":rootPackageJson",
|
||||||
":kotlinNpmInstall",
|
|
||||||
":compileKotlinJs",
|
":compileKotlinJs",
|
||||||
":nodeTest",
|
":nodeTest",
|
||||||
) + if (irBackend) listOf(":compileProductionExecutableKotlinJs") else emptyList()
|
) + if (irBackend) listOf(":compileProductionExecutableKotlinJs") else emptyList()
|
||||||
@@ -109,7 +108,6 @@ abstract class AbstractJsConfigurationCacheIT(protected val irBackend: Boolean)
|
|||||||
":packageJson",
|
":packageJson",
|
||||||
":publicPackageJson",
|
":publicPackageJson",
|
||||||
":rootPackageJson",
|
":rootPackageJson",
|
||||||
":kotlinNpmInstall",
|
|
||||||
":compileKotlinJs",
|
":compileKotlinJs",
|
||||||
":nodeTest",
|
":nodeTest",
|
||||||
) + if (irBackend) listOf(":compileProductionExecutableKotlinJs") else emptyList()
|
) + if (irBackend) listOf(":compileProductionExecutableKotlinJs") else emptyList()
|
||||||
@@ -125,7 +123,7 @@ abstract class AbstractJsConfigurationCacheIT(protected val irBackend: Boolean)
|
|||||||
assertSimpleConfigurationCacheScenarioWorks(
|
assertSimpleConfigurationCacheScenarioWorks(
|
||||||
"assemble", "kotlinStoreYarnLock",
|
"assemble", "kotlinStoreYarnLock",
|
||||||
buildOptions = defaultBuildOptions,
|
buildOptions = defaultBuildOptions,
|
||||||
executedTaskNames = listOf(":kotlinNpmInstall")
|
executedTaskNames = listOf(":rootPackageJson")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -1575,6 +1575,7 @@ abstract class AbstractKotlin2JsGradlePluginIT(protected val irBackend: Boolean)
|
|||||||
project("kotlin-js-browser-project", gradleVersion) {
|
project("kotlin-js-browser-project", gradleVersion) {
|
||||||
buildGradleKts.modify { originalScript ->
|
buildGradleKts.modify { originalScript ->
|
||||||
buildString {
|
buildString {
|
||||||
|
append("import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNpmResolutionManager")
|
||||||
append(originalScript)
|
append(originalScript)
|
||||||
append(
|
append(
|
||||||
"""
|
"""
|
||||||
@@ -1583,7 +1584,7 @@ abstract class AbstractKotlin2JsGradlePluginIT(protected val irBackend: Boolean)
|
|||||||
| val nodejs = the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>()
|
| val nodejs = the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>()
|
||||||
| tasks.named<org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask>("kotlinNpmInstall") {
|
| tasks.named<org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask>("kotlinNpmInstall") {
|
||||||
| doFirst {
|
| doFirst {
|
||||||
| nodejs.npmResolutionManager.state =
|
| project.rootProject.kotlinNpmResolutionManager.get().state =
|
||||||
| org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager.ResolutionState.Error(GradleException("someSpecialException"))
|
| org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager.ResolutionState.Error(GradleException("someSpecialException"))
|
||||||
| }
|
| }
|
||||||
| }
|
| }
|
||||||
|
|||||||
-5
@@ -7,14 +7,9 @@ package org.jetbrains.kotlin.generators.gradle.targets.js
|
|||||||
|
|
||||||
val npmPackages = listOf(
|
val npmPackages = listOf(
|
||||||
NpmPackage("webpack"),
|
NpmPackage("webpack"),
|
||||||
NpmPackage("webpack", "4.46.0", "webpack4"),
|
|
||||||
NpmPackage("webpack-cli"),
|
NpmPackage("webpack-cli"),
|
||||||
NpmPackage("webpack-cli", "3.3.12", "webpackCli3"),
|
|
||||||
NpmPackage("webpack-bundle-analyzer"),
|
|
||||||
NpmPackage("webpack-dev-server"),
|
NpmPackage("webpack-dev-server"),
|
||||||
NpmPackage("webpack-dev-server", "3.11.2", "webpackDevServer3"),
|
|
||||||
NpmPackage("source-map-loader"),
|
NpmPackage("source-map-loader"),
|
||||||
NpmPackage("source-map-loader", "1.1.0", "sourceMapLoader1"),
|
|
||||||
NpmPackage("source-map-support"),
|
NpmPackage("source-map-support"),
|
||||||
NpmPackage("css-loader"),
|
NpmPackage("css-loader"),
|
||||||
NpmPackage("style-loader"),
|
NpmPackage("style-loader"),
|
||||||
|
|||||||
+1
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.internal
|
package org.jetbrains.kotlin.gradle.internal
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
abstract class ConfigurationPhaseAware<C : Any> {
|
abstract class ConfigurationPhaseAware<C : Any> {
|
||||||
|
|||||||
-13
@@ -456,19 +456,6 @@ internal class PropertiesProvider private constructor(private val project: Proje
|
|||||||
val publishJsCompilerAttribute: Boolean
|
val publishJsCompilerAttribute: Boolean
|
||||||
get() = this.booleanProperty("$jsCompilerProperty.publish.attribute") ?: true
|
get() = this.booleanProperty("$jsCompilerProperty.publish.attribute") ?: true
|
||||||
|
|
||||||
/**
|
|
||||||
* Use Webpack 4 for compatibility
|
|
||||||
*/
|
|
||||||
val webpackMajorVersion: WebpackMajorVersion
|
|
||||||
get() = this.property(WebpackMajorVersion.webpackMajorVersion)?.let { WebpackMajorVersion.byArgument(it) }
|
|
||||||
?.also { version ->
|
|
||||||
if (!WebpackMajorVersion.webpackVersionWarning && version != WebpackMajorVersion.DEFAULT) {
|
|
||||||
WebpackMajorVersion.webpackVersionWarning = true
|
|
||||||
project.logger.warn(WebpackMajorVersion.warningMessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?: WebpackMajorVersion.DEFAULT
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use Kotlin/JS backend compiler type
|
* Use Kotlin/JS backend compiler type
|
||||||
*/
|
*/
|
||||||
|
|||||||
+5
-5
@@ -106,7 +106,7 @@ class DefaultKotlinDependencyHandler(
|
|||||||
version: String,
|
version: String,
|
||||||
): NpmDependency =
|
): NpmDependency =
|
||||||
NpmDependency(
|
NpmDependency(
|
||||||
project = project,
|
objectFactory = project.objects,
|
||||||
name = name,
|
name = name,
|
||||||
version = version,
|
version = version,
|
||||||
)
|
)
|
||||||
@@ -134,7 +134,7 @@ class DefaultKotlinDependencyHandler(
|
|||||||
version: String
|
version: String
|
||||||
): NpmDependency =
|
): NpmDependency =
|
||||||
NpmDependency(
|
NpmDependency(
|
||||||
project = project,
|
objectFactory = project.objects,
|
||||||
name = name,
|
name = name,
|
||||||
version = version,
|
version = version,
|
||||||
scope = NpmDependency.Scope.DEV
|
scope = NpmDependency.Scope.DEV
|
||||||
@@ -161,7 +161,7 @@ class DefaultKotlinDependencyHandler(
|
|||||||
version: String,
|
version: String,
|
||||||
): NpmDependency =
|
): NpmDependency =
|
||||||
NpmDependency(
|
NpmDependency(
|
||||||
project = project,
|
objectFactory = project.objects,
|
||||||
name = name,
|
name = name,
|
||||||
version = version,
|
version = version,
|
||||||
scope = NpmDependency.Scope.OPTIONAL,
|
scope = NpmDependency.Scope.OPTIONAL,
|
||||||
@@ -190,7 +190,7 @@ class DefaultKotlinDependencyHandler(
|
|||||||
version: String
|
version: String
|
||||||
): NpmDependency =
|
): NpmDependency =
|
||||||
NpmDependency(
|
NpmDependency(
|
||||||
project = project,
|
objectFactory = project.objects,
|
||||||
name = name,
|
name = name,
|
||||||
version = version,
|
version = version,
|
||||||
scope = NpmDependency.Scope.PEER
|
scope = NpmDependency.Scope.PEER
|
||||||
@@ -202,7 +202,7 @@ class DefaultKotlinDependencyHandler(
|
|||||||
scope: NpmDependency.Scope,
|
scope: NpmDependency.Scope,
|
||||||
): NpmDependency =
|
): NpmDependency =
|
||||||
directoryNpmDependency(
|
directoryNpmDependency(
|
||||||
project = project,
|
objectFactory = project.objects,
|
||||||
name = name,
|
name = name,
|
||||||
directory = directory,
|
directory = directory,
|
||||||
scope = scope,
|
scope = scope,
|
||||||
|
|||||||
+3
-3
@@ -7,9 +7,9 @@ package org.jetbrains.kotlin.gradle.targets.js
|
|||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.artifacts.Dependency
|
import org.gradle.api.artifacts.Dependency
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency
|
import java.io.Serializable
|
||||||
|
|
||||||
data class KotlinGradleNpmPackage(val simpleModuleName: String) : RequiredKotlinJsDependency {
|
data class KotlinGradleNpmPackage(val simpleModuleName: String) : Serializable {
|
||||||
override fun createDependency(project: Project, scope: NpmDependency.Scope): Dependency =
|
fun createDependency(project: Project): Dependency =
|
||||||
project.dependencies.create("org.jetbrains.kotlin:kotlin-$simpleModuleName")
|
project.dependencies.create("org.jetbrains.kotlin:kotlin-$simpleModuleName")
|
||||||
}
|
}
|
||||||
+12
-1
@@ -16,9 +16,14 @@ import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator.Compa
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.LEGACY
|
import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.LEGACY
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.*
|
import org.jetbrains.kotlin.gradle.plugin.mpp.PRIMARY_SINGLE_COMPONENT_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBrowserDsl
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsNodeDsl
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsSubTargetContainerDsl
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsBinaryContainer
|
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsBinaryContainer
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
|
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolverPlugin
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.subtargets.KotlinBrowserJs
|
import org.jetbrains.kotlin.gradle.targets.js.subtargets.KotlinBrowserJs
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.subtargets.KotlinNodeJs
|
import org.jetbrains.kotlin.gradle.targets.js.subtargets.KotlinNodeJs
|
||||||
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
||||||
@@ -147,8 +152,13 @@ constructor(
|
|||||||
|
|
||||||
private val propertiesProvider = PropertiesProvider(project)
|
private val propertiesProvider = PropertiesProvider(project)
|
||||||
|
|
||||||
|
private val commonLazy by lazy {
|
||||||
|
NpmResolverPlugin.apply(project)
|
||||||
|
}
|
||||||
|
|
||||||
//Browser
|
//Browser
|
||||||
private val browserLazyDelegate = lazy {
|
private val browserLazyDelegate = lazy {
|
||||||
|
commonLazy
|
||||||
project.objects.newInstance(KotlinBrowserJs::class.java, this).also {
|
project.objects.newInstance(KotlinBrowserJs::class.java, this).also {
|
||||||
it.configure()
|
it.configure()
|
||||||
|
|
||||||
@@ -177,6 +187,7 @@ constructor(
|
|||||||
|
|
||||||
//node.js
|
//node.js
|
||||||
private val nodejsLazyDelegate = lazy {
|
private val nodejsLazyDelegate = lazy {
|
||||||
|
commonLazy
|
||||||
project.objects.newInstance(KotlinNodeJs::class.java, this).also {
|
project.objects.newInstance(KotlinNodeJs::class.java, this).also {
|
||||||
it.configure()
|
it.configure()
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.targets.js
|
package org.jetbrains.kotlin.gradle.targets.js
|
||||||
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.artifacts.Dependency
|
import org.gradle.api.artifacts.Dependency
|
||||||
|
import org.gradle.api.model.ObjectFactory
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency
|
||||||
|
|
||||||
data class NpmPackageVersion(val name: String, var version: String) : RequiredKotlinJsDependency {
|
data class NpmPackageVersion(val name: String, var version: String) : RequiredKotlinJsDependency {
|
||||||
override fun createDependency(project: Project, scope: NpmDependency.Scope): Dependency =
|
override fun createDependency(objectFactory: ObjectFactory, scope: NpmDependency.Scope): Dependency =
|
||||||
NpmDependency(project, name, version, scope)
|
NpmDependency(objectFactory, scope, name, version)
|
||||||
}
|
}
|
||||||
+5
-10
@@ -12,24 +12,19 @@ import java.io.Serializable
|
|||||||
*/
|
*/
|
||||||
// DO NOT MODIFY DIRECTLY! Use org.jetbrains.kotlin.generators.gradle.targets.js.MainKt
|
// DO NOT MODIFY DIRECTLY! Use org.jetbrains.kotlin.generators.gradle.targets.js.MainKt
|
||||||
class NpmVersions : Serializable {
|
class NpmVersions : Serializable {
|
||||||
val webpack4 = NpmPackageVersion("webpack", "4.46.0")
|
|
||||||
val webpackCli3 = NpmPackageVersion("webpack-cli", "3.3.12")
|
|
||||||
val webpackDevServer3 = NpmPackageVersion("webpack-dev-server", "3.11.2")
|
|
||||||
val sourceMapLoader1 = NpmPackageVersion("source-map-loader", "1.1.0")
|
|
||||||
val webpack = NpmPackageVersion("webpack", "5.74.0")
|
val webpack = NpmPackageVersion("webpack", "5.74.0")
|
||||||
val webpackCli = NpmPackageVersion("webpack-cli", "4.10.0")
|
val webpackCli = NpmPackageVersion("webpack-cli", "4.10.0")
|
||||||
val webpackBundleAnalyzer = NpmPackageVersion("webpack-bundle-analyzer", "4.5.0")
|
val webpackDevServer = NpmPackageVersion("webpack-dev-server", "4.11.1")
|
||||||
val webpackDevServer = NpmPackageVersion("webpack-dev-server", "4.9.3")
|
|
||||||
val sourceMapLoader = NpmPackageVersion("source-map-loader", "4.0.0")
|
val sourceMapLoader = NpmPackageVersion("source-map-loader", "4.0.0")
|
||||||
val sourceMapSupport = NpmPackageVersion("source-map-support", "0.5.21")
|
val sourceMapSupport = NpmPackageVersion("source-map-support", "0.5.21")
|
||||||
val cssLoader = NpmPackageVersion("css-loader", "6.7.1")
|
val cssLoader = NpmPackageVersion("css-loader", "6.7.1")
|
||||||
val styleLoader = NpmPackageVersion("style-loader", "3.3.1")
|
val styleLoader = NpmPackageVersion("style-loader", "3.3.1")
|
||||||
val sassLoader = NpmPackageVersion("sass-loader", "13.0.2")
|
val sassLoader = NpmPackageVersion("sass-loader", "13.1.0")
|
||||||
val sass = NpmPackageVersion("sass", "1.54.3")
|
val sass = NpmPackageVersion("sass", "1.55.0")
|
||||||
val toStringLoader = NpmPackageVersion("to-string-loader", "1.2.0")
|
val toStringLoader = NpmPackageVersion("to-string-loader", "1.2.0")
|
||||||
val miniCssExtractPlugin = NpmPackageVersion("mini-css-extract-plugin", "2.6.1")
|
val miniCssExtractPlugin = NpmPackageVersion("mini-css-extract-plugin", "2.6.1")
|
||||||
val mocha = NpmPackageVersion("mocha", "10.0.0")
|
val mocha = NpmPackageVersion("mocha", "10.0.0")
|
||||||
val karma = NpmPackageVersion("karma", "6.4.0")
|
val karma = NpmPackageVersion("karma", "6.4.1")
|
||||||
val karmaChromeLauncher = NpmPackageVersion("karma-chrome-launcher", "3.1.1")
|
val karmaChromeLauncher = NpmPackageVersion("karma-chrome-launcher", "3.1.1")
|
||||||
val karmaPhantomjsLauncher = NpmPackageVersion("karma-phantomjs-launcher", "1.0.4")
|
val karmaPhantomjsLauncher = NpmPackageVersion("karma-phantomjs-launcher", "1.0.4")
|
||||||
val karmaFirefoxLauncher = NpmPackageVersion("karma-firefox-launcher", "2.1.2")
|
val karmaFirefoxLauncher = NpmPackageVersion("karma-firefox-launcher", "2.1.2")
|
||||||
@@ -41,7 +36,7 @@ class NpmVersions : Serializable {
|
|||||||
val karmaCoverage = NpmPackageVersion("karma-coverage", "2.2.0")
|
val karmaCoverage = NpmPackageVersion("karma-coverage", "2.2.0")
|
||||||
val karmaSourcemapLoader = NpmPackageVersion("karma-sourcemap-loader", "0.3.8")
|
val karmaSourcemapLoader = NpmPackageVersion("karma-sourcemap-loader", "0.3.8")
|
||||||
val formatUtil = NpmPackageVersion("format-util", "1.0.5")
|
val formatUtil = NpmPackageVersion("format-util", "1.0.5")
|
||||||
val typescript = NpmPackageVersion("typescript", "4.7.4")
|
val typescript = NpmPackageVersion("typescript", "4.8.4")
|
||||||
|
|
||||||
val kotlinJsTestRunner = KotlinGradleNpmPackage("test-js-runner")
|
val kotlinJsTestRunner = KotlinGradleNpmPackage("test-js-runner")
|
||||||
}
|
}
|
||||||
+2
-1
@@ -7,9 +7,10 @@ package org.jetbrains.kotlin.gradle.targets.js
|
|||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.artifacts.Dependency
|
import org.gradle.api.artifacts.Dependency
|
||||||
|
import org.gradle.api.model.ObjectFactory
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
interface RequiredKotlinJsDependency : Serializable {
|
interface RequiredKotlinJsDependency : Serializable {
|
||||||
fun createDependency(project: Project, scope: NpmDependency.Scope = NpmDependency.Scope.DEV): Dependency
|
fun createDependency(objectFactory: ObjectFactory, scope: NpmDependency.Scope = NpmDependency.Scope.DEV): Dependency
|
||||||
}
|
}
|
||||||
+15
-38
@@ -13,7 +13,6 @@ import org.gradle.api.tasks.Copy
|
|||||||
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJsDce
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJsDce
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.distsDirectory
|
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.distsDirectory
|
||||||
@@ -23,14 +22,13 @@ import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalDceDsl
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBrowserDsl
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBrowserDsl
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KotlinKarma
|
import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KotlinKarma
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.WebpackDevtool
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.WebpackDevtool
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.WebpackMajorVersion.Companion.choose
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.dependsOn
|
import org.jetbrains.kotlin.gradle.tasks.dependsOn
|
||||||
import org.jetbrains.kotlin.gradle.utils.doNotTrackStateCompat
|
import org.jetbrains.kotlin.gradle.utils.doNotTrackStateCompat
|
||||||
import org.jetbrains.kotlin.gradle.utils.newFileProperty
|
import org.jetbrains.kotlin.gradle.utils.newFileProperty
|
||||||
@@ -42,15 +40,11 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) :
|
|||||||
KotlinJsIrSubTarget(target, "browser"),
|
KotlinJsIrSubTarget(target, "browser"),
|
||||||
KotlinJsBrowserDsl {
|
KotlinJsBrowserDsl {
|
||||||
|
|
||||||
private val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
private val nodeJs = project.rootProject.kotlinNodeJsExtension
|
||||||
|
|
||||||
private val webpackTaskConfigurations: MutableList<Action<KotlinWebpack>> = mutableListOf()
|
private val webpackTaskConfigurations: MutableList<Action<KotlinWebpack>> = mutableListOf()
|
||||||
private val runTaskConfigurations: MutableList<Action<KotlinWebpack>> = mutableListOf()
|
private val runTaskConfigurations: MutableList<Action<KotlinWebpack>> = mutableListOf()
|
||||||
|
|
||||||
private val propertiesProvider = PropertiesProvider(project)
|
|
||||||
private val webpackMajorVersion
|
|
||||||
get() = propertiesProvider.webpackMajorVersion
|
|
||||||
|
|
||||||
override val testTaskDescription: String
|
override val testTaskDescription: String
|
||||||
get() = "Run all ${target.name} tests inside browser using karma and webpack"
|
get() = "Run all ${target.name} tests inside browser using karma and webpack"
|
||||||
|
|
||||||
@@ -110,9 +104,6 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) :
|
|||||||
override fun configureRun(
|
override fun configureRun(
|
||||||
compilation: KotlinJsIrCompilation
|
compilation: KotlinJsIrCompilation
|
||||||
) {
|
) {
|
||||||
val project = compilation.target.project
|
|
||||||
val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
|
||||||
|
|
||||||
val commonRunTask = registerSubTargetTask<Task>(disambiguateCamelCased(RUN_TASK_NAME)) {}
|
val commonRunTask = registerSubTargetTask<Task>(disambiguateCamelCased(RUN_TASK_NAME)) {}
|
||||||
|
|
||||||
compilation.binaries
|
compilation.binaries
|
||||||
@@ -134,10 +125,7 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) :
|
|||||||
task.dependsOn(binary.linkSyncTask)
|
task.dependsOn(binary.linkSyncTask)
|
||||||
task.outputDirectory.convention(distsDirectory).finalizeValueOnRead()
|
task.outputDirectory.convention(distsDirectory).finalizeValueOnRead()
|
||||||
|
|
||||||
webpackMajorVersion.choose(
|
task.args.add(0, "serve")
|
||||||
{ task.args.add(0, "serve") },
|
|
||||||
{ task.bin = "webpack-dev-server/bin/webpack-dev-server.js" }
|
|
||||||
)()
|
|
||||||
task.description = "start ${mode.name.toLowerCaseAsciiOnly()} webpack dev server"
|
task.description = "start ${mode.name.toLowerCaseAsciiOnly()} webpack dev server"
|
||||||
|
|
||||||
val openValue = if (compilation.platformType == KotlinPlatformType.wasm) {
|
val openValue = if (compilation.platformType == KotlinPlatformType.wasm) {
|
||||||
@@ -156,29 +144,19 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) :
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
webpackMajorVersion.choose(
|
task.devServer = KotlinWebpackConfig.DevServer(
|
||||||
{
|
open = openValue,
|
||||||
task.devServer = KotlinWebpackConfig.DevServer(
|
static = mutableListOf(
|
||||||
open = openValue,
|
"./kotlin",
|
||||||
static = mutableListOf(
|
compilation.output.resourcesDir.canonicalPath
|
||||||
"./kotlin",
|
),
|
||||||
compilation.output.resourcesDir.canonicalPath,
|
client = KotlinWebpackConfig.DevServer.Client(
|
||||||
),
|
KotlinWebpackConfig.DevServer.Client.Overlay(
|
||||||
client = KotlinWebpackConfig.DevServer.Client(
|
errors = true,
|
||||||
KotlinWebpackConfig.DevServer.Client.Overlay(
|
warnings = false
|
||||||
errors = true,
|
|
||||||
warnings = false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
},
|
)
|
||||||
{
|
)
|
||||||
task.devServer = KotlinWebpackConfig.DevServer(
|
|
||||||
open = true,
|
|
||||||
contentBase = mutableListOf(compilation.output.resourcesDir.canonicalPath)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)()
|
|
||||||
|
|
||||||
|
|
||||||
task.doNotTrackStateCompat("Tracked by external webpack tool")
|
task.doNotTrackStateCompat("Tracked by external webpack tool")
|
||||||
@@ -205,7 +183,6 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) :
|
|||||||
compilation: KotlinJsIrCompilation
|
compilation: KotlinJsIrCompilation
|
||||||
) {
|
) {
|
||||||
val project = compilation.target.project
|
val project = compilation.target.project
|
||||||
val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
|
||||||
|
|
||||||
val processResourcesTask = target.project.tasks.named(compilation.processResourcesTaskName)
|
val processResourcesTask = target.project.tasks.named(compilation.processResourcesTaskName)
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -12,7 +12,9 @@ import org.gradle.api.plugins.ExtensionAware
|
|||||||
import org.gradle.api.tasks.Copy
|
import org.gradle.api.tasks.Copy
|
||||||
import org.gradle.api.tasks.TaskProvider
|
import org.gradle.api.tasks.TaskProvider
|
||||||
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetWithTests
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
|
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
|
||||||
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
|
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsPlatformTestRun
|
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsPlatformTestRun
|
||||||
@@ -20,7 +22,6 @@ import org.jetbrains.kotlin.gradle.targets.js.dsl.Distribution
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalDistributionDsl
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalDistributionDsl
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsSubTargetDsl
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsSubTargetDsl
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolverPlugin
|
|
||||||
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.testing.KotlinJsTest
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
||||||
import org.jetbrains.kotlin.gradle.tasks.dependsOn
|
import org.jetbrains.kotlin.gradle.tasks.dependsOn
|
||||||
@@ -52,8 +53,6 @@ abstract class KotlinJsIrSubTarget(
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun configure() {
|
internal fun configure() {
|
||||||
NpmResolverPlugin.apply(project)
|
|
||||||
|
|
||||||
target.compilations.all {
|
target.compilations.all {
|
||||||
val npmProject = it.npmProject
|
val npmProject = it.npmProject
|
||||||
it.kotlinOptions {
|
it.kotlinOptions {
|
||||||
|
|||||||
+2
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.gradle.targets.js.KotlinJsReportAggregatingTestRun
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.binaryen.BinaryenExec
|
import org.jetbrains.kotlin.gradle.targets.js.binaryen.BinaryenExec
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.*
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.*
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolverPlugin
|
||||||
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.typescript.TypeScriptValidationTask
|
import org.jetbrains.kotlin.gradle.targets.js.typescript.TypeScriptValidationTask
|
||||||
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
||||||
@@ -110,6 +111,7 @@ constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val commonLazy by lazy {
|
private val commonLazy by lazy {
|
||||||
|
NpmResolverPlugin.apply(project)
|
||||||
compilations.all { compilation ->
|
compilations.all { compilation ->
|
||||||
compilation.binaries
|
compilation.binaries
|
||||||
.withType(JsIrBinary::class.java)
|
.withType(JsIrBinary::class.java)
|
||||||
|
|||||||
+6
-5
@@ -9,7 +9,7 @@ import org.gradle.api.Action
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsNodeDsl
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsNodeDsl
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExec
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExec
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinWasmNode
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinWasmNode
|
||||||
import org.jetbrains.kotlin.gradle.tasks.dependsOn
|
import org.jetbrains.kotlin.gradle.tasks.dependsOn
|
||||||
@@ -21,7 +21,8 @@ abstract class KotlinNodeJsIr @Inject constructor(target: KotlinJsIrTarget) :
|
|||||||
KotlinJsIrSubTargetBase(target, "node"),
|
KotlinJsIrSubTargetBase(target, "node"),
|
||||||
KotlinJsNodeDsl {
|
KotlinJsNodeDsl {
|
||||||
|
|
||||||
private val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
private val nodeJs = project.rootProject.kotlinNodeJsExtension
|
||||||
|
private val nodeJsTaskProviders = project.rootProject.kotlinNodeJsExtension
|
||||||
|
|
||||||
override val testTaskDescription: String
|
override val testTaskDescription: String
|
||||||
get() = "Run all ${target.name} tests inside nodejs using the builtin test framework"
|
get() = "Run all ${target.name} tests inside nodejs using the builtin test framework"
|
||||||
@@ -51,9 +52,9 @@ abstract class KotlinNodeJsIr @Inject constructor(target: KotlinJsIrTarget) :
|
|||||||
|
|
||||||
override fun configureTestDependencies(test: KotlinJsTest) {
|
override fun configureTestDependencies(test: KotlinJsTest) {
|
||||||
test.dependsOn(
|
test.dependsOn(
|
||||||
nodeJs.npmInstallTaskProvider,
|
nodeJsTaskProviders.npmInstallTaskProvider,
|
||||||
nodeJs.storeYarnLockTaskProvider,
|
nodeJsTaskProviders.storeYarnLockTaskProvider,
|
||||||
nodeJs.nodeJsSetupTaskProvider
|
nodeJsTaskProviders.nodeJsSetupTaskProvider
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -1,10 +1,12 @@
|
|||||||
package org.jetbrains.kotlin.gradle.targets.js.nodejs
|
package org.jetbrains.kotlin.gradle.targets.js.nodejs
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
|
||||||
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
|
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
data class NodeJsEnv(
|
data class NodeJsEnv(
|
||||||
val cleanableStore: CleanableStore,
|
val cleanableStore: CleanableStore,
|
||||||
|
val rootPackageDir: File,
|
||||||
val nodeDir: File,
|
val nodeDir: File,
|
||||||
val nodeBinDir: File,
|
val nodeBinDir: File,
|
||||||
val nodeExecutable: String,
|
val nodeExecutable: String,
|
||||||
@@ -12,7 +14,9 @@ data class NodeJsEnv(
|
|||||||
val platformName: String,
|
val platformName: String,
|
||||||
val architectureName: String,
|
val architectureName: String,
|
||||||
val ivyDependency: String,
|
val ivyDependency: String,
|
||||||
val downloadBaseUrl: String
|
val downloadBaseUrl: String,
|
||||||
|
|
||||||
|
val packageManager: NpmApi,
|
||||||
) {
|
) {
|
||||||
val isWindows: Boolean
|
val isWindows: Boolean
|
||||||
get() = platformName == "win"
|
get() = platformName == "win"
|
||||||
|
|||||||
+6
-7
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
|||||||
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.addWasmExperimentalArguments
|
import org.jetbrains.kotlin.gradle.targets.js.addWasmExperimentalArguments
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
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.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
@@ -48,10 +49,6 @@ constructor(
|
|||||||
@NormalizeLineEndings
|
@NormalizeLineEndings
|
||||||
val inputFileProperty: RegularFileProperty = project.newFileProperty()
|
val inputFileProperty: RegularFileProperty = project.newFileProperty()
|
||||||
|
|
||||||
@get:Internal
|
|
||||||
override val nodeModulesRequired: Boolean
|
|
||||||
get() = true
|
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
override val requiredNpmDependencies: Set<RequiredKotlinJsDependency> by lazy {
|
override val requiredNpmDependencies: Set<RequiredKotlinJsDependency> by lazy {
|
||||||
mutableSetOf<RequiredKotlinJsDependency>().also {
|
mutableSetOf<RequiredKotlinJsDependency>().also {
|
||||||
@@ -92,7 +89,9 @@ constructor(
|
|||||||
): TaskProvider<NodeJsExec> {
|
): TaskProvider<NodeJsExec> {
|
||||||
val target = compilation.target
|
val target = compilation.target
|
||||||
val project = target.project
|
val project = target.project
|
||||||
val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
NodeJsRootPlugin.apply(project.rootProject)
|
||||||
|
val nodeJs = project.rootProject.kotlinNodeJsExtension
|
||||||
|
val nodeJsTaskProviders = project.rootProject.kotlinNodeJsExtension
|
||||||
val npmProject = compilation.npmProject
|
val npmProject = compilation.npmProject
|
||||||
|
|
||||||
return project.registerTask(
|
return project.registerTask(
|
||||||
@@ -103,8 +102,8 @@ constructor(
|
|||||||
it.executable = nodeJs.requireConfigured().nodeExecutable
|
it.executable = nodeJs.requireConfigured().nodeExecutable
|
||||||
it.workingDir = npmProject.dir
|
it.workingDir = npmProject.dir
|
||||||
it.dependsOn(
|
it.dependsOn(
|
||||||
nodeJs.npmInstallTaskProvider,
|
nodeJsTaskProviders.npmInstallTaskProvider,
|
||||||
nodeJs.storeYarnLockTaskProvider,
|
nodeJsTaskProviders.storeYarnLockTaskProvider,
|
||||||
)
|
)
|
||||||
it.dependsOn(compilation.compileKotlinTaskProvider)
|
it.dependsOn(compilation.compileKotlinTaskProvider)
|
||||||
if (compilation.platformType == KotlinPlatformType.wasm) {
|
if (compilation.platformType == KotlinPlatformType.wasm) {
|
||||||
|
|||||||
+49
-82
@@ -12,29 +12,45 @@ import org.jetbrains.kotlin.gradle.internal.ConfigurationPhaseAware
|
|||||||
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
|
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
|
||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.NpmVersions
|
import org.jetbrains.kotlin.gradle.targets.js.NpmVersions
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager
|
|
||||||
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.resolver.KotlinRootNpmResolver
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.PACKAGE_JSON_UMBRELLA_TASK_NAME
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.PACKAGE_JSON_UMBRELLA_TASK_NAME
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmCachesSetup
|
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmCachesSetup
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask
|
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.RootPackageJsonTask
|
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.RootPackageJsonTask
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.Yarn
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.Yarn
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask.Companion.RESTORE_YARN_LOCK_NAME
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockCopyTask.Companion.STORE_YARN_LOCK_NAME
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
|
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.Serializable
|
|
||||||
|
|
||||||
open class NodeJsRootExtension(@Transient val rootProject: Project) : ConfigurationPhaseAware<NodeJsEnv>(), Serializable {
|
open class NodeJsRootExtension(
|
||||||
|
val project: Project
|
||||||
|
) : ConfigurationPhaseAware<NodeJsEnv>() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
check(rootProject.rootProject == rootProject)
|
check(project.rootProject == project)
|
||||||
|
|
||||||
|
val projectProperties = PropertiesProvider(project)
|
||||||
|
|
||||||
|
if (projectProperties.errorJsGenerateExternals != null) {
|
||||||
|
project.logger.warn(
|
||||||
|
"""
|
||||||
|
|
|
||||||
|
|==========
|
||||||
|
|Please note, Dukat integration in Gradle plugin does not work now, it was removed.
|
||||||
|
|We rethink how we can integrate properly.
|
||||||
|
|==========
|
||||||
|
|
|
||||||
|
""".trimMargin()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val logger = rootProject.logger
|
val rootProjectDir
|
||||||
|
get() = project.projectDir
|
||||||
|
|
||||||
private val gradleHome = rootProject.gradle.gradleUserHomeDir.also {
|
private val gradleHome = project.gradle.gradleUserHomeDir.also {
|
||||||
logger.kotlinInfo("Storing cached files in $it")
|
project.logger.kotlinInfo("Storing cached files in $it")
|
||||||
}
|
}
|
||||||
|
|
||||||
var installationDir by Property(gradleHome.resolve("nodejs"))
|
var installationDir by Property(gradleHome.resolve("nodejs"))
|
||||||
@@ -52,70 +68,12 @@ open class NodeJsRootExtension(@Transient val rootProject: Project) : Configurat
|
|||||||
|
|
||||||
var packageManager: NpmApi by Property(Yarn())
|
var packageManager: NpmApi by Property(Yarn())
|
||||||
|
|
||||||
@Transient
|
val taskRequirements: TasksRequirements
|
||||||
private val projectProperties = PropertiesProvider(rootProject)
|
get() = resolver.tasksRequirements
|
||||||
|
|
||||||
private val errorGenerateExternals = run {
|
lateinit var resolver: KotlinRootNpmResolver
|
||||||
if (projectProperties.errorJsGenerateExternals != null) {
|
|
||||||
logger.warn(
|
|
||||||
"""
|
|
||||||
|
|
|
||||||
|==========
|
|
||||||
|Please note, Dukat integration in Gradle plugin does not work now, it was removed.
|
|
||||||
|We rethink how we can integrate properly.
|
|
||||||
|==========
|
|
||||||
|
|
|
||||||
""".trimMargin()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val taskRequirements: TasksRequirements = TasksRequirements()
|
val rootPackageDir: File = project.buildDir.resolve("js")
|
||||||
|
|
||||||
val nodeJsSetupTaskProvider: TaskProvider<out NodeJsSetupTask>
|
|
||||||
get() = rootProject.tasks.withType(NodeJsSetupTask::class.java).named(NodeJsSetupTask.NAME)
|
|
||||||
|
|
||||||
@Suppress(
|
|
||||||
"UNNECESSARY_SAFE_CALL",
|
|
||||||
"SAFE_CALL_WILL_CHANGE_NULLABILITY"
|
|
||||||
) // TODO: investigate this warning; fixing it breaks integration tests.
|
|
||||||
val npmInstallTaskProvider: TaskProvider<out KotlinNpmInstallTask>?
|
|
||||||
get() = rootProject?.tasks?.withType(KotlinNpmInstallTask::class.java)?.named(KotlinNpmInstallTask.NAME)
|
|
||||||
|
|
||||||
val packageJsonUmbrellaTaskProvider: TaskProvider<Task>
|
|
||||||
get() = rootProject.tasks.named(PACKAGE_JSON_UMBRELLA_TASK_NAME)
|
|
||||||
|
|
||||||
@Suppress(
|
|
||||||
"UNNECESSARY_SAFE_CALL",
|
|
||||||
"SAFE_CALL_WILL_CHANGE_NULLABILITY"
|
|
||||||
) // TODO: investigate this warning; fixing it breaks integration tests.
|
|
||||||
val rootPackageJsonTaskProvider: TaskProvider<RootPackageJsonTask>?
|
|
||||||
get() = rootProject?.tasks?.withType(RootPackageJsonTask::class.java)?.named(RootPackageJsonTask.NAME)
|
|
||||||
|
|
||||||
@Suppress(
|
|
||||||
"UNNECESSARY_SAFE_CALL",
|
|
||||||
"SAFE_CALL_WILL_CHANGE_NULLABILITY"
|
|
||||||
) // TODO: investigate this warning; fixing it breaks integration tests.
|
|
||||||
val npmCachesSetupTaskProvider: TaskProvider<out KotlinNpmCachesSetup>?
|
|
||||||
get() = rootProject?.tasks?.withType(KotlinNpmCachesSetup::class.java)?.named(KotlinNpmCachesSetup.NAME)
|
|
||||||
|
|
||||||
@Suppress(
|
|
||||||
"UNNECESSARY_SAFE_CALL",
|
|
||||||
"SAFE_CALL_WILL_CHANGE_NULLABILITY"
|
|
||||||
) // TODO: investigate this warning; fixing it breaks integration tests.
|
|
||||||
val storeYarnLockTaskProvider: TaskProvider<out YarnLockCopyTask>?
|
|
||||||
get() = rootProject?.tasks?.withType(YarnLockCopyTask::class.java)?.named(STORE_YARN_LOCK_NAME)
|
|
||||||
|
|
||||||
@Suppress(
|
|
||||||
"UNNECESSARY_SAFE_CALL",
|
|
||||||
"SAFE_CALL_WILL_CHANGE_NULLABILITY"
|
|
||||||
) // TODO: investigate this warning; fixing it breaks integration tests.
|
|
||||||
val restoreYarnLockTaskProvider: TaskProvider<out YarnLockCopyTask>?
|
|
||||||
get() = rootProject?.tasks?.withType(YarnLockCopyTask::class.java)?.named(RESTORE_YARN_LOCK_NAME)
|
|
||||||
|
|
||||||
val rootPackageDir: File by lazy {
|
|
||||||
rootProject.buildDir.resolve("js")
|
|
||||||
}
|
|
||||||
|
|
||||||
val projectPackagesDir: File
|
val projectPackagesDir: File
|
||||||
get() = rootPackageDir.resolve("packages")
|
get() = rootPackageDir.resolve("packages")
|
||||||
@@ -123,6 +81,8 @@ open class NodeJsRootExtension(@Transient val rootProject: Project) : Configurat
|
|||||||
val nodeModulesGradleCacheDir: File
|
val nodeModulesGradleCacheDir: File
|
||||||
get() = rootPackageDir.resolve("packages_imported")
|
get() = rootPackageDir.resolve("packages_imported")
|
||||||
|
|
||||||
|
val versions = NpmVersions()
|
||||||
|
|
||||||
override fun finalizeConfiguration(): NodeJsEnv {
|
override fun finalizeConfiguration(): NodeJsEnv {
|
||||||
val platformHelper = PlatformHelper
|
val platformHelper = PlatformHelper
|
||||||
val platform = platformHelper.osName
|
val platform = platformHelper.osName
|
||||||
@@ -146,28 +106,35 @@ open class NodeJsRootExtension(@Transient val rootProject: Project) : Configurat
|
|||||||
|
|
||||||
return NodeJsEnv(
|
return NodeJsEnv(
|
||||||
cleanableStore = cleanableStore,
|
cleanableStore = cleanableStore,
|
||||||
|
rootPackageDir = rootPackageDir,
|
||||||
nodeDir = nodeDir,
|
nodeDir = nodeDir,
|
||||||
nodeBinDir = nodeBinDir,
|
nodeBinDir = nodeBinDir,
|
||||||
nodeExecutable = getExecutable("node", nodeCommand, "exe"),
|
nodeExecutable = getExecutable("node", nodeCommand, "exe"),
|
||||||
platformName = platform,
|
platformName = platform,
|
||||||
architectureName = architecture,
|
architectureName = architecture,
|
||||||
ivyDependency = getIvyDependency(),
|
ivyDependency = getIvyDependency(),
|
||||||
downloadBaseUrl = nodeDownloadBaseUrl
|
downloadBaseUrl = nodeDownloadBaseUrl,
|
||||||
|
packageManager = packageManager
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun executeSetup() {
|
val nodeJsSetupTaskProvider: TaskProvider<out NodeJsSetupTask>
|
||||||
if (download) {
|
get() = project.tasks.withType(NodeJsSetupTask::class.java).named(NodeJsSetupTask.NAME)
|
||||||
val nodeJsSetupTask = nodeJsSetupTaskProvider.get()
|
|
||||||
nodeJsSetupTask.actions.forEach {
|
|
||||||
it.execute(nodeJsSetupTask)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val versions = NpmVersions()
|
val npmInstallTaskProvider: TaskProvider<out KotlinNpmInstallTask>
|
||||||
|
get() = project.tasks.withType(KotlinNpmInstallTask::class.java).named(KotlinNpmInstallTask.NAME)
|
||||||
|
|
||||||
val npmResolutionManager = KotlinNpmResolutionManager(this)
|
val rootPackageJsonTaskProvider: TaskProvider<RootPackageJsonTask>
|
||||||
|
get() = project.tasks.withType(RootPackageJsonTask::class.java).named(RootPackageJsonTask.NAME)
|
||||||
|
|
||||||
|
val packageJsonUmbrellaTaskProvider: TaskProvider<Task>
|
||||||
|
get() = project.tasks.named(PACKAGE_JSON_UMBRELLA_TASK_NAME)
|
||||||
|
|
||||||
|
val npmCachesSetupTaskProvider: TaskProvider<out KotlinNpmCachesSetup>
|
||||||
|
get() = project.tasks.withType(KotlinNpmCachesSetup::class.java).named(KotlinNpmCachesSetup.NAME)
|
||||||
|
|
||||||
|
val storeYarnLockTaskProvider: TaskProvider<out YarnLockCopyTask>
|
||||||
|
get() = project.tasks.withType(YarnLockCopyTask::class.java).named(YarnLockCopyTask.STORE_YARN_LOCK_NAME)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val EXTENSION_NAME: String = "kotlinNodeJs"
|
const val EXTENSION_NAME: String = "kotlinNodeJs"
|
||||||
|
|||||||
+105
-14
@@ -9,18 +9,25 @@ import org.gradle.api.Plugin
|
|||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.Task
|
import org.gradle.api.Task
|
||||||
import org.gradle.api.plugins.BasePlugin
|
import org.gradle.api.plugins.BasePlugin
|
||||||
import org.jetbrains.kotlin.gradle.utils.markResolvable
|
import org.gradle.api.provider.Provider
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector
|
import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension.Companion.EXTENSION_NAME
|
import org.jetbrains.kotlin.gradle.targets.js.npm.CompositeNodeModulesCache
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.GradleNodeModulesCache
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.PACKAGE_JSON_UMBRELLA_TASK_NAME
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.PACKAGE_JSON_UMBRELLA_TASK_NAME
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmCachesSetup
|
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmCachesSetup
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin
|
||||||
import org.jetbrains.kotlin.gradle.tasks.CleanDataTask
|
import org.jetbrains.kotlin.gradle.tasks.CleanDataTask
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.castIsolatedKotlinPluginClassLoaderAware
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.doNotTrackStateCompat
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.markResolvable
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.providerWithLazyConvention
|
||||||
|
|
||||||
open class NodeJsRootPlugin : Plugin<Project> {
|
open class NodeJsRootPlugin : Plugin<Project> {
|
||||||
override fun apply(project: Project): Unit = project.run {
|
override fun apply(project: Project) {
|
||||||
MultiplePluginDeclarationDetector.detect(project)
|
MultiplePluginDeclarationDetector.detect(project)
|
||||||
|
|
||||||
project.plugins.apply(BasePlugin::class.java)
|
project.plugins.apply(BasePlugin::class.java)
|
||||||
@@ -29,35 +36,93 @@ open class NodeJsRootPlugin : Plugin<Project> {
|
|||||||
"NodeJsRootPlugin can be applied only to root project"
|
"NodeJsRootPlugin can be applied only to root project"
|
||||||
}
|
}
|
||||||
|
|
||||||
val settings = this.extensions.create(EXTENSION_NAME, NodeJsRootExtension::class.java, this)
|
val nodeJs = project.extensions.create(
|
||||||
|
NodeJsRootExtension.EXTENSION_NAME,
|
||||||
|
NodeJsRootExtension::class.java,
|
||||||
|
project
|
||||||
|
)
|
||||||
|
|
||||||
val setupTask = registerTask<NodeJsSetupTask>(NodeJsSetupTask.NAME) {
|
val setupTask = project.registerTask<NodeJsSetupTask>(NodeJsSetupTask.NAME) {
|
||||||
it.group = TASKS_GROUP_NAME
|
it.group = TASKS_GROUP_NAME
|
||||||
it.description = "Download and install a local node/npm version"
|
it.description = "Download and install a local node/npm version"
|
||||||
it.configuration = provider {
|
it.configuration = project.provider {
|
||||||
this.project.configurations.detachedConfiguration(this.project.dependencies.create(it.ivyDependency))
|
project.configurations.detachedConfiguration(project.dependencies.create(it.ivyDependency))
|
||||||
.markResolvable()
|
.markResolvable()
|
||||||
.also { conf -> conf.isTransitive = false }
|
.also { conf -> conf.isTransitive = false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val setupFileHasherTask = registerTask<KotlinNpmCachesSetup>(KotlinNpmCachesSetup.NAME) {
|
val gradleNodeModulesProvider: Provider<GradleNodeModulesCache> = GradleNodeModulesCache.registerIfAbsent(
|
||||||
|
project,
|
||||||
|
project.projectDir,
|
||||||
|
nodeJs.nodeModulesGradleCacheDir
|
||||||
|
)
|
||||||
|
|
||||||
|
val compositeNodeModulesProvider: Provider<CompositeNodeModulesCache> = CompositeNodeModulesCache.registerIfAbsent(
|
||||||
|
project,
|
||||||
|
project.projectDir,
|
||||||
|
nodeJs.nodeModulesGradleCacheDir
|
||||||
|
)
|
||||||
|
|
||||||
|
val setupFileHasherTask = project.registerTask<KotlinNpmCachesSetup>(KotlinNpmCachesSetup.NAME) {
|
||||||
it.description = "Setup file hasher for caches"
|
it.description = "Setup file hasher for caches"
|
||||||
|
|
||||||
|
it.gradleNodeModules.set(gradleNodeModulesProvider)
|
||||||
|
it.compositeNodeModules.set(compositeNodeModulesProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
registerTask<KotlinNpmInstallTask>(KotlinNpmInstallTask.NAME) {
|
val npmInstall = project.registerTask<KotlinNpmInstallTask>(KotlinNpmInstallTask.NAME) {
|
||||||
it.dependsOn(setupTask)
|
it.dependsOn(setupTask)
|
||||||
it.dependsOn(setupFileHasherTask)
|
it.dependsOn(setupFileHasherTask)
|
||||||
it.group = TASKS_GROUP_NAME
|
it.group = TASKS_GROUP_NAME
|
||||||
it.description = "Find, download and link NPM dependencies and projects"
|
it.description = "Find, download and link NPM dependencies and projects"
|
||||||
|
|
||||||
|
it.onlyIf { task ->
|
||||||
|
task as KotlinNpmInstallTask
|
||||||
|
task.preparedFiles.all { file ->
|
||||||
|
file.exists()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it.doNotTrackStateCompat("NPM package manager track by its own")
|
||||||
}
|
}
|
||||||
|
|
||||||
registerTask<Task>(PACKAGE_JSON_UMBRELLA_TASK_NAME)
|
project.registerTask<Task>(PACKAGE_JSON_UMBRELLA_TASK_NAME)
|
||||||
|
|
||||||
YarnPlugin.apply(project)
|
YarnPlugin.apply(project)
|
||||||
|
|
||||||
tasks.register("node" + CleanDataTask.NAME_SUFFIX, CleanDataTask::class.java) {
|
nodeJs.resolver = KotlinRootNpmResolver(
|
||||||
it.cleanableStoreProvider = provider { settings.requireConfigured().cleanableStore }
|
project.name,
|
||||||
|
project.version.toString(),
|
||||||
|
TasksRequirements(),
|
||||||
|
nodeJs.versions,
|
||||||
|
nodeJs.projectPackagesDir,
|
||||||
|
nodeJs.rootProjectDir,
|
||||||
|
)
|
||||||
|
|
||||||
|
val objectFactory = project.objects
|
||||||
|
|
||||||
|
val npmResolutionManager = KotlinNpmResolutionManager.registerIfAbsent(
|
||||||
|
project,
|
||||||
|
objectFactory.providerWithLazyConvention {
|
||||||
|
nodeJs.resolver.close()
|
||||||
|
},
|
||||||
|
objectFactory.providerWithLazyConvention {
|
||||||
|
nodeJs.resolver.compilations.associate { compilation ->
|
||||||
|
"${compilation.project.path}:${compilation.disambiguatedName}" to compilation.packageJsonHandlers
|
||||||
|
}
|
||||||
|
},
|
||||||
|
gradleNodeModulesProvider,
|
||||||
|
compositeNodeModulesProvider
|
||||||
|
)
|
||||||
|
|
||||||
|
npmInstall.configure {
|
||||||
|
it.npmResolutionManager.set(npmResolutionManager)
|
||||||
|
it.npmResolutionManager.disallowChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.register("node" + CleanDataTask.NAME_SUFFIX, CleanDataTask::class.java) {
|
||||||
|
it.cleanableStoreProvider = project.provider { nodeJs.requireConfigured().cleanableStore }
|
||||||
it.group = TASKS_GROUP_NAME
|
it.group = TASKS_GROUP_NAME
|
||||||
it.description = "Clean unused local node version"
|
it.description = "Clean unused local node version"
|
||||||
}
|
}
|
||||||
@@ -69,7 +134,33 @@ open class NodeJsRootPlugin : Plugin<Project> {
|
|||||||
fun apply(rootProject: Project): NodeJsRootExtension {
|
fun apply(rootProject: Project): NodeJsRootExtension {
|
||||||
check(rootProject == rootProject.rootProject)
|
check(rootProject == rootProject.rootProject)
|
||||||
rootProject.plugins.apply(NodeJsRootPlugin::class.java)
|
rootProject.plugins.apply(NodeJsRootPlugin::class.java)
|
||||||
return rootProject.extensions.getByName(EXTENSION_NAME) as NodeJsRootExtension
|
return rootProject.extensions.getByName(NodeJsRootExtension.EXTENSION_NAME) as NodeJsRootExtension
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val Project.kotlinNodeJsExtension: NodeJsRootExtension
|
||||||
|
get() = extensions.getByName(NodeJsRootExtension.EXTENSION_NAME).castIsolatedKotlinPluginClassLoaderAware()
|
||||||
|
|
||||||
|
private val Project.gradleNodeModules
|
||||||
|
get() = GradleNodeModulesCache.registerIfAbsent(
|
||||||
|
this,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
|
||||||
|
private val Project.compositeNodeModules
|
||||||
|
get() = CompositeNodeModulesCache.registerIfAbsent(
|
||||||
|
this,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
|
||||||
|
val Project.kotlinNpmResolutionManager
|
||||||
|
get() = KotlinNpmResolutionManager.registerIfAbsent(
|
||||||
|
this,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
gradleNodeModules,
|
||||||
|
compositeNodeModules
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -2,6 +2,7 @@ package org.jetbrains.kotlin.gradle.targets.js.nodejs
|
|||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.artifacts.Configuration
|
import org.gradle.api.artifacts.Configuration
|
||||||
|
import org.gradle.api.file.ArchiveOperations
|
||||||
import org.gradle.api.file.FileSystemOperations
|
import org.gradle.api.file.FileSystemOperations
|
||||||
import org.gradle.api.model.ObjectFactory
|
import org.gradle.api.model.ObjectFactory
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
@@ -9,8 +10,8 @@ import org.gradle.api.tasks.*
|
|||||||
import org.gradle.internal.hash.FileHasher
|
import org.gradle.internal.hash.FileHasher
|
||||||
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
|
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
|
||||||
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.extractWithUpToDate
|
import org.jetbrains.kotlin.gradle.targets.js.extractWithUpToDate
|
||||||
import org.jetbrains.kotlin.gradle.utils.ArchiveOperationsCompat
|
|
||||||
import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
|
import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
@@ -21,12 +22,13 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
abstract class NodeJsSetupTask : DefaultTask() {
|
abstract class NodeJsSetupTask : DefaultTask() {
|
||||||
@Transient
|
@Transient
|
||||||
private val settings = NodeJsRootPlugin.apply(project.rootProject)
|
private val settings = project.rootProject.kotlinNodeJsExtension
|
||||||
private val env by lazy { settings.requireConfigured() }
|
private val env by lazy { settings.requireConfigured() }
|
||||||
|
|
||||||
private val shouldDownload = settings.download
|
private val shouldDownload = settings.download
|
||||||
|
|
||||||
private val archiveOperations = ArchiveOperationsCompat(project)
|
@get:Inject
|
||||||
|
abstract internal val archiveOperations: ArchiveOperations
|
||||||
|
|
||||||
@get:Inject
|
@get:Inject
|
||||||
internal open val fileHasher: FileHasher
|
internal open val fileHasher: FileHasher
|
||||||
@@ -36,8 +38,7 @@ abstract class NodeJsSetupTask : DefaultTask() {
|
|||||||
internal abstract val objects: ObjectFactory
|
internal abstract val objects: ObjectFactory
|
||||||
|
|
||||||
@get:Inject
|
@get:Inject
|
||||||
internal open val fs: FileSystemOperations
|
abstract internal val fs: FileSystemOperations
|
||||||
get() = error("Should be injected")
|
|
||||||
|
|
||||||
val ivyDependency: String
|
val ivyDependency: String
|
||||||
@Input get() = env.ivyDependency
|
@Input get() = env.ivyDependency
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ class TasksRequirements : Serializable {
|
|||||||
|
|
||||||
val requiredNpmDependencies = requirements
|
val requiredNpmDependencies = requirements
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.map { it.createDependency(task.compilation.target.project) }
|
.map { it.createDependency(task.compilation.target.project.objects) }
|
||||||
.filterIsInstance<NpmDependency>()
|
.filterIsInstance<NpmDependency>()
|
||||||
.toMutableSet()
|
.toMutableSet()
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -16,8 +16,8 @@ import java.io.File
|
|||||||
/**
|
/**
|
||||||
* Cache for storing already created [GradleNodeModule]s
|
* Cache for storing already created [GradleNodeModule]s
|
||||||
*/
|
*/
|
||||||
internal abstract class AbstractNodeModulesCache : AutoCloseable, BuildService<AbstractNodeModulesCache.Parameters> {
|
abstract class AbstractNodeModulesCache : AutoCloseable, BuildService<AbstractNodeModulesCache.Parameters> {
|
||||||
internal interface Parameters : BuildServiceParameters {
|
interface Parameters : BuildServiceParameters {
|
||||||
val rootProjectDir: DirectoryProperty
|
val rootProjectDir: DirectoryProperty
|
||||||
val cacheDir: DirectoryProperty
|
val cacheDir: DirectoryProperty
|
||||||
}
|
}
|
||||||
|
|||||||
+52
-2
@@ -5,14 +5,24 @@
|
|||||||
|
|
||||||
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.Task
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
import org.gradle.api.tasks.Internal
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.withType
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
internal interface UsesCompositeNodeModulesCache : Task {
|
||||||
|
@get:Internal
|
||||||
|
val compositeNodeModules: Property<CompositeNodeModulesCache>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache for storing already created [GradleNodeModule]s
|
* Cache for storing already created [GradleNodeModule]s
|
||||||
*/
|
*/
|
||||||
internal abstract class CompositeNodeModulesCache : AbstractNodeModulesCache() {
|
abstract class CompositeNodeModulesCache : AbstractNodeModulesCache() {
|
||||||
override val type: String
|
override val type: String
|
||||||
get() = "composite"
|
get() = "composite"
|
||||||
|
|
||||||
@@ -24,4 +34,44 @@ internal abstract class CompositeNodeModulesCache : AbstractNodeModulesCache() {
|
|||||||
val module = CompositeNodeModuleBuilder(file, parameters.cacheDir.get().asFile)
|
val module = CompositeNodeModuleBuilder(file, parameters.cacheDir.get().asFile)
|
||||||
return module.rebuild()
|
return module.rebuild()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val serviceClass = CompositeNodeModulesCache::class.java
|
||||||
|
private val serviceName = serviceClass.name
|
||||||
|
|
||||||
|
private fun registerIfAbsentImpl(
|
||||||
|
project: Project,
|
||||||
|
rootProjectDir: File?,
|
||||||
|
cacheDir: File?
|
||||||
|
): Provider<CompositeNodeModulesCache> {
|
||||||
|
project.gradle.sharedServices.registrations.findByName(serviceName)?.let {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return it.service as Provider<CompositeNodeModulesCache>
|
||||||
|
}
|
||||||
|
|
||||||
|
val message = {
|
||||||
|
"Build service Composite Node Modules should be already registered"
|
||||||
|
}
|
||||||
|
|
||||||
|
requireNotNull(rootProjectDir, message)
|
||||||
|
requireNotNull(cacheDir, message)
|
||||||
|
|
||||||
|
return project.gradle.sharedServices.registerIfAbsent(serviceName, serviceClass) {
|
||||||
|
it.parameters.rootProjectDir.set(rootProjectDir)
|
||||||
|
it.parameters.cacheDir.set(cacheDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun registerIfAbsent(
|
||||||
|
project: Project,
|
||||||
|
rootProjectDir: File?,
|
||||||
|
cacheDir: File?
|
||||||
|
) = registerIfAbsentImpl(project, rootProjectDir, cacheDir).also { serviceProvider ->
|
||||||
|
SingleActionPerProject.run(project, UsesCompositeNodeModulesCache::class.java.name) {
|
||||||
|
project.tasks.withType<UsesCompositeNodeModulesCache>().configureEach { task ->
|
||||||
|
task.usesService(serviceProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+4
-4
@@ -5,22 +5,22 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.targets.js.npm
|
package org.jetbrains.kotlin.gradle.targets.js.npm
|
||||||
|
|
||||||
|
import org.gradle.api.file.ArchiveOperations
|
||||||
|
import org.gradle.api.file.FileSystemOperations
|
||||||
import org.gradle.api.file.FileTree
|
import org.gradle.api.file.FileTree
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.HTML
|
import org.jetbrains.kotlin.gradle.targets.js.HTML
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.JS
|
import org.jetbrains.kotlin.gradle.targets.js.JS
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.JS_MAP
|
import org.jetbrains.kotlin.gradle.targets.js.JS_MAP
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.META_JS
|
import org.jetbrains.kotlin.gradle.targets.js.META_JS
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KLIB_TYPE
|
import org.jetbrains.kotlin.gradle.targets.js.ir.KLIB_TYPE
|
||||||
import org.jetbrains.kotlin.gradle.utils.ArchiveOperationsCompat
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.FileSystemOperationsCompat
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates fake NodeJS module directory from given gradle [dependency].
|
* Creates fake NodeJS module directory from given gradle [dependency].
|
||||||
*/
|
*/
|
||||||
internal class GradleNodeModuleBuilder(
|
internal class GradleNodeModuleBuilder(
|
||||||
val fs: FileSystemOperationsCompat,
|
val fs: FileSystemOperations,
|
||||||
val archiveOperations: ArchiveOperationsCompat,
|
val archiveOperations: ArchiveOperations,
|
||||||
val moduleName: String,
|
val moduleName: String,
|
||||||
val moduleVersion: String,
|
val moduleVersion: String,
|
||||||
val srcFiles: Collection<File>,
|
val srcFiles: Collection<File>,
|
||||||
|
|||||||
+62
-10
@@ -5,28 +5,40 @@
|
|||||||
|
|
||||||
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.Task
|
||||||
|
import org.gradle.api.file.ArchiveOperations
|
||||||
|
import org.gradle.api.file.DirectoryProperty
|
||||||
import org.gradle.api.file.FileSystemOperations
|
import org.gradle.api.file.FileSystemOperations
|
||||||
import org.jetbrains.kotlin.gradle.utils.ArchiveOperationsCompat
|
import org.gradle.api.provider.Property
|
||||||
import org.jetbrains.kotlin.gradle.utils.FileSystemOperationsCompat
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.tasks.Internal
|
||||||
|
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
|
||||||
|
import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService
|
||||||
|
import org.jetbrains.kotlin.gradle.report.reportingSettings
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.withType
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal interface UsesGradleNodeModulesCache : Task {
|
||||||
|
@get:Internal
|
||||||
|
val gradleNodeModules: Property<GradleNodeModulesCache>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache for storing already created [GradleNodeModule]s
|
* Cache for storing already created [GradleNodeModule]s
|
||||||
*/
|
*/
|
||||||
internal abstract class GradleNodeModulesCache : AbstractNodeModulesCache() {
|
abstract class GradleNodeModulesCache : AbstractNodeModulesCache() {
|
||||||
|
|
||||||
// TODO: replace by injected service org.gradle.api.file.FileSystemOperations once min support Gradle is 6.2
|
@get:Inject
|
||||||
// https://github.com/gradle/gradle/commit/d02b9d84c08dba64775fb9581e3280f88d319a21
|
abstract val fs: FileSystemOperations
|
||||||
@Transient
|
|
||||||
lateinit var fs: FileSystemOperationsCompat
|
|
||||||
|
|
||||||
override val type: String
|
override val type: String
|
||||||
get() = "gradle"
|
get() = "gradle"
|
||||||
|
|
||||||
// TODO: replace by injected service org.gradle.api.file.ArchiveOperations once min supported Gradle is 6.6
|
@get:Inject
|
||||||
@Transient
|
abstract val archiveOperations: ArchiveOperations
|
||||||
lateinit var archiveOperations: ArchiveOperationsCompat
|
|
||||||
|
|
||||||
override fun buildImportedPackage(
|
override fun buildImportedPackage(
|
||||||
name: String,
|
name: String,
|
||||||
@@ -37,4 +49,44 @@ internal abstract class GradleNodeModulesCache : AbstractNodeModulesCache() {
|
|||||||
module.visitArtifacts()
|
module.visitArtifacts()
|
||||||
return module.rebuild()
|
return module.rebuild()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val serviceClass = GradleNodeModulesCache::class.java
|
||||||
|
private val serviceName = serviceClass.name
|
||||||
|
|
||||||
|
private fun registerIfAbsentImpl(
|
||||||
|
project: Project,
|
||||||
|
rootProjectDir: File?,
|
||||||
|
cacheDir: File?
|
||||||
|
): Provider<GradleNodeModulesCache> {
|
||||||
|
project.gradle.sharedServices.registrations.findByName(serviceName)?.let {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return it.service as Provider<GradleNodeModulesCache>
|
||||||
|
}
|
||||||
|
|
||||||
|
val message = {
|
||||||
|
"Build service Gradle Node Modules should be already registered"
|
||||||
|
}
|
||||||
|
|
||||||
|
requireNotNull(rootProjectDir, message)
|
||||||
|
requireNotNull(cacheDir, message)
|
||||||
|
|
||||||
|
return project.gradle.sharedServices.registerIfAbsent(serviceName, serviceClass) {
|
||||||
|
it.parameters.rootProjectDir.set(rootProjectDir)
|
||||||
|
it.parameters.cacheDir.set(cacheDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun registerIfAbsent(
|
||||||
|
project: Project,
|
||||||
|
rootProjectDir: File?,
|
||||||
|
cacheDir: File?
|
||||||
|
) = registerIfAbsentImpl(project, rootProjectDir, cacheDir).also { serviceProvider ->
|
||||||
|
SingleActionPerProject.run(project, UsesGradleNodeModulesCache::class.java.name) {
|
||||||
|
project.tasks.withType<UsesGradleNodeModulesCache>().configureEach { task ->
|
||||||
|
task.usesService(serviceProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+108
-204
@@ -5,169 +5,74 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.targets.js.npm
|
package org.jetbrains.kotlin.gradle.targets.js.npm
|
||||||
|
|
||||||
import org.gradle.api.Incubating
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.Task
|
import org.gradle.api.Task
|
||||||
import org.gradle.api.internal.project.ProjectInternal
|
|
||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
|
import org.gradle.api.provider.MapProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.services.BuildService
|
import org.gradle.api.services.BuildService
|
||||||
import org.gradle.api.services.BuildServiceParameters
|
import org.gradle.api.services.BuildServiceParameters
|
||||||
|
import org.gradle.api.tasks.Internal
|
||||||
import org.gradle.internal.service.ServiceRegistry
|
import org.gradle.internal.service.ServiceRegistry
|
||||||
import org.jetbrains.kotlin.gradle.internal.isInIdeaSync
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.Installation
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinProjectNpmResolution
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinRootNpmResolution
|
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.withType
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinProjectNpmResolver
|
import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinPackageJsonTask
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.unavailableValueError
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
/**
|
internal interface UsesKotlinNpmResolutionManager : Task {
|
||||||
* # NPM resolution state manager
|
@get:Internal
|
||||||
*
|
val npmResolutionManager: Property<KotlinNpmResolutionManager>
|
||||||
* ## Resolving process from Gradle
|
}
|
||||||
*
|
|
||||||
* **configuring**. Global initial state. [NpmResolverPlugin] should be applied for each project
|
abstract class KotlinNpmResolutionManager : BuildService<KotlinNpmResolutionManager.Parameters> {
|
||||||
* that requires NPM resolution. When applied, [KotlinProjectNpmResolver] will be created for the
|
|
||||||
* corresponding project and will subscribe to all js compilations. [NpmResolverPlugin] requires
|
interface Parameters : BuildServiceParameters {
|
||||||
* kotlin mulitplatform or plaform plugin applied first.
|
val resolution: Property<KotlinRootNpmResolution>
|
||||||
*
|
|
||||||
* **up-to-date-checked**. This state is compilation local: one compilation may be in up-to-date-checked
|
// pulled up from compilation resolver since it was failing with ClassNotFoundException on deserialization, see KT-49061
|
||||||
* state, while another may be steel in configuring state. New compilations may be added in this
|
val packageJsonHandlers: MapProperty<String, List<PackageJson.() -> Unit>>
|
||||||
* state, but compilations that are already up-to-date-checked cannot be changed.
|
|
||||||
* Initiated by calling [KotlinPackageJsonTask.producerInputs] getter (will be called by Gradle).
|
val gradleNodeModulesProvider: Property<GradleNodeModulesCache>
|
||||||
* [KotlinCompilationNpmResolver] will create and **resolve** aggregated compilation configuration,
|
val compositeNodeModulesProvider: Property<CompositeNodeModulesCache>
|
||||||
* which contains all related compilation configuration and NPM tools configuration.
|
|
||||||
* NPM tools configuration contains all dependencies that is required for all enabled
|
|
||||||
* tasks related to this compilation. It is important to resolve this configuration inside particular
|
|
||||||
* project and not globally. Aggregated configuration will be analyzed for gradle internal dependencies
|
|
||||||
* (project dependencies), gradle external dependencies and npm dependencies. This collections will
|
|
||||||
* be treated as `packageJson` task inputs.
|
|
||||||
*
|
|
||||||
* **package-json-created**. This state also compilation local. Initiated by executing `packageJson`
|
|
||||||
* task for particular compilation. If `packageJson` task is up-to-date, this state is reached by
|
|
||||||
* first calling [KotlinCompilationNpmResolver.getResolutionOrResolveIfForced] which may be called
|
|
||||||
* by compilation that depends on this compilation. Note that package.json will be executed only for
|
|
||||||
* required compilations, while other may be missed.
|
|
||||||
*
|
|
||||||
* **Prepared**.
|
|
||||||
* Global final state. Initiated by executing global `rootPackageJson` task.
|
|
||||||
*
|
|
||||||
* **Installed**.
|
|
||||||
* All created package.json files will be gathered and package manager will be executed.
|
|
||||||
* Package manager will create lock file, that will be parsed for transitive npm dependencies
|
|
||||||
* that will be added to the root [NpmDependency] objects. `kotlinNpmInstall` task may be up-to-date.
|
|
||||||
* In this case, installed state will be reached by first call of [installIfNeeded] without executing
|
|
||||||
* package manager.
|
|
||||||
*
|
|
||||||
* Resolution will be used from [NpmDependency] by calling [getNpmDependencyResolvedCompilation].
|
|
||||||
* Also resolution will be checked before calling [NpmProject.require] and executing any task
|
|
||||||
* that requires npm dependencies or node_modules.
|
|
||||||
*
|
|
||||||
* User can call [requireInstalled] to get resolution info.
|
|
||||||
*
|
|
||||||
* ## Resolving process during Idea import
|
|
||||||
*
|
|
||||||
* In this case [forceFullResolve] will be set, and all compilations will be resolved
|
|
||||||
* even without `packageJson` task execution.
|
|
||||||
*
|
|
||||||
* During building gradle project model, all [NpmDependency] will be asked for there files,
|
|
||||||
* and [getNpmDependencyResolvedCompilation] will be called. In the [forceFullResolve] mode
|
|
||||||
* project will be fully resolved: all `package.json` files will be created, and package manager
|
|
||||||
* will be called. We are manually tracking package.json files contents to avoid calling package manager
|
|
||||||
* if nothing was changes.
|
|
||||||
*
|
|
||||||
* Note that in this case resolution process will be performed outside of task execution.
|
|
||||||
*/
|
|
||||||
class KotlinNpmResolutionManager(@Transient private val nodeJsSettings: NodeJsRootExtension?) {
|
|
||||||
private val forceFullResolve: Boolean by lazy {
|
|
||||||
(nodeJsSettings ?: unavailableValueError("nodeJsSettings")).rootProject.isInIdeaSync
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val resolver = KotlinRootNpmResolver(nodeJsSettings, forceFullResolve)
|
val resolution
|
||||||
|
get() = parameters.resolution
|
||||||
|
|
||||||
internal abstract class KotlinNpmResolutionManagerStateHolder : BuildService<BuildServiceParameters.None> {
|
@Volatile
|
||||||
@Volatile
|
var state: ResolutionState = ResolutionState.Configuring(resolution.get())
|
||||||
internal var state: ResolutionState? = null
|
|
||||||
}
|
|
||||||
|
|
||||||
private val stateHolderProvider = (nodeJsSettings ?: unavailableValueError("nodeJsSettings"))
|
|
||||||
.rootProject.gradle.sharedServices.registerIfAbsent(
|
|
||||||
"npm-resolution-manager-state-holder", KotlinNpmResolutionManagerStateHolder::class.java
|
|
||||||
) {
|
|
||||||
}.also {
|
|
||||||
resolver.declareBuildServiceForRootProjectJsTasks(it)
|
|
||||||
resolver.declareBuildServiceForAllProjectsJsTasks(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val stateHolder get() = stateHolderProvider.get()
|
|
||||||
|
|
||||||
var state: ResolutionState
|
|
||||||
get() = stateHolder.state ?: ResolutionState.Configuring(resolver)
|
|
||||||
set(value) {
|
|
||||||
stateHolder.state = value
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class ResolutionState {
|
sealed class ResolutionState {
|
||||||
abstract val npmProjects: List<NpmProject>
|
|
||||||
|
|
||||||
class Configuring(val resolver: KotlinRootNpmResolver) : ResolutionState() {
|
class Configuring(val resolution: KotlinRootNpmResolution) : ResolutionState()
|
||||||
override val npmProjects: List<NpmProject>
|
|
||||||
get() = resolver.compilations.map { it.npmProject }
|
|
||||||
}
|
|
||||||
|
|
||||||
open class Prepared(val preparedInstallation: KotlinRootNpmResolver.Installation) : ResolutionState() {
|
open class Prepared(val preparedInstallation: Installation) : ResolutionState()
|
||||||
override val npmProjects: List<NpmProject>
|
|
||||||
get() = npmProjectsByProjectResolutions(preparedInstallation.projectResolutions)
|
|
||||||
}
|
|
||||||
|
|
||||||
class Installed internal constructor(internal val resolved: KotlinRootNpmResolution) : ResolutionState() {
|
class Installed() : ResolutionState()
|
||||||
override val npmProjects: List<NpmProject>
|
|
||||||
get() = npmProjectsByProjectResolutions(resolved.projects)
|
|
||||||
}
|
|
||||||
|
|
||||||
class Error(val wrappedException: Throwable) : ResolutionState() {
|
class Error(val wrappedException: Throwable) : ResolutionState()
|
||||||
override val npmProjects: List<NpmProject>
|
|
||||||
get() = emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun npmProjectsByProjectResolutions(
|
|
||||||
resolutions: Map<String, KotlinProjectNpmResolution>
|
|
||||||
): List<NpmProject> {
|
|
||||||
return resolutions
|
|
||||||
.values
|
|
||||||
.flatMap { it.npmProjects.map { it.npmProject } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Incubating
|
|
||||||
internal fun requireInstalled(
|
|
||||||
services: ServiceRegistry,
|
|
||||||
logger: Logger,
|
|
||||||
reason: String = ""
|
|
||||||
) = installIfNeeded(reason = reason, services = services, logger = logger)
|
|
||||||
|
|
||||||
internal fun requireConfiguringState(): KotlinRootNpmResolver =
|
|
||||||
(this.state as? ResolutionState.Configuring ?: error("NPM Dependencies already resolved and installed")).resolver
|
|
||||||
|
|
||||||
internal fun isConfiguringState(): Boolean =
|
internal fun isConfiguringState(): Boolean =
|
||||||
this.state is ResolutionState.Configuring
|
this.state is ResolutionState.Configuring
|
||||||
|
|
||||||
internal fun prepare(logger: Logger) = prepareIfNeeded(requireNotPrepared = true, logger = logger)
|
internal fun prepare(
|
||||||
|
logger: Logger,
|
||||||
|
npmEnvironment: NpmEnvironment,
|
||||||
|
yarnEnvironment: YarnEnvironment,
|
||||||
|
) = prepareIfNeeded(logger = logger, npmEnvironment, yarnEnvironment)
|
||||||
|
|
||||||
internal fun installIfNeeded(
|
internal fun installIfNeeded(
|
||||||
reason: String? = "",
|
|
||||||
args: List<String> = emptyList(),
|
args: List<String> = emptyList(),
|
||||||
services: ServiceRegistry,
|
services: ServiceRegistry,
|
||||||
logger: Logger
|
logger: Logger,
|
||||||
): KotlinRootNpmResolution? {
|
npmEnvironment: NpmEnvironment,
|
||||||
synchronized(stateHolder) {
|
yarnEnvironment: YarnEnvironment,
|
||||||
|
): Unit? {
|
||||||
|
synchronized(this) {
|
||||||
if (state is ResolutionState.Installed) {
|
if (state is ResolutionState.Installed) {
|
||||||
return (state as ResolutionState.Installed).resolved
|
return Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state is ResolutionState.Error) {
|
if (state is ResolutionState.Error) {
|
||||||
@@ -175,14 +80,9 @@ class KotlinNpmResolutionManager(@Transient private val nodeJsSettings: NodeJsRo
|
|||||||
}
|
}
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
val installUpToDate = nodeJsSettings?.npmInstallTaskProvider?.get()?.state?.upToDate ?: false
|
val installation: Installation = prepareIfNeeded(logger = logger, npmEnvironment, yarnEnvironment)
|
||||||
val forceUpToDate = installUpToDate && !forceFullResolve
|
installation.install(args, services, logger, npmEnvironment, yarnEnvironment)
|
||||||
|
state = ResolutionState.Installed()
|
||||||
val installation = prepareIfNeeded(requireUpToDateReason = reason, logger = logger)
|
|
||||||
val resolution = installation
|
|
||||||
.install(forceUpToDate, args, services, logger)
|
|
||||||
state = ResolutionState.Installed(resolution)
|
|
||||||
resolution
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
state = ResolutionState.Error(e)
|
state = ResolutionState.Error(e)
|
||||||
throw e
|
throw e
|
||||||
@@ -190,93 +90,97 @@ class KotlinNpmResolutionManager(@Transient private val nodeJsSettings: NodeJsRo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val packageJsonFiles: Collection<File>
|
// internal val packageJsonFiles: Collection<File>
|
||||||
get() = state.npmProjects.map { it.packageJsonFile }
|
// get() = state.npmProjects.map { it.packageJsonFile }
|
||||||
|
|
||||||
/**
|
|
||||||
* @param requireUpToDateReason Check that project already resolved,
|
|
||||||
* or it is up-to-date but just not closed. Show given message if it is not.
|
|
||||||
* @param requireNotPrepared Check that project is not prepared
|
|
||||||
*/
|
|
||||||
private fun prepareIfNeeded(
|
private fun prepareIfNeeded(
|
||||||
requireUpToDateReason: String? = null,
|
logger: Logger,
|
||||||
requireNotPrepared: Boolean = false,
|
npmEnvironment: NpmEnvironment,
|
||||||
logger: Logger
|
yarnEnvironment: YarnEnvironment,
|
||||||
): KotlinRootNpmResolver.Installation {
|
): Installation {
|
||||||
fun alreadyResolved(installation: KotlinRootNpmResolver.Installation): KotlinRootNpmResolver.Installation {
|
|
||||||
if (requireNotPrepared) error("Project already prepared")
|
|
||||||
return installation
|
|
||||||
}
|
|
||||||
|
|
||||||
val state0 = this.state
|
val state0 = this.state
|
||||||
return when (state0) {
|
return when (state0) {
|
||||||
is ResolutionState.Prepared -> {
|
is ResolutionState.Prepared -> {
|
||||||
alreadyResolved(state0.preparedInstallation)
|
state0.preparedInstallation
|
||||||
}
|
}
|
||||||
|
|
||||||
is ResolutionState.Configuring -> {
|
is ResolutionState.Configuring -> {
|
||||||
synchronized(stateHolder) {
|
synchronized(this) {
|
||||||
val state1 = this.state
|
val state1 = this.state
|
||||||
when (state1) {
|
when (state1) {
|
||||||
is ResolutionState.Prepared -> alreadyResolved(state1.preparedInstallation)
|
is ResolutionState.Prepared -> state1.preparedInstallation
|
||||||
is ResolutionState.Configuring -> {
|
is ResolutionState.Configuring -> {
|
||||||
val upToDate = nodeJsSettings?.rootPackageJsonTaskProvider?.get()?.state?.upToDate ?: true
|
state1.resolution.prepareInstallation(
|
||||||
if (requireUpToDateReason != null && !upToDate) {
|
logger,
|
||||||
error("NPM dependencies should be resolved $requireUpToDateReason")
|
npmEnvironment,
|
||||||
}
|
yarnEnvironment,
|
||||||
|
this
|
||||||
state1.resolver.prepareInstallation(logger).also {
|
).also {
|
||||||
this.state = ResolutionState.Prepared(it)
|
this.state = ResolutionState.Prepared(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is ResolutionState.Installed -> error("Project already installed")
|
is ResolutionState.Installed -> error("Project already installed")
|
||||||
is ResolutionState.Error -> throw state1.wrappedException
|
is ResolutionState.Error -> throw state1.wrappedException
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is ResolutionState.Installed -> error("Project already installed")
|
is ResolutionState.Installed -> error("Project already installed")
|
||||||
is ResolutionState.Error -> throw state0.wrappedException
|
is ResolutionState.Error -> throw state0.wrappedException
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getNpmDependencyResolvedCompilation(npmDependency: NpmDependency): KotlinCompilationNpmResolution? {
|
companion object {
|
||||||
val project = npmDependency.project!!
|
private val serviceClass = KotlinNpmResolutionManager::class.java
|
||||||
val projectPath = project.path
|
private val serviceName = serviceClass.name
|
||||||
val services = (project as ProjectInternal).services
|
|
||||||
val logger = project.logger
|
|
||||||
|
|
||||||
val resolvedProject =
|
private fun registerIfAbsentImpl(
|
||||||
if (forceFullResolve) {
|
project: Project,
|
||||||
installIfNeeded(reason = null, services = services, logger = logger)?.get(projectPath) ?: return null
|
resolution: Provider<KotlinRootNpmResolution>?,
|
||||||
} else {
|
packageJsonHandlers: Provider<Map<String, MutableList<PackageJson.() -> Unit>>>?,
|
||||||
// may return null only during npm resolution
|
gradleNodeModulesProvider: Provider<GradleNodeModulesCache>,
|
||||||
// (it can be called since NpmDependency added to configuration that
|
compositeNodeModulesProvider: Provider<CompositeNodeModulesCache>
|
||||||
// requires resolve to build package.json, in this case we should just skip this call)
|
): Provider<KotlinNpmResolutionManager> {
|
||||||
val state0 = state
|
project.gradle.sharedServices.registrations.findByName(serviceName)?.let {
|
||||||
when (state0) {
|
@Suppress("UNCHECKED_CAST")
|
||||||
is ResolutionState.Prepared -> state0.preparedInstallation[projectPath]
|
return it.service as Provider<KotlinNpmResolutionManager>
|
||||||
is ResolutionState.Configuring -> {
|
|
||||||
return null
|
|
||||||
//error("Cannot use NpmDependency before :kotlinNpmInstall task execution")
|
|
||||||
}
|
|
||||||
is ResolutionState.Installed -> state0.resolved[projectPath]
|
|
||||||
is ResolutionState.Error -> {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolvedProject.npmProjectsByNpmDependency[npmDependency] ?: error("NPM project resolved without $this")
|
val message = {
|
||||||
}
|
"Build service KotlinNpmResolutionManager should be already registered"
|
||||||
|
}
|
||||||
|
|
||||||
internal fun <T> checkRequiredDependencies(task: T)
|
requireNotNull(resolution, message)
|
||||||
where T : RequiresNpmDependencies,
|
requireNotNull(packageJsonHandlers, message)
|
||||||
T : Task {
|
|
||||||
val targetRequired = resolver.taskRequirements.byTask[task.path]?.toSet() ?: setOf()
|
|
||||||
|
|
||||||
task.requiredNpmDependencies.forEach {
|
return project.gradle.sharedServices.registerIfAbsent(serviceName, serviceClass) {
|
||||||
check(it in targetRequired) {
|
it.parameters.resolution.set(resolution)
|
||||||
"${it.createDependency(task.project)} required by $task was not found resolved at the time of nodejs package manager call. " +
|
it.parameters.packageJsonHandlers.set(packageJsonHandlers)
|
||||||
"This may be caused by changing $task configuration after npm dependencies resolution."
|
it.parameters.gradleNodeModulesProvider.set(gradleNodeModulesProvider)
|
||||||
|
it.parameters.compositeNodeModulesProvider.set(compositeNodeModulesProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun registerIfAbsent(
|
||||||
|
project: Project,
|
||||||
|
resolution: Provider<KotlinRootNpmResolution>?,
|
||||||
|
packageJsonHandlers: Provider<Map<String, MutableList<PackageJson.() -> Unit>>>?,
|
||||||
|
gradleNodeModulesProvider: Provider<GradleNodeModulesCache>,
|
||||||
|
compositeNodeModulesProvider: Provider<CompositeNodeModulesCache>
|
||||||
|
) = registerIfAbsentImpl(
|
||||||
|
project,
|
||||||
|
resolution,
|
||||||
|
packageJsonHandlers,
|
||||||
|
gradleNodeModulesProvider,
|
||||||
|
compositeNodeModulesProvider
|
||||||
|
).also { serviceProvider ->
|
||||||
|
SingleActionPerProject.run(project, UsesKotlinNpmResolutionManager::class.java.name) {
|
||||||
|
project.tasks.withType<UsesKotlinNpmResolutionManager>().configureEach { task ->
|
||||||
|
task.usesService(serviceProvider)
|
||||||
|
task.usesService(gradleNodeModulesProvider)
|
||||||
|
task.usesService(compositeNodeModulesProvider)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-20
@@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
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.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.internal.service.ServiceRegistry
|
import org.gradle.internal.service.ServiceRegistry
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsEnv
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.PreparedKotlinCompilationNpmResolution
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnEnv
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnEnv
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnResolution
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
@@ -18,36 +18,26 @@ import java.io.Serializable
|
|||||||
* NodeJS package manager API
|
* NodeJS package manager API
|
||||||
*/
|
*/
|
||||||
interface NpmApi : Serializable {
|
interface NpmApi : Serializable {
|
||||||
fun setup(project: Project)
|
|
||||||
|
|
||||||
fun preparedFiles(nodeJs: NpmEnvironment): Collection<File>
|
fun preparedFiles(nodeJs: NpmEnvironment): Collection<File>
|
||||||
|
|
||||||
fun prepareRootProject(
|
fun prepareRootProject(
|
||||||
rootProject: Project?,
|
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NpmEnvironment,
|
||||||
rootProjectName: String,
|
rootProjectName: String,
|
||||||
rootProjectVersion: String,
|
rootProjectVersion: String,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
subProjects: Collection<KotlinCompilationNpmResolution>,
|
subProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
resolutions: Map<String, String>,
|
resolutions: Map<String, String>,
|
||||||
forceFullResolve: Boolean
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fun resolveRootProject(
|
fun resolveRootProject(
|
||||||
services: ServiceRegistry,
|
services: ServiceRegistry,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NpmEnvironment,
|
||||||
yarn: YarnEnv,
|
yarn: YarnEnvironment,
|
||||||
npmProjects: Collection<KotlinCompilationNpmResolution>,
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
cliArgs: List<String>
|
cliArgs: List<String>
|
||||||
)
|
)
|
||||||
|
|
||||||
fun resolveDependency(
|
|
||||||
npmResolution: KotlinCompilationNpmResolution,
|
|
||||||
dependency: NpmDependency,
|
|
||||||
transitive: Boolean
|
|
||||||
): Set<File>
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun resolveOperationDescription(packageManagerTitle: String): String =
|
fun resolveOperationDescription(packageManagerTitle: String): String =
|
||||||
"Resolving NPM dependencies using $packageManagerTitle"
|
"Resolving NPM dependencies using $packageManagerTitle"
|
||||||
@@ -57,12 +47,29 @@ interface NpmApi : Serializable {
|
|||||||
data class NpmEnvironment(
|
data class NpmEnvironment(
|
||||||
val rootPackageDir: File,
|
val rootPackageDir: File,
|
||||||
val nodeExecutable: String,
|
val nodeExecutable: String,
|
||||||
val isWindows: Boolean
|
val isWindows: Boolean,
|
||||||
|
val packageManager: NpmApi
|
||||||
) : Serializable
|
) : Serializable
|
||||||
|
|
||||||
internal val NodeJsRootExtension.asNpmEnvironment
|
internal val NodeJsEnv.asNpmEnvironment
|
||||||
get() = NpmEnvironment(
|
get() = NpmEnvironment(
|
||||||
rootPackageDir,
|
rootPackageDir,
|
||||||
requireConfigured().nodeExecutable,
|
nodeExecutable,
|
||||||
requireConfigured().isWindows
|
isWindows,
|
||||||
|
packageManager
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class YarnEnvironment(
|
||||||
|
val executable: String,
|
||||||
|
val standalone: Boolean,
|
||||||
|
val ignoreScripts: Boolean,
|
||||||
|
val yarnResolutions: List<YarnResolution>
|
||||||
|
) : Serializable
|
||||||
|
|
||||||
|
internal val YarnEnv.asYarnEnvironment
|
||||||
|
get() = YarnEnvironment(
|
||||||
|
executable,
|
||||||
|
standalone,
|
||||||
|
ignoreScripts,
|
||||||
|
yarnResolutions
|
||||||
|
)
|
||||||
+20
-68
@@ -5,31 +5,23 @@
|
|||||||
|
|
||||||
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.artifacts.Dependency
|
import org.gradle.api.artifacts.Dependency
|
||||||
import org.gradle.api.artifacts.FileCollectionDependency
|
import org.gradle.api.artifacts.FileCollectionDependency
|
||||||
import org.gradle.api.artifacts.SelfResolvingDependency
|
import org.gradle.api.artifacts.component.ComponentIdentifier
|
||||||
import org.gradle.api.file.FileCollection
|
import org.gradle.api.file.FileCollection
|
||||||
import org.gradle.api.internal.artifacts.DependencyResolveContext
|
|
||||||
import org.gradle.api.internal.artifacts.ResolvableDependency
|
|
||||||
import org.gradle.api.internal.artifacts.dependencies.SelfResolvingDependencyInternal
|
import org.gradle.api.internal.artifacts.dependencies.SelfResolvingDependencyInternal
|
||||||
|
import org.gradle.api.model.ObjectFactory
|
||||||
import org.gradle.api.tasks.TaskDependency
|
import org.gradle.api.tasks.TaskDependency
|
||||||
import org.gradle.internal.component.local.model.DefaultLibraryBinaryIdentifier
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject.Companion.PACKAGE_JSON
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject.Companion.PACKAGE_JSON
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
data class NpmDependency(
|
data class NpmDependency(
|
||||||
@Transient
|
val objectFactory: ObjectFactory,
|
||||||
internal val project: Project?,
|
val scope: Scope = Scope.NORMAL,
|
||||||
private val name: String,
|
private val name: String,
|
||||||
private val version: String,
|
private val version: String,
|
||||||
val scope: Scope = Scope.NORMAL,
|
) : FileCollectionDependency,
|
||||||
) : SelfResolvingDependency,
|
SelfResolvingDependencyInternal {
|
||||||
SelfResolvingDependencyInternal,
|
|
||||||
ResolvableDependency,
|
|
||||||
FileCollectionDependency {
|
|
||||||
|
|
||||||
enum class Scope {
|
enum class Scope {
|
||||||
NORMAL,
|
NORMAL,
|
||||||
@@ -38,73 +30,33 @@ data class NpmDependency(
|
|||||||
PEER
|
PEER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var reason: String? = null
|
||||||
|
|
||||||
override fun getGroup(): String? = null
|
override fun getGroup(): String? = null
|
||||||
|
|
||||||
|
override fun getName() = name
|
||||||
|
|
||||||
|
override fun getVersion() = version
|
||||||
|
|
||||||
internal var parent: NpmDependency? = null
|
internal var parent: NpmDependency? = null
|
||||||
internal val dependencies = mutableSetOf<NpmDependency>()
|
internal val dependencies = mutableSetOf<NpmDependency>()
|
||||||
internal var resolvedVersion: String? = null
|
internal var resolvedVersion: String? = null
|
||||||
internal var integrity: String? = null
|
internal var integrity: String? = null
|
||||||
|
|
||||||
override fun resolve(transitive: Boolean): Set<File> =
|
override fun resolve(transitive: Boolean): Set<File> =
|
||||||
resolveProject()
|
resolve()
|
||||||
?.let {
|
|
||||||
it
|
|
||||||
.npmProject
|
|
||||||
.nodeJs
|
|
||||||
.packageManager
|
|
||||||
.resolveDependency(
|
|
||||||
it,
|
|
||||||
this,
|
|
||||||
transitive
|
|
||||||
)
|
|
||||||
}
|
|
||||||
?: mutableSetOf()
|
|
||||||
|
|
||||||
override fun resolve(): MutableSet<File> {
|
override fun getTargetComponentId(): ComponentIdentifier? = null
|
||||||
val npmPackage = parent?.resolveProject()
|
override fun resolve(): MutableSet<File> = mutableSetOf()
|
||||||
?: resolveProject()
|
|
||||||
?: return mutableSetOf()
|
|
||||||
return mutableSetOf(npmPackage.npmProject.resolve(key)!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun resolve(context: DependencyResolveContext) {
|
override fun getFiles(): FileCollection = objectFactory.fileCollection()
|
||||||
val npmPackage = resolveProject()
|
|
||||||
if (npmPackage != null) {
|
|
||||||
npmPackage.project.files(npmPackage.npmProject.resolve(key))
|
|
||||||
dependencies.forEach {
|
|
||||||
context.add(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// may return null only during npm resolution
|
|
||||||
// (it can be called since NpmDependency added to configuration that
|
|
||||||
// requires resolve to build package.json, in this case we should just skip this call)
|
|
||||||
private fun resolveProject(): KotlinCompilationNpmResolution? {
|
|
||||||
val nodeJs = NodeJsRootPlugin.apply(project!!.rootProject)
|
|
||||||
return nodeJs.npmResolutionManager.getNpmDependencyResolvedCompilation(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
val key: String = name
|
|
||||||
|
|
||||||
override fun toString() = "$key: $version"
|
|
||||||
|
|
||||||
override fun getFiles(): FileCollection = project!!.files(resolve(true))
|
|
||||||
|
|
||||||
override fun getName() = name
|
|
||||||
|
|
||||||
override fun getVersion() = version
|
|
||||||
|
|
||||||
override fun getBuildDependencies(): TaskDependency = TaskDependency { mutableSetOf() }
|
override fun getBuildDependencies(): TaskDependency = TaskDependency { mutableSetOf() }
|
||||||
|
|
||||||
override fun contentEquals(dependency: Dependency) = this == dependency
|
override fun contentEquals(dependency: Dependency) = this == dependency
|
||||||
|
|
||||||
override fun getTargetComponentId() = DefaultLibraryBinaryIdentifier(project!!.path, key, "npm")
|
|
||||||
|
|
||||||
override fun copy(): Dependency = this.copy(name = name)
|
override fun copy(): Dependency = this.copy(name = name)
|
||||||
|
|
||||||
private var reason: String? = null
|
|
||||||
|
|
||||||
override fun because(reason: String?) {
|
override fun because(reason: String?) {
|
||||||
this.reason = reason
|
this.reason = reason
|
||||||
}
|
}
|
||||||
@@ -113,20 +65,20 @@ data class NpmDependency(
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun directoryNpmDependency(
|
internal fun directoryNpmDependency(
|
||||||
project: Project,
|
objectFactory: ObjectFactory,
|
||||||
|
scope: NpmDependency.Scope,
|
||||||
name: String,
|
name: String,
|
||||||
directory: File,
|
directory: File,
|
||||||
scope: NpmDependency.Scope,
|
|
||||||
): NpmDependency {
|
): NpmDependency {
|
||||||
check(directory.isDirectory) {
|
check(directory.isDirectory) {
|
||||||
"Dependency on local path should point on directory but $directory found"
|
"Dependency on local path should point on directory but $directory found"
|
||||||
}
|
}
|
||||||
|
|
||||||
return NpmDependency(
|
return NpmDependency(
|
||||||
project = project,
|
objectFactory = objectFactory,
|
||||||
|
scope = scope,
|
||||||
name = name,
|
name = name,
|
||||||
version = fileVersion(directory),
|
version = fileVersion(directory),
|
||||||
scope = scope,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -118,7 +118,7 @@ private abstract class NpmDependencyExtensionDelegate(
|
|||||||
version: String,
|
version: String,
|
||||||
): NpmDependency =
|
): NpmDependency =
|
||||||
NpmDependency(
|
NpmDependency(
|
||||||
project = project,
|
objectFactory = project.objects,
|
||||||
name = name,
|
name = name,
|
||||||
version = version,
|
version = version,
|
||||||
scope = scope,
|
scope = scope,
|
||||||
@@ -289,10 +289,10 @@ private fun defaultNpmDependencyDelegate(
|
|||||||
directory: File,
|
directory: File,
|
||||||
): NpmDependency =
|
): NpmDependency =
|
||||||
directoryNpmDependency(
|
directoryNpmDependency(
|
||||||
project = project,
|
objectFactory = project.objects,
|
||||||
|
scope = scope,
|
||||||
name = name,
|
name = name,
|
||||||
directory = directory,
|
directory = directory,
|
||||||
scope = scope,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun processNonStringFirstArgument(arg: Any?, vararg args: Any?): NpmDependency {
|
override fun processNonStringFirstArgument(arg: Any?, vararg args: Any?): NpmDependency {
|
||||||
|
|||||||
+2
-1
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName
|
import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinPackageJsonTask
|
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinPackageJsonTask
|
||||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -37,7 +38,7 @@ open class NpmProject(@Transient val compilation: KotlinJsCompilation) : Seriali
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
val nodeJs = project.rootProject.kotlinNodeJsExtension
|
||||||
|
|
||||||
val dir: File by lazy {
|
val dir: File by lazy {
|
||||||
nodeJs.projectPackagesDir.resolve(name)
|
nodeJs.projectPackagesDir.resolve(name)
|
||||||
|
|||||||
+24
-3
@@ -7,13 +7,34 @@ package org.jetbrains.kotlin.gradle.targets.js.npm
|
|||||||
|
|
||||||
import org.gradle.api.Plugin
|
import org.gradle.api.Plugin
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.implementing
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
||||||
|
|
||||||
class NpmResolverPlugin : Plugin<Project> {
|
class NpmResolverPlugin : Plugin<Project> {
|
||||||
override fun apply(target: Project) {
|
override fun apply(project: Project) {
|
||||||
val project = target
|
|
||||||
val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
||||||
nodeJs.npmResolutionManager.requireConfiguringState().addProject(project)
|
project.rootProject.kotlinNodeJsExtension.resolver.addProject(project)
|
||||||
|
val kotlinNodeJsTaskProvidersExtension = project.rootProject.kotlinNodeJsExtension
|
||||||
|
project.whenEvaluated {
|
||||||
|
project.tasks.implementing(RequiresNpmDependencies::class)
|
||||||
|
.configureEach { task ->
|
||||||
|
if (task.enabled) {
|
||||||
|
task as RequiresNpmDependencies
|
||||||
|
// KotlinJsTest delegates npm dependencies to testFramework,
|
||||||
|
// which can be defined after this configure action
|
||||||
|
if (task !is KotlinJsTest) {
|
||||||
|
nodeJs.taskRequirements.addTaskRequirements(task)
|
||||||
|
}
|
||||||
|
task.dependsOn(
|
||||||
|
kotlinNodeJsTaskProvidersExtension.npmInstallTaskProvider,
|
||||||
|
kotlinNodeJsTaskProvidersExtension.storeYarnLockTaskProvider,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+41
-41
@@ -6,33 +6,40 @@
|
|||||||
package org.jetbrains.kotlin.gradle.targets.js.npm
|
package org.jetbrains.kotlin.gradle.targets.js.npm
|
||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
import org.gradle.api.tasks.Input
|
import org.gradle.api.tasks.Input
|
||||||
import org.gradle.api.tasks.Nested
|
import org.gradle.api.tasks.Internal
|
||||||
import org.gradle.api.tasks.OutputFile
|
import org.gradle.api.tasks.OutputFile
|
||||||
import org.gradle.api.tasks.TaskAction
|
import org.gradle.api.tasks.TaskAction
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject.Companion.PACKAGE_JSON
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject.Companion.PACKAGE_JSON
|
||||||
import org.jetbrains.kotlin.gradle.utils.property
|
import org.jetbrains.kotlin.gradle.utils.property
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
open class PublicPackageJsonTask
|
abstract class PublicPackageJsonTask :
|
||||||
@Inject
|
DefaultTask(),
|
||||||
constructor(
|
UsesKotlinNpmResolutionManager {
|
||||||
@Transient
|
|
||||||
private val compilation: KotlinJsCompilation
|
|
||||||
) : DefaultTask() {
|
|
||||||
private val npmProject = compilation.npmProject
|
|
||||||
|
|
||||||
@Transient
|
@get:Internal
|
||||||
private val nodeJs = npmProject.nodeJs
|
abstract val compilationDisambiguatedName: Property<String>
|
||||||
private val resolutionManager = nodeJs.npmResolutionManager
|
|
||||||
|
|
||||||
private val compilationName = compilation.disambiguatedName
|
|
||||||
private val projectPath = project.path
|
private val projectPath = project.path
|
||||||
|
|
||||||
private val packageJsonHandlers = compilation.packageJsonHandlers
|
@get:Input
|
||||||
|
val projectVersion = project.version.toString()
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
abstract val jsIrCompilation: Property<Boolean>
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
abstract val npmProjectName: Property<String>
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
abstract val npmProjectMain: Property<String>
|
||||||
|
|
||||||
|
private val packageJsonHandlers: List<PackageJson.() -> Unit>
|
||||||
|
get() = npmResolutionManager.get().parameters.packageJsonHandlers.get()
|
||||||
|
.getValue("$projectPath:${compilationDisambiguatedName.get()}")
|
||||||
|
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
val packageJsonCustomFields: Map<String, Any?>
|
val packageJsonCustomFields: Map<String, Any?>
|
||||||
@@ -41,47 +48,40 @@ constructor(
|
|||||||
packageJsonHandlers.forEach { it() }
|
packageJsonHandlers.forEach { it() }
|
||||||
}.customFields
|
}.customFields
|
||||||
|
|
||||||
private val compilationResolver
|
|
||||||
get() = resolutionManager.resolver[projectPath][compilationName]
|
|
||||||
|
|
||||||
private val compilationResolution
|
private val compilationResolution
|
||||||
get() = compilationResolver.getResolutionOrResolveIfForced() ?: error("Compilation resolution isn't available")
|
get() = npmResolutionManager.get().resolution.get()[projectPath][compilationDisambiguatedName.get()]
|
||||||
|
.getResolutionOrResolve(
|
||||||
|
npmResolutionManager.get(),
|
||||||
|
logger
|
||||||
|
)
|
||||||
|
|
||||||
@get:Nested
|
@get:Input
|
||||||
internal val externalDependencies: Collection<NpmDependencyDeclaration>
|
val externalDependencies: Collection<NpmDependencyDeclaration>
|
||||||
get() = compilationResolution.externalNpmDependencies
|
get() = compilationResolution.externalNpmDependencies
|
||||||
.map {
|
|
||||||
NpmDependencyDeclaration(
|
|
||||||
scope = it.scope,
|
|
||||||
name = it.name,
|
|
||||||
version = it.version,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val publicPackageJsonTaskName by lazy {
|
|
||||||
npmProject.publicPackageJsonTaskName
|
|
||||||
}
|
|
||||||
|
|
||||||
private val defaultPackageJsonFile by lazy {
|
private val defaultPackageJsonFile by lazy {
|
||||||
project.buildDir
|
project.buildDir
|
||||||
.resolve("tmp")
|
.resolve("tmp")
|
||||||
.resolve(publicPackageJsonTaskName)
|
.resolve(name)
|
||||||
.resolve(PACKAGE_JSON)
|
.resolve(PACKAGE_JSON)
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:OutputFile
|
@get:OutputFile
|
||||||
var packageJsonFile: File by property { defaultPackageJsonFile }
|
var packageJsonFile: File by property { defaultPackageJsonFile }
|
||||||
|
|
||||||
private val isJrIrCompilation = compilation is KotlinJsIrCompilation
|
|
||||||
private val projectVersion = project.version.toString()
|
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun resolve() {
|
fun resolve() {
|
||||||
packageJson(npmProject.name, projectVersion, npmProject.main, externalDependencies, packageJsonHandlers).let { packageJson ->
|
packageJson(
|
||||||
packageJson.main = "${npmProject.name}.js"
|
npmProjectName.get(),
|
||||||
|
projectVersion,
|
||||||
|
npmProjectMain.get(),
|
||||||
|
externalDependencies,
|
||||||
|
packageJsonHandlers
|
||||||
|
).let { packageJson ->
|
||||||
|
packageJson.main = "${npmProjectName}.js"
|
||||||
|
|
||||||
if (isJrIrCompilation) {
|
if (jsIrCompilation.get()) {
|
||||||
packageJson.types = "${npmProject.name}.d.ts"
|
packageJson.types = "${npmProjectName}.d.ts"
|
||||||
}
|
}
|
||||||
|
|
||||||
packageJson.apply {
|
packageJson.apply {
|
||||||
|
|||||||
-1
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
|
|||||||
|
|
||||||
interface RequiresNpmDependencies {
|
interface RequiresNpmDependencies {
|
||||||
val compilation: KotlinJsCompilation
|
val compilation: KotlinJsCompilation
|
||||||
val nodeModulesRequired: Boolean
|
|
||||||
val requiredNpmDependencies: Set<RequiredKotlinJsDependency>
|
val requiredNpmDependencies: Set<RequiredKotlinJsDependency>
|
||||||
|
|
||||||
@Internal
|
@Internal
|
||||||
|
|||||||
-37
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.targets.js.npm.resolved
|
|
||||||
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
|
||||||
import java.io.Serializable
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolved [NpmProject]
|
|
||||||
*/
|
|
||||||
class KotlinCompilationNpmResolution(
|
|
||||||
@Transient
|
|
||||||
private val _project: Project?,
|
|
||||||
val npmProject: NpmProject,
|
|
||||||
val internalCompositeDependencies: Collection<GradleNodeModule>,
|
|
||||||
val externalGradleDependencies: Collection<GradleNodeModule>,
|
|
||||||
private val _externalNpmDependencies: Collection<NpmDependencyDeclaration>,
|
|
||||||
val packageJson: PackageJson
|
|
||||||
) : Serializable {
|
|
||||||
val project
|
|
||||||
get() = _project!!
|
|
||||||
|
|
||||||
val externalNpmDependencies
|
|
||||||
get() = _externalNpmDependencies
|
|
||||||
.map {
|
|
||||||
NpmDependency(
|
|
||||||
project = _project,
|
|
||||||
name = it.name,
|
|
||||||
version = it.version,
|
|
||||||
scope = it.scope,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+7
-22
@@ -5,35 +5,20 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.targets.js.npm.resolved
|
package org.jetbrains.kotlin.gradle.targets.js.npm.resolved
|
||||||
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinCompilationNpmResolution
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency
|
import java.io.Serializable
|
||||||
|
|
||||||
/**
|
|
||||||
* Info about NPM projects inside particular gradle [project].
|
|
||||||
*/
|
|
||||||
class KotlinProjectNpmResolution(
|
class KotlinProjectNpmResolution(
|
||||||
val project: String,
|
val byCompilation: Map<String, KotlinCompilationNpmResolution>,
|
||||||
val npmProjects: List<KotlinCompilationNpmResolution>,
|
) : Serializable {
|
||||||
val taskRequirements: Map<String, Collection<RequiredKotlinJsDependency>>
|
val npmProjects: Collection<KotlinCompilationNpmResolution>
|
||||||
) {
|
get() = byCompilation.values
|
||||||
val npmProjectsByNpmDependency: Map<NpmDependency, KotlinCompilationNpmResolution> by lazy {
|
|
||||||
mutableMapOf<NpmDependency, KotlinCompilationNpmResolution>().also { result ->
|
|
||||||
npmProjects.forEach { npmPackage ->
|
|
||||||
npmPackage.externalNpmDependencies.forEach { npmDependency ->
|
|
||||||
result[npmDependency] = npmPackage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val byCompilation by lazy { npmProjects.associateBy { it.npmProject.compilationName } }
|
|
||||||
|
|
||||||
operator fun get(compilationName: String): KotlinCompilationNpmResolution {
|
operator fun get(compilationName: String): KotlinCompilationNpmResolution {
|
||||||
// check(compilation.target.project.path == project)
|
|
||||||
return byCompilation.getValue(compilationName)
|
return byCompilation.getValue(compilationName)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun empty(project: String) = KotlinProjectNpmResolution(project, listOf(), mapOf())
|
fun empty() = KotlinProjectNpmResolution(emptyMap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+64
-6
@@ -5,11 +5,69 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.targets.js.npm.resolved
|
package org.jetbrains.kotlin.gradle.targets.js.npm.resolved
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.logging.Logger
|
||||||
|
import org.gradle.internal.service.ServiceRegistry
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmEnvironment
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.YarnEnvironment
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.toVersionString
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
internal class KotlinRootNpmResolution(
|
class KotlinRootNpmResolution(
|
||||||
val rootProject: Project?,
|
val projects: Map<String, KotlinProjectNpmResolution>,
|
||||||
internal val projects: Map<String, KotlinProjectNpmResolution>
|
val rootProjectName: String,
|
||||||
) {
|
val rootProjectVersion: String
|
||||||
operator fun get(project: String) = projects[project] ?: KotlinProjectNpmResolution.empty(project)
|
) : Serializable {
|
||||||
|
operator fun get(project: String) = projects[project] ?: KotlinProjectNpmResolution.empty()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't use directly, use [KotlinNpmResolutionManager.installIfNeeded] instead.
|
||||||
|
*/
|
||||||
|
internal fun prepareInstallation(
|
||||||
|
logger: Logger,
|
||||||
|
npmEnvironment: NpmEnvironment,
|
||||||
|
yarnEnvironment: YarnEnvironment,
|
||||||
|
npmResolutionManager: KotlinNpmResolutionManager
|
||||||
|
): Installation {
|
||||||
|
synchronized(projects) {
|
||||||
|
npmResolutionManager.parameters.gradleNodeModulesProvider.get().close()
|
||||||
|
npmResolutionManager.parameters.compositeNodeModulesProvider.get().close()
|
||||||
|
|
||||||
|
val projectResolutions: List<PreparedKotlinCompilationNpmResolution> = projects.values.flatMap { it.npmProjects }.map { it.close(npmResolutionManager, logger) }
|
||||||
|
npmEnvironment.packageManager.prepareRootProject(
|
||||||
|
npmEnvironment,
|
||||||
|
rootProjectName,
|
||||||
|
rootProjectVersion,
|
||||||
|
logger,
|
||||||
|
projectResolutions,
|
||||||
|
yarnEnvironment.yarnResolutions
|
||||||
|
.associate { it.path to it.toVersionString() },
|
||||||
|
)
|
||||||
|
|
||||||
|
return Installation(
|
||||||
|
projectResolutions
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Installation(val compilationResolutions: Collection<PreparedKotlinCompilationNpmResolution>) {
|
||||||
|
internal fun install(
|
||||||
|
args: List<String>,
|
||||||
|
services: ServiceRegistry,
|
||||||
|
logger: Logger,
|
||||||
|
npmEnvironment: NpmEnvironment,
|
||||||
|
yarnEnvironment: YarnEnvironment,
|
||||||
|
) {
|
||||||
|
synchronized(compilationResolutions) {
|
||||||
|
npmEnvironment.packageManager.resolveRootProject(
|
||||||
|
services,
|
||||||
|
logger,
|
||||||
|
npmEnvironment,
|
||||||
|
yarnEnvironment,
|
||||||
|
compilationResolutions,
|
||||||
|
args
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.targets.js.npm.resolved
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
||||||
|
import java.io.File
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolved [NpmProject]
|
||||||
|
*/
|
||||||
|
class PreparedKotlinCompilationNpmResolution(
|
||||||
|
val npmProjectDir: File,
|
||||||
|
val internalCompositeDependencies: Collection<GradleNodeModule>,
|
||||||
|
val externalGradleDependencies: Collection<GradleNodeModule>,
|
||||||
|
val externalNpmDependencies: Collection<NpmDependencyDeclaration>,
|
||||||
|
) : Serializable
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.ResolvedArtifact
|
||||||
|
import org.gradle.api.artifacts.ResolvedDependency
|
||||||
|
import org.gradle.api.initialization.IncludedBuild
|
||||||
|
import java.io.File
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
data class ExternalGradleDependency(
|
||||||
|
val dependency: ResolvedDependency,
|
||||||
|
val artifact: ResolvedArtifact
|
||||||
|
) : Serializable
|
||||||
|
|
||||||
|
data class FileCollectionExternalGradleDependency(
|
||||||
|
val files: Collection<File>,
|
||||||
|
val dependencyVersion: String?
|
||||||
|
) : Serializable
|
||||||
|
|
||||||
|
data class FileExternalGradleDependency(
|
||||||
|
val dependencyName: String,
|
||||||
|
val dependencyVersion: String,
|
||||||
|
val file: File
|
||||||
|
) : Serializable
|
||||||
|
|
||||||
|
data class CompositeDependency(
|
||||||
|
val dependencyName: String,
|
||||||
|
val dependencyVersion: String,
|
||||||
|
val includedBuildDir: File,
|
||||||
|
@Transient
|
||||||
|
val includedBuild: IncludedBuild?
|
||||||
|
) : Serializable
|
||||||
|
|
||||||
|
data class InternalDependency(
|
||||||
|
val projectPath: String,
|
||||||
|
val compilationName: String,
|
||||||
|
val projectName: String
|
||||||
|
) : Serializable
|
||||||
+201
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.logging.Logger
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.TasksRequirements
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject.Companion.PACKAGE_JSON
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.PreparedKotlinCompilationNpmResolution
|
||||||
|
import java.io.Serializable
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class KotlinCompilationNpmResolution(
|
||||||
|
var internalDependencies: Collection<InternalDependency>,
|
||||||
|
var internalCompositeDependencies: Collection<CompositeDependency>,
|
||||||
|
var externalGradleDependencies: Collection<FileExternalGradleDependency>,
|
||||||
|
var externalNpmDependencies: Collection<NpmDependencyDeclaration>,
|
||||||
|
var fileCollectionDependencies: Collection<FileCollectionExternalGradleDependency>,
|
||||||
|
val projectPath: String,
|
||||||
|
val projectPackagesDir: File,
|
||||||
|
val rootDir: File,
|
||||||
|
val compilationDisambiguatedName: String,
|
||||||
|
val npmProjectName: String,
|
||||||
|
val npmProjectVersion: String,
|
||||||
|
val npmProjectMain: String,
|
||||||
|
val npmProjectPackageJsonFile: File,
|
||||||
|
val npmProjectDir: File,
|
||||||
|
val tasksRequirements: TasksRequirements
|
||||||
|
) : Serializable {
|
||||||
|
|
||||||
|
val inputs: PackageJsonProducerInputs
|
||||||
|
get() = PackageJsonProducerInputs(
|
||||||
|
internalDependencies.map { it.projectName },
|
||||||
|
internalCompositeDependencies.flatMap { it.getPackages() },
|
||||||
|
externalGradleDependencies.map { it.file },
|
||||||
|
externalNpmDependencies.map { it.uniqueRepresentation() },
|
||||||
|
fileCollectionDependencies.flatMap { it.files }
|
||||||
|
)
|
||||||
|
|
||||||
|
private var closed = false
|
||||||
|
private var resolution: PreparedKotlinCompilationNpmResolution? = null
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun resolve(
|
||||||
|
skipWriting: Boolean = false,
|
||||||
|
npmResolutionManager: KotlinNpmResolutionManager,
|
||||||
|
logger: Logger
|
||||||
|
): PreparedKotlinCompilationNpmResolution {
|
||||||
|
check(resolution == null) { "$this already resolved" }
|
||||||
|
|
||||||
|
return createPackageJson(
|
||||||
|
skipWriting,
|
||||||
|
npmResolutionManager,
|
||||||
|
logger
|
||||||
|
).also {
|
||||||
|
resolution = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun getResolutionOrResolve(
|
||||||
|
npmResolutionManager: KotlinNpmResolutionManager,
|
||||||
|
logger: Logger,
|
||||||
|
): PreparedKotlinCompilationNpmResolution {
|
||||||
|
|
||||||
|
return resolution ?: resolve(
|
||||||
|
skipWriting = true,
|
||||||
|
npmResolutionManager,
|
||||||
|
logger
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun close(
|
||||||
|
npmResolutionManager: KotlinNpmResolutionManager,
|
||||||
|
logger: Logger,
|
||||||
|
): PreparedKotlinCompilationNpmResolution {
|
||||||
|
check(!closed) { "$this already closed" }
|
||||||
|
closed = true
|
||||||
|
return getResolutionOrResolve(npmResolutionManager, logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createPackageJson(
|
||||||
|
skipWriting: Boolean,
|
||||||
|
npmResolutionManager: KotlinNpmResolutionManager,
|
||||||
|
logger: Logger
|
||||||
|
): PreparedKotlinCompilationNpmResolution {
|
||||||
|
val rootResolver = npmResolutionManager.parameters.resolution.get()
|
||||||
|
|
||||||
|
internalDependencies.map {
|
||||||
|
val compilationNpmResolution: KotlinCompilationNpmResolution = rootResolver[it.projectPath][it.compilationName]
|
||||||
|
compilationNpmResolution.getResolutionOrResolve(
|
||||||
|
npmResolutionManager,
|
||||||
|
logger
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val importedExternalGradleDependencies = externalGradleDependencies.mapNotNull {
|
||||||
|
npmResolutionManager.parameters.gradleNodeModulesProvider.get().get(it.dependencyName, it.dependencyVersion, it.file)
|
||||||
|
} + fileCollectionDependencies.flatMap { dependency ->
|
||||||
|
dependency.files
|
||||||
|
// Gradle can hash with FileHasher only files and only existed files
|
||||||
|
.filter { it.isFile }
|
||||||
|
.map { file ->
|
||||||
|
npmResolutionManager.parameters.gradleNodeModulesProvider.get().get(
|
||||||
|
file.name,
|
||||||
|
dependency.dependencyVersion ?: "0.0.1",
|
||||||
|
file
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.filterNotNull()
|
||||||
|
val transitiveNpmDependencies = importedExternalGradleDependencies.flatMap {
|
||||||
|
it.dependencies
|
||||||
|
}.filter { it.scope != NpmDependency.Scope.DEV }
|
||||||
|
|
||||||
|
val compositeDependencies = internalCompositeDependencies.flatMap { dependency ->
|
||||||
|
dependency.getPackages()
|
||||||
|
.map { file ->
|
||||||
|
npmResolutionManager.parameters.compositeNodeModulesProvider.get().get(
|
||||||
|
dependency.dependencyName,
|
||||||
|
dependency.dependencyVersion,
|
||||||
|
file
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.filterNotNull()
|
||||||
|
|
||||||
|
val toolsNpmDependencies = tasksRequirements
|
||||||
|
.getCompilationNpmRequirements(projectPath, compilationDisambiguatedName)
|
||||||
|
|
||||||
|
val otherNpmDependencies = toolsNpmDependencies + transitiveNpmDependencies
|
||||||
|
val allNpmDependencies = disambiguateDependencies(externalNpmDependencies, otherNpmDependencies, logger)
|
||||||
|
val packageJsonHandlers =
|
||||||
|
npmResolutionManager.parameters.packageJsonHandlers.get()["$projectPath:${compilationDisambiguatedName}"]
|
||||||
|
?: emptyList()
|
||||||
|
|
||||||
|
val packageJson = packageJson(
|
||||||
|
npmProjectName,
|
||||||
|
npmProjectVersion,
|
||||||
|
npmProjectMain,
|
||||||
|
allNpmDependencies,
|
||||||
|
packageJsonHandlers
|
||||||
|
)
|
||||||
|
|
||||||
|
compositeDependencies.forEach {
|
||||||
|
packageJson.dependencies[it.name] = it.version
|
||||||
|
}
|
||||||
|
|
||||||
|
packageJsonHandlers.forEach {
|
||||||
|
it(packageJson)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skipWriting) {
|
||||||
|
packageJson.saveTo(npmProjectPackageJsonFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
return PreparedKotlinCompilationNpmResolution(
|
||||||
|
npmProjectDir,
|
||||||
|
compositeDependencies,
|
||||||
|
importedExternalGradleDependencies,
|
||||||
|
allNpmDependencies,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun disambiguateDependencies(
|
||||||
|
direct: Collection<NpmDependencyDeclaration>,
|
||||||
|
others: Collection<NpmDependencyDeclaration>,
|
||||||
|
logger: Logger,
|
||||||
|
): Collection<NpmDependencyDeclaration> {
|
||||||
|
val unique = others.groupBy(NpmDependencyDeclaration::name)
|
||||||
|
.filterKeys { k -> direct.none { it.name == k } }
|
||||||
|
.mapNotNull { (name, dependencies) ->
|
||||||
|
dependencies.maxByOrNull { dep ->
|
||||||
|
SemVer.from(dep.version, true)
|
||||||
|
}?.also { selected ->
|
||||||
|
if (dependencies.size > 1) {
|
||||||
|
logger.warn(
|
||||||
|
"""
|
||||||
|
Transitive npm dependency version clash for compilation "${compilationDisambiguatedName}"
|
||||||
|
Candidates:
|
||||||
|
${dependencies.joinToString("\n") { "\t\t" + it.name + "@" + it.version }}
|
||||||
|
Selected:
|
||||||
|
${selected.name}@${selected.version}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return direct + unique
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun CompositeDependency.getPackages(): List<File> {
|
||||||
|
val packages = includedBuildDir.resolve(projectPackagesDir.relativeTo(rootDir))
|
||||||
|
return packages
|
||||||
|
.list()
|
||||||
|
?.map { packages.resolve(it) }
|
||||||
|
?.map { it.resolve(PACKAGE_JSON) }
|
||||||
|
?: emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
+48
-268
@@ -12,12 +12,9 @@ import org.gradle.api.artifacts.ResolvedDependency
|
|||||||
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
||||||
import org.gradle.api.attributes.Category
|
import org.gradle.api.attributes.Category
|
||||||
import org.gradle.api.attributes.Usage
|
import org.gradle.api.attributes.Usage
|
||||||
import org.gradle.api.initialization.IncludedBuild
|
|
||||||
import org.gradle.api.internal.artifacts.DefaultProjectComponentIdentifier
|
import org.gradle.api.internal.artifacts.DefaultProjectComponentIdentifier
|
||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.TaskProvider
|
||||||
import org.gradle.api.tasks.bundling.Zip
|
import org.gradle.api.tasks.bundling.Zip
|
||||||
import org.gradle.configurationcache.extensions.serviceOf
|
|
||||||
import org.gradle.work.NormalizeLineEndings
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.categoryByName
|
import org.jetbrains.kotlin.gradle.plugin.categoryByName
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
@@ -28,29 +25,24 @@ import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.sources.compilationDependencyConfigurationByScope
|
import org.jetbrains.kotlin.gradle.plugin.sources.compilationDependencyConfigurationByScope
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
|
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
|
||||||
import org.jetbrains.kotlin.gradle.plugin.usesPlatformOf
|
import org.jetbrains.kotlin.gradle.plugin.usesPlatformOf
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
|
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNpmResolutionManager
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject.Companion.PACKAGE_JSON
|
|
||||||
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.tasks.KotlinPackageJsonTask
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
import org.jetbrains.kotlin.gradle.utils.CompositeProjectComponentArtifactMetadata
|
import org.jetbrains.kotlin.gradle.utils.CompositeProjectComponentArtifactMetadata
|
||||||
import org.jetbrains.kotlin.gradle.utils.`is`
|
import org.jetbrains.kotlin.gradle.utils.`is`
|
||||||
import org.jetbrains.kotlin.gradle.utils.topRealPath
|
import org.jetbrains.kotlin.gradle.utils.topRealPath
|
||||||
import org.jetbrains.kotlin.gradle.utils.unavailableValueError
|
|
||||||
import java.io.File
|
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See [KotlinNpmResolutionManager] for details about resolution process.
|
* See [KotlinNpmResolutionManager] for details about resolution process.
|
||||||
*/
|
*/
|
||||||
internal class KotlinCompilationNpmResolver(
|
class KotlinCompilationNpmResolver(
|
||||||
@Transient
|
|
||||||
val projectResolver: KotlinProjectNpmResolver,
|
val projectResolver: KotlinProjectNpmResolver,
|
||||||
@Transient
|
|
||||||
val compilation: KotlinJsCompilation
|
val compilation: KotlinJsCompilation
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
@Transient
|
|
||||||
var rootResolver = projectResolver.resolver
|
var rootResolver = projectResolver.resolver
|
||||||
|
|
||||||
val npmProject = compilation.npmProject
|
val npmProject = compilation.npmProject
|
||||||
@@ -61,26 +53,32 @@ internal class KotlinCompilationNpmResolver(
|
|||||||
project.version.toString()
|
project.version.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
val nodeJs get() = rootResolver.nodeJs
|
|
||||||
private val nodeJs_ get() = nodeJs ?: unavailableValueError("nodeJs")
|
|
||||||
|
|
||||||
val target get() = compilation.target
|
val target get() = compilation.target
|
||||||
|
|
||||||
val project get() = target.project
|
val project get() = target.project
|
||||||
|
|
||||||
val projectPath = project.path
|
val projectPath: String = project.path
|
||||||
|
|
||||||
@Transient
|
val packageJsonTaskHolder: TaskProvider<KotlinPackageJsonTask> =
|
||||||
val packageJsonTaskHolder: TaskProvider<KotlinPackageJsonTask>? =
|
|
||||||
KotlinPackageJsonTask.create(compilation)
|
KotlinPackageJsonTask.create(compilation)
|
||||||
|
|
||||||
@Transient
|
val publicPackageJsonTaskHolder: TaskProvider<PublicPackageJsonTask> = run {
|
||||||
val publicPackageJsonTaskHolder: TaskProvider<PublicPackageJsonTask> =
|
val npmResolutionManager = project.kotlinNpmResolutionManager
|
||||||
project.registerTask<PublicPackageJsonTask>(
|
project.registerTask<PublicPackageJsonTask>(
|
||||||
npmProject.publicPackageJsonTaskName,
|
npmProject.publicPackageJsonTaskName
|
||||||
listOf(compilation)
|
|
||||||
) {
|
) {
|
||||||
it.dependsOn(packageJsonTaskHolder)
|
it.dependsOn(packageJsonTaskHolder)
|
||||||
|
|
||||||
|
it.compilationDisambiguatedName.set(compilation.disambiguatedName)
|
||||||
|
|
||||||
|
it.npmResolutionManager.apply {
|
||||||
|
set(npmResolutionManager)
|
||||||
|
disallowChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
it.jsIrCompilation.set(compilation is KotlinJsIrCompilation)
|
||||||
|
it.npmProjectName.set(npmProject.name)
|
||||||
|
it.npmProjectMain.set(npmProject.main)
|
||||||
}.also { packageJsonTask ->
|
}.also { packageJsonTask ->
|
||||||
if (compilation.isMain()) {
|
if (compilation.isMain()) {
|
||||||
project.tasks
|
project.tasks
|
||||||
@@ -91,66 +89,29 @@ internal class KotlinCompilationNpmResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString(): String = "KotlinCompilationNpmResolver(${npmProject.name})"
|
override fun toString(): String = "KotlinCompilationNpmResolver(${npmProject.name})"
|
||||||
|
|
||||||
@delegate:Transient
|
private var _compilationNpmResolution: KotlinCompilationNpmResolution? = null
|
||||||
private val aggregatedConfiguration: Configuration by lazy {
|
|
||||||
createAggregatedConfiguration()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val packageJsonProducer_: PackageJsonProducer by lazy {
|
val compilationNpmResolution: KotlinCompilationNpmResolution
|
||||||
val visitor = ConfigurationVisitor()
|
|
||||||
visitor.visit(aggregatedConfiguration)
|
|
||||||
visitor.toPackageJsonProducer().also { it.compilationResolver = this }
|
|
||||||
}
|
|
||||||
|
|
||||||
val packageJsonProducer: PackageJsonProducer
|
|
||||||
get() {
|
get() {
|
||||||
val packageJsonProducer = packageJsonProducer_
|
return _compilationNpmResolution ?: run {
|
||||||
packageJsonProducer.compilationResolver = this
|
val visitor = ConfigurationVisitor()
|
||||||
return packageJsonProducer
|
visitor.visit(createAggregatedConfiguration())
|
||||||
|
visitor.toPackageJsonProducer()
|
||||||
|
}.also {
|
||||||
|
_compilationNpmResolution = it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var closed = false
|
|
||||||
private var resolution: KotlinCompilationNpmResolution? = null
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
fun resolve(skipWriting: Boolean = false): KotlinCompilationNpmResolution {
|
|
||||||
check(!closed) { "$this already closed" }
|
|
||||||
check(resolution == null) { "$this already resolved" }
|
|
||||||
|
|
||||||
return packageJsonProducer.createPackageJson(skipWriting).also {
|
|
||||||
resolution = it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
fun getResolutionOrResolveIfForced(): KotlinCompilationNpmResolution? {
|
|
||||||
if (resolution != null) return resolution
|
|
||||||
if (rootResolver.mayBeUpToDateTasksRegistry.get().shouldResolveNpmDependenciesFor(npmProject.packageJsonTaskPath)) {
|
|
||||||
// when we need to resolve the compilation but the task is UP-TO-DATE, so we don't have ready resolution yet
|
|
||||||
return resolve(skipWriting = true)
|
|
||||||
}
|
|
||||||
if (rootResolver.forceFullResolve) {
|
|
||||||
// need to force all NPM tasks to be configured in IDEA import
|
|
||||||
rootResolver.gradleNodeModules.fileHasher = project.serviceOf()
|
|
||||||
rootResolver.compositeNodeModules.fileHasher = project.serviceOf()
|
|
||||||
project.tasks.implementing(RequiresNpmDependencies::class).all {}
|
|
||||||
return resolve()
|
|
||||||
}
|
|
||||||
return null // we don't need to resolve NPM dependencies for the compilation
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun close(): KotlinCompilationNpmResolution? {
|
fun close(): KotlinCompilationNpmResolution? {
|
||||||
check(!closed) { "$this already closed" }
|
return _compilationNpmResolution
|
||||||
val resolution = getResolutionOrResolveIfForced()
|
|
||||||
closed = true
|
|
||||||
return resolution
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createAggregatedConfiguration(): Configuration {
|
fun createAggregatedConfiguration(): Configuration {
|
||||||
val all = project.configurations.create(compilation.disambiguateName("npm"))
|
val all = project.configurations.create(compilation.disambiguateName("npm"))
|
||||||
|
|
||||||
all.usesPlatformOf(target)
|
all.usesPlatformOf(target)
|
||||||
@@ -174,46 +135,16 @@ internal class KotlinCompilationNpmResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We don't have `kotlin-js-test-runner` in NPM yet
|
// We don't have `kotlin-js-test-runner` in NPM yet
|
||||||
all.dependencies.add(nodeJs_.versions.kotlinJsTestRunner.createDependency(project))
|
all.dependencies.add(rootResolver.versions.kotlinJsTestRunner.createDependency(project))
|
||||||
|
|
||||||
return all
|
return all
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ExternalGradleDependency(
|
|
||||||
val dependency: ResolvedDependency,
|
|
||||||
val artifact: ResolvedArtifact
|
|
||||||
) : Serializable
|
|
||||||
|
|
||||||
data class FileCollectionExternalGradleDependency(
|
|
||||||
val files: Collection<File>,
|
|
||||||
val dependencyVersion: String?
|
|
||||||
) : Serializable
|
|
||||||
|
|
||||||
data class FileExternalGradleDependency(
|
|
||||||
val dependencyName: String,
|
|
||||||
val dependencyVersion: String,
|
|
||||||
val file: File
|
|
||||||
) : Serializable
|
|
||||||
|
|
||||||
data class CompositeDependency(
|
|
||||||
val dependencyName: String,
|
|
||||||
val dependencyVersion: String,
|
|
||||||
val includedBuildDir: File,
|
|
||||||
@Transient
|
|
||||||
val includedBuild: IncludedBuild?
|
|
||||||
) : Serializable
|
|
||||||
|
|
||||||
data class InternalDependency(
|
|
||||||
val projectPath: String,
|
|
||||||
val compilationName: String,
|
|
||||||
val projectName: String
|
|
||||||
) : Serializable
|
|
||||||
|
|
||||||
inner class ConfigurationVisitor {
|
inner class ConfigurationVisitor {
|
||||||
private val internalDependencies = mutableSetOf<InternalDependency>()
|
private val internalDependencies = mutableSetOf<InternalDependency>()
|
||||||
private val internalCompositeDependencies = mutableSetOf<CompositeDependency>()
|
private val internalCompositeDependencies = mutableSetOf<CompositeDependency>()
|
||||||
private val externalGradleDependencies = mutableSetOf<ExternalGradleDependency>()
|
private val externalGradleDependencies = mutableSetOf<ExternalGradleDependency>()
|
||||||
private val externalNpmDependencies = mutableSetOf<NpmDependency>()
|
private val externalNpmDependencies = mutableSetOf<NpmDependencyDeclaration>()
|
||||||
private val fileCollectionDependencies = mutableSetOf<FileCollectionExternalGradleDependency>()
|
private val fileCollectionDependencies = mutableSetOf<FileCollectionExternalGradleDependency>()
|
||||||
|
|
||||||
private val visitedDependencies = mutableSetOf<ResolvedDependency>()
|
private val visitedDependencies = mutableSetOf<ResolvedDependency>()
|
||||||
@@ -225,7 +156,7 @@ internal class KotlinCompilationNpmResolver(
|
|||||||
|
|
||||||
configuration.allDependencies.forEach { dependency ->
|
configuration.allDependencies.forEach { dependency ->
|
||||||
when (dependency) {
|
when (dependency) {
|
||||||
is NpmDependency -> externalNpmDependencies.add(dependency)
|
is NpmDependency -> externalNpmDependencies.add(dependency.toDeclaration())
|
||||||
is FileCollectionDependency -> fileCollectionDependencies.add(
|
is FileCollectionDependency -> fileCollectionDependencies.add(
|
||||||
FileCollectionExternalGradleDependency(
|
FileCollectionExternalGradleDependency(
|
||||||
dependency.files.files,
|
dependency.files.files,
|
||||||
@@ -240,7 +171,7 @@ internal class KotlinCompilationNpmResolver(
|
|||||||
val main = compilation.target.compilations.findByName(KotlinCompilation.MAIN_COMPILATION_NAME) as KotlinJsCompilation
|
val main = compilation.target.compilations.findByName(KotlinCompilation.MAIN_COMPILATION_NAME) as KotlinJsCompilation
|
||||||
internalDependencies.add(
|
internalDependencies.add(
|
||||||
InternalDependency(
|
InternalDependency(
|
||||||
projectResolver.project.path,
|
projectResolver.projectPath,
|
||||||
main.disambiguatedName,
|
main.disambiguatedName,
|
||||||
projectResolver[main].npmProject.name
|
projectResolver[main].npmProject.name
|
||||||
)
|
)
|
||||||
@@ -336,7 +267,7 @@ internal class KotlinCompilationNpmResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toPackageJsonProducer() = PackageJsonProducer(
|
fun toPackageJsonProducer() = KotlinCompilationNpmResolution(
|
||||||
internalDependencies,
|
internalDependencies,
|
||||||
internalCompositeDependencies,
|
internalCompositeDependencies,
|
||||||
externalGradleDependencies.map {
|
externalGradleDependencies.map {
|
||||||
@@ -346,169 +277,18 @@ internal class KotlinCompilationNpmResolver(
|
|||||||
it.artifact.file
|
it.artifact.file
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
externalNpmDependencies.map { it.toDeclaration() },
|
externalNpmDependencies,
|
||||||
fileCollectionDependencies,
|
fileCollectionDependencies,
|
||||||
projectPath
|
projectPath,
|
||||||
|
rootResolver.projectPackagesDir,
|
||||||
|
rootResolver.rootProjectDir,
|
||||||
|
compilationDisambiguatedName,
|
||||||
|
npmProject.name,
|
||||||
|
npmVersion,
|
||||||
|
npmProject.main,
|
||||||
|
npmProject.packageJsonFile,
|
||||||
|
npmProject.dir,
|
||||||
|
rootResolver.tasksRequirements
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
class PackageJsonProducerInputs(
|
|
||||||
@get:Input
|
|
||||||
val internalDependencies: Collection<String>,
|
|
||||||
|
|
||||||
@get:PathSensitive(PathSensitivity.ABSOLUTE)
|
|
||||||
@get:IgnoreEmptyDirectories
|
|
||||||
@get:NormalizeLineEndings
|
|
||||||
@get:InputFiles
|
|
||||||
val internalCompositeDependencies: Collection<File>,
|
|
||||||
|
|
||||||
@get:PathSensitive(PathSensitivity.ABSOLUTE)
|
|
||||||
@get:IgnoreEmptyDirectories
|
|
||||||
@get:NormalizeLineEndings
|
|
||||||
@get:InputFiles
|
|
||||||
val externalGradleDependencies: Collection<File>,
|
|
||||||
|
|
||||||
@get:Input
|
|
||||||
val externalDependencies: Collection<String>,
|
|
||||||
|
|
||||||
@get:Input
|
|
||||||
val fileCollectionDependencies: Collection<File>
|
|
||||||
)
|
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
|
||||||
class PackageJsonProducer(
|
|
||||||
var internalDependencies: Collection<InternalDependency>,
|
|
||||||
var internalCompositeDependencies: Collection<CompositeDependency>,
|
|
||||||
var externalGradleDependencies: Collection<FileExternalGradleDependency>,
|
|
||||||
var externalNpmDependencies: Collection<NpmDependencyDeclaration>,
|
|
||||||
var fileCollectionDependencies: Collection<FileCollectionExternalGradleDependency>,
|
|
||||||
val projectPath: String
|
|
||||||
) : Serializable {
|
|
||||||
private val projectPackagesDir by lazy { compilationResolver.nodeJs_.projectPackagesDir }
|
|
||||||
private val rootDir by lazy { compilationResolver.nodeJs_.rootProject.rootDir }
|
|
||||||
|
|
||||||
@Transient
|
|
||||||
internal lateinit var compilationResolver: KotlinCompilationNpmResolver
|
|
||||||
|
|
||||||
val inputs: PackageJsonProducerInputs
|
|
||||||
get() = PackageJsonProducerInputs(
|
|
||||||
internalDependencies.map { it.projectName },
|
|
||||||
internalCompositeDependencies.flatMap { it.getPackages() },
|
|
||||||
externalGradleDependencies.map { it.file },
|
|
||||||
externalNpmDependencies.map { it.uniqueRepresentation() },
|
|
||||||
fileCollectionDependencies.flatMap { it.files }
|
|
||||||
)
|
|
||||||
|
|
||||||
fun createPackageJson(skipWriting: Boolean): KotlinCompilationNpmResolution {
|
|
||||||
internalDependencies.map {
|
|
||||||
compilationResolver.rootResolver[it.projectPath][it.compilationName].getResolutionOrResolveIfForced()
|
|
||||||
?: error("Unresolved dependent npm package: ${compilationResolver} -> $it")
|
|
||||||
}
|
|
||||||
val importedExternalGradleDependencies = externalGradleDependencies.mapNotNull {
|
|
||||||
compilationResolver.rootResolver.gradleNodeModules.get(it.dependencyName, it.dependencyVersion, it.file)
|
|
||||||
} + fileCollectionDependencies.flatMap { dependency ->
|
|
||||||
dependency.files
|
|
||||||
// Gradle can hash with FileHasher only files and only existed files
|
|
||||||
.filter { it.isFile }
|
|
||||||
.map { file ->
|
|
||||||
compilationResolver.rootResolver.gradleNodeModules.get(
|
|
||||||
file.name,
|
|
||||||
dependency.dependencyVersion ?: "0.0.1",
|
|
||||||
file
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}.filterNotNull()
|
|
||||||
val transitiveNpmDependencies = importedExternalGradleDependencies.flatMap {
|
|
||||||
it.dependencies
|
|
||||||
}.filter { it.scope != NpmDependency.Scope.DEV }
|
|
||||||
|
|
||||||
val compositeDependencies = internalCompositeDependencies.flatMap { dependency ->
|
|
||||||
dependency.getPackages()
|
|
||||||
.map { file ->
|
|
||||||
compilationResolver.rootResolver.compositeNodeModules.get(
|
|
||||||
dependency.dependencyName,
|
|
||||||
dependency.dependencyVersion,
|
|
||||||
file
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}.filterNotNull()
|
|
||||||
|
|
||||||
val toolsNpmDependencies = compilationResolver.rootResolver.taskRequirements
|
|
||||||
.getCompilationNpmRequirements(projectPath, compilationResolver.compilationDisambiguatedName)
|
|
||||||
|
|
||||||
val otherNpmDependencies = toolsNpmDependencies + transitiveNpmDependencies
|
|
||||||
val allNpmDependencies = disambiguateDependencies(externalNpmDependencies, otherNpmDependencies)
|
|
||||||
val packageJsonHandlers = if (compilationResolver.compilation != null) {
|
|
||||||
compilationResolver.compilation.packageJsonHandlers
|
|
||||||
} else {
|
|
||||||
compilationResolver.rootResolver.getPackageJsonHandlers(projectPath, compilationResolver.compilationDisambiguatedName)
|
|
||||||
}
|
|
||||||
|
|
||||||
val packageJson = packageJson(
|
|
||||||
compilationResolver.npmProject.name,
|
|
||||||
compilationResolver.npmVersion,
|
|
||||||
compilationResolver.npmProject.main,
|
|
||||||
allNpmDependencies,
|
|
||||||
packageJsonHandlers
|
|
||||||
)
|
|
||||||
|
|
||||||
compositeDependencies.forEach {
|
|
||||||
packageJson.dependencies[it.name] = it.version
|
|
||||||
}
|
|
||||||
|
|
||||||
packageJsonHandlers.forEach {
|
|
||||||
it(packageJson)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!skipWriting) {
|
|
||||||
packageJson.saveTo(compilationResolver.npmProject.packageJsonFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
return KotlinCompilationNpmResolution(
|
|
||||||
@Suppress("SENSELESS_COMPARISON")
|
|
||||||
if (compilationResolver.compilation != null) compilationResolver.project else null,
|
|
||||||
compilationResolver.npmProject,
|
|
||||||
compositeDependencies,
|
|
||||||
importedExternalGradleDependencies,
|
|
||||||
allNpmDependencies,
|
|
||||||
packageJson
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun disambiguateDependencies(
|
|
||||||
direct: Collection<NpmDependencyDeclaration>,
|
|
||||||
others: Collection<NpmDependencyDeclaration>,
|
|
||||||
): Collection<NpmDependencyDeclaration> {
|
|
||||||
val unique = others.groupBy(NpmDependencyDeclaration::name)
|
|
||||||
.filterKeys { k -> direct.none { it.name == k } }
|
|
||||||
.mapNotNull { (name, dependencies) ->
|
|
||||||
dependencies.maxByOrNull { dep ->
|
|
||||||
SemVer.from(dep.version, true)
|
|
||||||
}?.also { selected ->
|
|
||||||
if (dependencies.size > 1) {
|
|
||||||
compilationResolver.project.logger.warn(
|
|
||||||
"""
|
|
||||||
Transitive npm dependency version clash for compilation "${compilationResolver.compilation.name}"
|
|
||||||
Candidates:
|
|
||||||
${dependencies.joinToString("\n") { "\t\t" + it.name + "@" + it.version }}
|
|
||||||
Selected:
|
|
||||||
${selected.name}@${selected.version}
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return direct + unique
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun CompositeDependency.getPackages(): List<File> {
|
|
||||||
val packages = includedBuildDir.resolve(projectPackagesDir.relativeTo(rootDir))
|
|
||||||
return packages
|
|
||||||
.list()
|
|
||||||
?.map { packages.resolve(it) }
|
|
||||||
?.map { it.resolve(PACKAGE_JSON) }
|
|
||||||
?: emptyList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-48
@@ -14,32 +14,24 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtensionOrNull
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
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.whenEvaluated
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies
|
import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinProjectNpmResolution
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinProjectNpmResolution
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.unavailableValueError
|
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See [KotlinNpmResolutionManager] for details about resolution process.
|
* See [KotlinNpmResolutionManager] for details about resolution process.
|
||||||
*/
|
*/
|
||||||
internal class KotlinProjectNpmResolver(
|
class KotlinProjectNpmResolver(
|
||||||
@Transient
|
project: Project,
|
||||||
val project: Project,
|
|
||||||
@Transient
|
|
||||||
var resolver: KotlinRootNpmResolver
|
var resolver: KotlinRootNpmResolver
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
override fun toString(): String = "ProjectNpmResolver($project)"
|
val projectPath by lazy { project.path }
|
||||||
|
|
||||||
private val projectPath by lazy { project.path }
|
|
||||||
|
|
||||||
private val byCompilation = mutableMapOf<String, KotlinCompilationNpmResolver>()
|
private val byCompilation = mutableMapOf<String, KotlinCompilationNpmResolver>()
|
||||||
|
|
||||||
operator fun get(compilation: KotlinJsCompilation): KotlinCompilationNpmResolver {
|
operator fun get(compilation: KotlinJsCompilation): KotlinCompilationNpmResolver {
|
||||||
check(compilation.target.project == project)
|
|
||||||
return byCompilation[compilation.disambiguatedName] ?: error("$compilation was not registered in $this")
|
return byCompilation[compilation.disambiguatedName] ?: error("$compilation was not registered in $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,38 +39,17 @@ internal class KotlinProjectNpmResolver(
|
|||||||
return byCompilation[compilationName] ?: error("$compilationName was not registered in $this")
|
return byCompilation[compilationName] ?: error("$compilationName was not registered in $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
private var closed = false
|
private var resolution: KotlinProjectNpmResolution? = null
|
||||||
|
|
||||||
val compilationResolvers: Collection<KotlinCompilationNpmResolver>
|
val compilationResolvers: Collection<KotlinCompilationNpmResolver>
|
||||||
get() = byCompilation.values
|
get() = byCompilation.values
|
||||||
|
|
||||||
init {
|
init {
|
||||||
addContainerListeners()
|
project.addContainerListeners()
|
||||||
|
|
||||||
project.whenEvaluated {
|
|
||||||
val nodeJs = resolver.nodeJs ?: unavailableValueError("resolver.nodeJs")
|
|
||||||
project.tasks.implementing(RequiresNpmDependencies::class)
|
|
||||||
.configureEach { task ->
|
|
||||||
if (task.enabled) {
|
|
||||||
task as RequiresNpmDependencies
|
|
||||||
// KotlinJsTest delegates npm dependencies to testFramework,
|
|
||||||
// which can be defined after this configure action
|
|
||||||
val packageJsonTaskHolder = get(task.compilation).packageJsonTaskHolder
|
|
||||||
if (task !is KotlinJsTest) {
|
|
||||||
nodeJs.taskRequirements.addTaskRequirements(task)
|
|
||||||
}
|
|
||||||
task.dependsOn(packageJsonTaskHolder)
|
|
||||||
task.dependsOn(
|
|
||||||
nodeJs.npmInstallTaskProvider,
|
|
||||||
nodeJs.storeYarnLockTaskProvider,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addContainerListeners() {
|
private fun Project.addContainerListeners() {
|
||||||
val kotlin = project.kotlinExtensionOrNull
|
val kotlin = kotlinExtensionOrNull
|
||||||
?: error("NpmResolverPlugin should be applied after kotlin plugin")
|
?: error("NpmResolverPlugin should be applied after kotlin plugin")
|
||||||
|
|
||||||
when (kotlin) {
|
when (kotlin) {
|
||||||
@@ -91,10 +62,11 @@ internal class KotlinProjectNpmResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addTargetListeners(target: KotlinTarget) {
|
private fun addTargetListeners(target: KotlinTarget) {
|
||||||
check(!closed) { resolver.alreadyResolvedMessage("add target $target") }
|
check(resolution == null) { resolver.alreadyResolvedMessage("add target $target") }
|
||||||
|
|
||||||
if (target.platformType == KotlinPlatformType.js ||
|
if (target.platformType == KotlinPlatformType.js ||
|
||||||
target.platformType == KotlinPlatformType.wasm) {
|
target.platformType == KotlinPlatformType.wasm
|
||||||
|
) {
|
||||||
target.compilations.all { compilation ->
|
target.compilations.all { compilation ->
|
||||||
if (compilation is KotlinJsCompilation) {
|
if (compilation is KotlinJsCompilation) {
|
||||||
// compilation may be KotlinWithJavaTarget for old Kotlin2JsPlugin
|
// compilation may be KotlinWithJavaTarget for old Kotlin2JsPlugin
|
||||||
@@ -115,19 +87,23 @@ internal class KotlinProjectNpmResolver(
|
|||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun addCompilation(compilation: KotlinJsCompilation) {
|
private fun addCompilation(compilation: KotlinJsCompilation) {
|
||||||
check(!closed) { resolver.alreadyResolvedMessage("add compilation $compilation") }
|
check(resolution == null) { resolver.alreadyResolvedMessage("add compilation $compilation") }
|
||||||
|
|
||||||
byCompilation[compilation.disambiguatedName] = KotlinCompilationNpmResolver(this, compilation)
|
byCompilation[compilation.disambiguatedName] =
|
||||||
|
KotlinCompilationNpmResolver(
|
||||||
|
this,
|
||||||
|
compilation
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun close(): KotlinProjectNpmResolution {
|
fun close(): KotlinProjectNpmResolution {
|
||||||
check(!closed)
|
return resolution ?: KotlinProjectNpmResolution(
|
||||||
closed = true
|
byCompilation
|
||||||
|
.map { (key, value) ->
|
||||||
return KotlinProjectNpmResolution(
|
value.close()?.let { key to it }
|
||||||
projectPath,
|
}
|
||||||
byCompilation.values.mapNotNull { it.close() },
|
.filterNotNull()
|
||||||
resolver.taskRequirements.byTask
|
.toMap(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-282
@@ -6,204 +6,45 @@
|
|||||||
package org.jetbrains.kotlin.gradle.targets.js.npm.resolver
|
package org.jetbrains.kotlin.gradle.targets.js.npm.resolver
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.Task
|
|
||||||
import org.gradle.api.logging.Logger
|
|
||||||
import org.gradle.api.provider.Provider
|
|
||||||
import org.gradle.api.services.BuildService
|
|
||||||
import org.gradle.internal.service.ServiceRegistry
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
|
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.NpmVersions
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation
|
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.TasksRequirements
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.TasksRequirements
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinProjectNpmResolution
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinRootNpmResolution
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinRootNpmResolution
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmCachesSetup
|
import java.io.File
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask
|
import java.io.Serializable
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinPackageJsonTask
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.RootPackageJsonTask
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnEnv
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnResolution
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.toVersionString
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.withType
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.ArchiveOperationsCompat
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.FileSystemOperationsCompat
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.unavailableValueError
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See [KotlinNpmResolutionManager] for details about resolution process.
|
|
||||||
*
|
|
||||||
* This class contains many transient properties to deduplicate data when configuration cache is used.
|
|
||||||
* Regularly tasks share the same instance of this class, but with configuration cache each task that holds a reference to the instance will
|
|
||||||
* create an own copy. We use build services as a single storage for the heavy state of this class.
|
|
||||||
*/
|
|
||||||
class KotlinRootNpmResolver internal constructor(
|
class KotlinRootNpmResolver internal constructor(
|
||||||
@Transient
|
val rootProjectName: String,
|
||||||
val nodeJs: NodeJsRootExtension?,
|
val rootProjectVersion: String,
|
||||||
val forceFullResolve: Boolean
|
val tasksRequirements: TasksRequirements,
|
||||||
) {
|
val versions: NpmVersions,
|
||||||
private val nodeJs_
|
val projectPackagesDir: File,
|
||||||
get() = nodeJs ?: unavailableValueError("nodeJs")
|
val rootProjectDir: File,
|
||||||
|
) : Serializable {
|
||||||
|
|
||||||
private val rootProject: Project?
|
internal var resolution: KotlinRootNpmResolution? = null
|
||||||
get() = nodeJs?.rootProject
|
|
||||||
|
|
||||||
private val rootProject_: Project
|
val projectResolvers: MutableMap<String, KotlinProjectNpmResolver> = mutableMapOf()
|
||||||
get() = rootProject ?: unavailableValueError("rootProject")
|
|
||||||
|
|
||||||
private val rootProjectName by lazy {
|
|
||||||
rootProject_.name
|
|
||||||
}
|
|
||||||
|
|
||||||
private val rootProjectVersion by lazy {
|
|
||||||
rootProject_.version.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transient
|
|
||||||
@Volatile
|
|
||||||
private var state_: RootResolverState? = RootResolverState.CONFIGURING
|
|
||||||
|
|
||||||
var state
|
|
||||||
get() = state_ ?: resolverStateHolder.get().state
|
|
||||||
set(value) {
|
|
||||||
if (state_ != null) {
|
|
||||||
state_ = value
|
|
||||||
} else {
|
|
||||||
resolverStateHolder.get().state = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val archiveOperations by lazy { ArchiveOperationsCompat(rootProject_) }
|
|
||||||
private val fs by lazy { FileSystemOperationsCompat(rootProject_) }
|
|
||||||
|
|
||||||
internal val gradleNodeModulesProvider: Provider<GradleNodeModulesCache> =
|
|
||||||
rootProject_
|
|
||||||
.gradle.sharedServices.registerIfAbsent("gradle-node-modules", GradleNodeModulesCache::class.java) {
|
|
||||||
it.parameters.cacheDir.set(nodeJs_.nodeModulesGradleCacheDir)
|
|
||||||
it.parameters.rootProjectDir.set(rootProject_.projectDir)
|
|
||||||
}.also {
|
|
||||||
declareBuildServiceForRootProjectJsTasks(it)
|
|
||||||
declareBuildServiceForAllProjectsJsTasks(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val gradleNodeModules: GradleNodeModulesCache
|
|
||||||
get() = gradleNodeModulesProvider.get().also {
|
|
||||||
it.archiveOperations = archiveOperations
|
|
||||||
it.fs = fs
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val compositeNodeModulesProvider: Provider<CompositeNodeModulesCache> =
|
|
||||||
rootProject_
|
|
||||||
.gradle.sharedServices.registerIfAbsent("composite-node-modules", CompositeNodeModulesCache::class.java) {
|
|
||||||
it.parameters.cacheDir.set(nodeJs_.nodeModulesGradleCacheDir)
|
|
||||||
it.parameters.rootProjectDir.set(rootProject_.projectDir)
|
|
||||||
}.also {
|
|
||||||
declareBuildServiceForRootProjectJsTasks(it)
|
|
||||||
declareBuildServiceForAllProjectsJsTasks(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val compositeNodeModules: CompositeNodeModulesCache
|
|
||||||
get() = compositeNodeModulesProvider.get()
|
|
||||||
|
|
||||||
@Transient
|
|
||||||
private val projectResolvers_: MutableMap<String, KotlinProjectNpmResolver>? = mutableMapOf()
|
|
||||||
|
|
||||||
@Transient
|
|
||||||
private val yarnEnvironment_: Provider<YarnEnv>? = rootProject_.provider {
|
|
||||||
YarnPlugin.apply(rootProject_).requireConfigured()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transient
|
|
||||||
private val npmEnvironment_: Provider<NpmEnvironment>? = rootProject_.provider {
|
|
||||||
nodeJs_.asNpmEnvironment
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transient
|
|
||||||
private val yarnResolutions_: Provider<List<YarnResolution>>? = rootProject_.provider {
|
|
||||||
YarnPlugin.apply(rootProject_).resolutions
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transient
|
|
||||||
private val taskRequirements_: TasksRequirements? = nodeJs_.taskRequirements
|
|
||||||
|
|
||||||
private val resolverStateHolder by lazy {
|
|
||||||
rootProject_.gradle.sharedServices.registerIfAbsent(
|
|
||||||
KotlinRootNpmResolverStateHolder::class.qualifiedName,
|
|
||||||
KotlinRootNpmResolverStateHolder::class.java
|
|
||||||
) { service ->
|
|
||||||
service.parameters.projectResolvers.set(projectResolvers_)
|
|
||||||
service.parameters.packageManager.set(nodeJs_.packageManager)
|
|
||||||
service.parameters.yarnEnvironment.set(yarnEnvironment_?.get())
|
|
||||||
service.parameters.npmEnvironment.set(npmEnvironment_?.get())
|
|
||||||
service.parameters.yarnResolutions.set(yarnResolutions_?.get())
|
|
||||||
service.parameters.taskRequirements.set(taskRequirements_)
|
|
||||||
service.parameters.packageJsonHandlers.set(compilations.associate { compilation ->
|
|
||||||
"${compilation.project.path}:${compilation.disambiguatedName}" to compilation.packageJsonHandlers
|
|
||||||
}.filter { it.value.isNotEmpty() })
|
|
||||||
}.also {
|
|
||||||
declareBuildServiceForRootProjectJsTasks(it)
|
|
||||||
declareBuildServiceForAllProjectsJsTasks(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val configurationCacheProjectResolvers: MutableMap<String, KotlinProjectNpmResolver>
|
|
||||||
get() {
|
|
||||||
val stateHolder = resolverStateHolder.get()
|
|
||||||
val projResolvers = stateHolder.parameters.projectResolvers.get()
|
|
||||||
if (stateHolder.initialized) return projResolvers
|
|
||||||
projResolvers.forEach { (_, value) ->
|
|
||||||
value.resolver = this
|
|
||||||
value.compilationResolvers.forEach { compResolver ->
|
|
||||||
compResolver.rootResolver = this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stateHolder.initialized = true
|
|
||||||
return projResolvers
|
|
||||||
}
|
|
||||||
|
|
||||||
private val projectResolvers
|
|
||||||
get() = projectResolvers_ ?: configurationCacheProjectResolvers
|
|
||||||
|
|
||||||
private val packageManager
|
|
||||||
get() = nodeJs?.packageManager ?: resolverStateHolder.get().parameters.packageManager.get()
|
|
||||||
|
|
||||||
private val yarnEnvironment
|
|
||||||
get() = yarnEnvironment_?.get() ?: resolverStateHolder.get().parameters.yarnEnvironment.get()
|
|
||||||
|
|
||||||
private val npmEnvironment
|
|
||||||
get() = npmEnvironment_?.get() ?: resolverStateHolder.get().parameters.npmEnvironment.get()
|
|
||||||
|
|
||||||
private val yarnResolutions
|
|
||||||
get() = yarnResolutions_?.get() ?: resolverStateHolder.get().parameters.yarnResolutions.get()
|
|
||||||
|
|
||||||
internal val taskRequirements
|
|
||||||
get() = taskRequirements_ ?: resolverStateHolder.get().parameters.taskRequirements.get()
|
|
||||||
|
|
||||||
internal val mayBeUpToDateTasksRegistry =
|
|
||||||
MayBeUpToDatePackageJsonTasksRegistry.registerIfAbsent(rootProject_)
|
|
||||||
|
|
||||||
fun alreadyResolvedMessage(action: String) = "Cannot $action. NodeJS projects already resolved."
|
fun alreadyResolvedMessage(action: String) = "Cannot $action. NodeJS projects already resolved."
|
||||||
|
|
||||||
fun addProject(target: Project) {
|
fun addProject(target: Project) {
|
||||||
synchronized(projectResolvers) {
|
synchronized(projectResolvers) {
|
||||||
check(state == RootResolverState.CONFIGURING) { alreadyResolvedMessage("add new project: $target") }
|
check(resolution == null) { alreadyResolvedMessage("add new project: $target") }
|
||||||
projectResolvers[target.path] = KotlinProjectNpmResolver(target, this)
|
val kotlinProjectNpmResolver = KotlinProjectNpmResolver(target, this)
|
||||||
|
projectResolvers[target.path] = kotlinProjectNpmResolver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal operator fun get(projectPath: String) = projectResolvers[projectPath] ?: error("$projectPath is not configured for JS usage")
|
internal operator fun get(projectPath: String) =
|
||||||
|
projectResolvers[projectPath] ?: error("$projectPath is not configured for JS usage")
|
||||||
|
|
||||||
val compilations: Collection<KotlinJsCompilation>
|
val compilations: Collection<KotlinJsCompilation>
|
||||||
get() = projectResolvers.values.flatMap { it.compilationResolvers.map { it.compilation } }
|
get() = projectResolvers.values.flatMap { it.compilationResolvers.map { it.compilation } }
|
||||||
|
|
||||||
internal fun getPackageJsonHandlers(projectPath: String, compilationDisambiguatedName: String): List<PackageJson.() -> Unit> =
|
|
||||||
resolverStateHolder.get().parameters.packageJsonHandlers.get()["$projectPath:$compilationDisambiguatedName"] ?: emptyList()
|
|
||||||
|
|
||||||
internal fun findDependentResolver(src: Project, target: Project): List<KotlinCompilationNpmResolver>? {
|
internal fun findDependentResolver(src: Project, target: Project): List<KotlinCompilationNpmResolver>? {
|
||||||
// todo: proper finding using KotlinTargetComponent.findUsageContext
|
// todo: proper finding using KotlinTargetComponent.findUsageContext
|
||||||
val targetResolver = this[target.path]
|
val targetResolver = this[target.path]
|
||||||
@@ -242,113 +83,15 @@ class KotlinRootNpmResolver internal constructor(
|
|||||||
return mainCompilations
|
return mainCompilations
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
internal fun close(): KotlinRootNpmResolution {
|
||||||
* Don't use directly, use [KotlinNpmResolutionManager.installIfNeeded] instead.
|
return resolution ?: KotlinRootNpmResolution(
|
||||||
*/
|
projectResolvers
|
||||||
internal fun prepareInstallation(logger: Logger): Installation {
|
.map { (key, value) -> key to value.close() }
|
||||||
synchronized(projectResolvers) {
|
.toMap(),
|
||||||
state = RootResolverState.PROJECTS_CLOSED
|
rootProjectName,
|
||||||
|
rootProjectVersion
|
||||||
val projectResolutions = projectResolvers.values
|
)
|
||||||
.map { it.close() }
|
|
||||||
.associateBy { it.project }
|
|
||||||
val allNpmPackages = projectResolutions.values.flatMap { it.npmProjects }
|
|
||||||
|
|
||||||
gradleNodeModules.close()
|
|
||||||
compositeNodeModules.close()
|
|
||||||
|
|
||||||
packageManager.prepareRootProject(
|
|
||||||
rootProject,
|
|
||||||
npmEnvironment,
|
|
||||||
rootProjectName,
|
|
||||||
rootProjectVersion,
|
|
||||||
logger,
|
|
||||||
allNpmPackages,
|
|
||||||
yarnResolutions
|
|
||||||
.associate { it.path to it.toVersionString() },
|
|
||||||
forceFullResolve
|
|
||||||
)
|
|
||||||
|
|
||||||
return Installation(
|
|
||||||
projectResolutions
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open inner class Installation(val projectResolutions: Map<String, KotlinProjectNpmResolution>) {
|
|
||||||
operator fun get(project: String) =
|
|
||||||
projectResolutions[project] ?: KotlinProjectNpmResolution.empty(project)
|
|
||||||
|
|
||||||
internal fun install(
|
|
||||||
forceUpToDate: Boolean,
|
|
||||||
args: List<String>,
|
|
||||||
services: ServiceRegistry,
|
|
||||||
logger: Logger
|
|
||||||
): KotlinRootNpmResolution {
|
|
||||||
synchronized(projectResolvers) {
|
|
||||||
if (state == RootResolverState.INSTALLED) {
|
|
||||||
return KotlinRootNpmResolution(rootProject, projectResolutions)
|
|
||||||
}
|
|
||||||
check(state == RootResolverState.PROJECTS_CLOSED) {
|
|
||||||
"Projects must be closed"
|
|
||||||
}
|
|
||||||
state = RootResolverState.INSTALLED
|
|
||||||
|
|
||||||
val allNpmPackages = projectResolutions
|
|
||||||
.values
|
|
||||||
.flatMap { it.npmProjects }
|
|
||||||
|
|
||||||
packageManager.resolveRootProject(
|
|
||||||
services,
|
|
||||||
logger,
|
|
||||||
npmEnvironment,
|
|
||||||
yarnEnvironment,
|
|
||||||
allNpmPackages,
|
|
||||||
args
|
|
||||||
)
|
|
||||||
|
|
||||||
return KotlinRootNpmResolution(rootProject, projectResolutions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun removeOutdatedPackages(nodeJs: NodeJsRootExtension, allNpmPackages: List<KotlinCompilationNpmResolution>) {
|
|
||||||
val packages = allNpmPackages.mapTo(mutableSetOf()) { it.npmProject.name }
|
|
||||||
nodeJs.projectPackagesDir.listFiles()?.forEach {
|
|
||||||
if (it.name !in packages) {
|
|
||||||
it.deleteRecursively()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun declareBuildServiceForRootProjectJsTasks(serviceProvider: Provider<out BuildService<*>>) {
|
|
||||||
rootProject_.tasks.withType<RootPackageJsonTask>().configureEach {
|
|
||||||
it.usesService(serviceProvider)
|
|
||||||
}
|
|
||||||
rootProject_.tasks.withType<KotlinNpmInstallTask>().configureEach {
|
|
||||||
it.usesService(serviceProvider)
|
|
||||||
}
|
|
||||||
rootProject_.tasks.withType<KotlinNpmCachesSetup>().configureEach {
|
|
||||||
it.usesService(serviceProvider)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun declareBuildServiceForAllProjectsJsTasks(serviceProvider: Provider<out BuildService<*>>) {
|
|
||||||
rootProject_.allprojects { project ->
|
|
||||||
project.tasks.withType<Kotlin2JsCompile>().configureEach {
|
|
||||||
it.usesService(serviceProvider)
|
|
||||||
}
|
|
||||||
project.tasks.withType<KotlinPackageJsonTask>().configureEach {
|
|
||||||
it.usesService(serviceProvider)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class RootResolverState {
|
|
||||||
CONFIGURING,
|
|
||||||
PROJECTS_CLOSED,
|
|
||||||
INSTALLED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const val PACKAGE_JSON_UMBRELLA_TASK_NAME = "packageJsonUmbrella"
|
const val PACKAGE_JSON_UMBRELLA_TASK_NAME = "packageJsonUmbrella"
|
||||||
-38
@@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2021 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.provider.ListProperty
|
|
||||||
import org.gradle.api.provider.MapProperty
|
|
||||||
import org.gradle.api.provider.Property
|
|
||||||
import org.gradle.api.services.BuildService
|
|
||||||
import org.gradle.api.services.BuildServiceParameters
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.TasksRequirements
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmEnvironment
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.PackageJson
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnEnv
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnResolution
|
|
||||||
|
|
||||||
// We use this service as a single storage for duplicated data in configuration cache
|
|
||||||
abstract class KotlinRootNpmResolverStateHolder : BuildService<KotlinRootNpmResolverStateHolder.Parameters> {
|
|
||||||
internal interface Parameters : BuildServiceParameters {
|
|
||||||
val projectResolvers: MapProperty<String, KotlinProjectNpmResolver>
|
|
||||||
val packageManager: Property<NpmApi>
|
|
||||||
val yarnEnvironment: Property<YarnEnv>
|
|
||||||
val npmEnvironment: Property<NpmEnvironment>
|
|
||||||
val yarnResolutions: ListProperty<YarnResolution>
|
|
||||||
val taskRequirements: Property<TasksRequirements>
|
|
||||||
|
|
||||||
// pulled up from compilation resolver since it was failing with ClassNotFoundException on deserialization, see KT-49061
|
|
||||||
val packageJsonHandlers: MapProperty<String, List<PackageJson.() -> Unit>>
|
|
||||||
}
|
|
||||||
|
|
||||||
var initialized = false
|
|
||||||
|
|
||||||
@Volatile
|
|
||||||
var state = RootResolverState.CONFIGURING
|
|
||||||
}
|
|
||||||
-31
@@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2021 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.gradle.api.provider.Provider
|
|
||||||
import org.gradle.api.services.BuildService
|
|
||||||
import org.gradle.api.services.BuildServiceParameters
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinPackageJsonTask
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
|
||||||
|
|
||||||
internal abstract class MayBeUpToDatePackageJsonTasksRegistry : BuildService<BuildServiceParameters.None> {
|
|
||||||
private val mayBeUpToDateTasks = ConcurrentHashMap.newKeySet<String>()
|
|
||||||
|
|
||||||
fun markForNpmDependenciesResolve(task: KotlinPackageJsonTask) {
|
|
||||||
mayBeUpToDateTasks.add(task.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun shouldResolveNpmDependenciesFor(taskPath: String) = taskPath in mayBeUpToDateTasks
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun registerIfAbsent(project: Project): Provider<MayBeUpToDatePackageJsonTasksRegistry> =
|
|
||||||
project.rootProject.gradle.sharedServices.registerIfAbsent(
|
|
||||||
MayBeUpToDatePackageJsonTasksRegistry::class.qualifiedName,
|
|
||||||
MayBeUpToDatePackageJsonTasksRegistry::class.java
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.tasks.*
|
||||||
|
import org.gradle.work.NormalizeLineEndings
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class PackageJsonProducerInputs(
|
||||||
|
@get:Input
|
||||||
|
val internalDependencies: Collection<String>,
|
||||||
|
|
||||||
|
@get:PathSensitive(PathSensitivity.ABSOLUTE)
|
||||||
|
@get:IgnoreEmptyDirectories
|
||||||
|
@get:NormalizeLineEndings
|
||||||
|
@get:InputFiles
|
||||||
|
val internalCompositeDependencies: Collection<File>,
|
||||||
|
|
||||||
|
@get:PathSensitive(PathSensitivity.ABSOLUTE)
|
||||||
|
@get:IgnoreEmptyDirectories
|
||||||
|
@get:NormalizeLineEndings
|
||||||
|
@get:InputFiles
|
||||||
|
val externalGradleDependencies: Collection<File>,
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
val externalDependencies: Collection<String>,
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
val fileCollectionDependencies: Collection<File>
|
||||||
|
)
|
||||||
+10
-7
@@ -6,21 +6,24 @@
|
|||||||
package org.jetbrains.kotlin.gradle.targets.js.npm.tasks
|
package org.jetbrains.kotlin.gradle.targets.js.npm.tasks
|
||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.tasks.Internal
|
||||||
import org.gradle.api.tasks.TaskAction
|
import org.gradle.api.tasks.TaskAction
|
||||||
import org.gradle.internal.hash.FileHasher
|
import org.gradle.internal.hash.FileHasher
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.npm.CompositeNodeModulesCache
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.GradleNodeModulesCache
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.UsesCompositeNodeModulesCache
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.UsesGradleNodeModulesCache
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
abstract class KotlinNpmCachesSetup : DefaultTask() {
|
abstract class KotlinNpmCachesSetup :
|
||||||
|
DefaultTask(),
|
||||||
|
UsesGradleNodeModulesCache,
|
||||||
|
UsesCompositeNodeModulesCache {
|
||||||
@get:Inject
|
@get:Inject
|
||||||
open val fileHasher: FileHasher
|
open val fileHasher: FileHasher
|
||||||
get() = throw UnsupportedOperationException()
|
get() = throw UnsupportedOperationException()
|
||||||
|
|
||||||
@Transient
|
|
||||||
private val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
|
||||||
private val gradleNodeModules = nodeJs.npmResolutionManager.resolver.gradleNodeModulesProvider
|
|
||||||
private val compositeNodeModules = nodeJs.npmResolutionManager.resolver.compositeNodeModulesProvider
|
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun setup() {
|
fun setup() {
|
||||||
gradleNodeModules.get().fileHasher = fileHasher
|
gradleNodeModules.get().fileHasher = fileHasher
|
||||||
|
|||||||
+35
-41
@@ -9,72 +9,66 @@ import org.gradle.api.DefaultTask
|
|||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.*
|
||||||
import org.gradle.work.NormalizeLineEndings
|
import org.gradle.work.NormalizeLineEndings
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager
|
import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.UsesKotlinNpmResolutionManager
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.asNpmEnvironment
|
import org.jetbrains.kotlin.gradle.targets.js.npm.asNpmEnvironment
|
||||||
import org.jetbrains.kotlin.gradle.utils.unavailableValueError
|
import org.jetbrains.kotlin.gradle.targets.js.npm.asYarnEnvironment
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.yarn
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
open class KotlinNpmInstallTask : DefaultTask() {
|
abstract class KotlinNpmInstallTask :
|
||||||
|
DefaultTask(),
|
||||||
|
UsesKotlinNpmResolutionManager {
|
||||||
init {
|
init {
|
||||||
check(project == project.rootProject)
|
check(project == project.rootProject)
|
||||||
|
|
||||||
onlyIf {
|
|
||||||
preparedFiles.all {
|
|
||||||
it.exists()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transient
|
// Only in configuration phase
|
||||||
private val nodeJs: NodeJsRootExtension? = NodeJsRootPlugin.apply(project.rootProject)
|
// Not part of configuration caching
|
||||||
private val resolutionManager = (nodeJs ?: unavailableValueError("nodeJs")).npmResolutionManager
|
|
||||||
|
private val nodeJs: NodeJsRootExtension
|
||||||
|
get() = project.rootProject.kotlinNodeJsExtension
|
||||||
|
|
||||||
|
private val yarn
|
||||||
|
get() = project.rootProject.yarn
|
||||||
|
|
||||||
|
// -----
|
||||||
|
|
||||||
|
private val npmEnvironment by lazy {
|
||||||
|
nodeJs.requireConfigured().asNpmEnvironment
|
||||||
|
}
|
||||||
|
|
||||||
|
private val yarnEnv by lazy {
|
||||||
|
yarn.requireConfigured().asYarnEnvironment
|
||||||
|
}
|
||||||
|
|
||||||
@Input
|
@Input
|
||||||
val args: MutableList<String> = mutableListOf()
|
val args: MutableList<String> = mutableListOf()
|
||||||
|
|
||||||
@get:Internal
|
|
||||||
val nodeModulesDir: File by lazy {
|
|
||||||
(nodeJs ?: unavailableValueError("nodeJs"))
|
|
||||||
.rootPackageDir
|
|
||||||
.resolve("node_modules")
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
outputs.upToDateWhen {
|
|
||||||
nodeModulesDir.isDirectory
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
@get:PathSensitive(PathSensitivity.ABSOLUTE)
|
|
||||||
@get:IgnoreEmptyDirectories
|
|
||||||
@get:NormalizeLineEndings
|
|
||||||
@get:InputFiles
|
|
||||||
val packageJsonFiles: Collection<File> by lazy {
|
|
||||||
resolutionManager.packageJsonFiles
|
|
||||||
}
|
|
||||||
|
|
||||||
@get:PathSensitive(PathSensitivity.ABSOLUTE)
|
@get:PathSensitive(PathSensitivity.ABSOLUTE)
|
||||||
@get:IgnoreEmptyDirectories
|
@get:IgnoreEmptyDirectories
|
||||||
@get:NormalizeLineEndings
|
@get:NormalizeLineEndings
|
||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
val preparedFiles: Collection<File> by lazy {
|
val preparedFiles: Collection<File> by lazy {
|
||||||
(nodeJs ?: unavailableValueError("nodeJs")).packageManager.preparedFiles(nodeJs.asNpmEnvironment)
|
nodeJs.packageManager.preparedFiles(npmEnvironment)
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:OutputFile
|
@get:OutputFile
|
||||||
val yarnLock: File by lazy {
|
val yarnLock: File by lazy {
|
||||||
(nodeJs ?: unavailableValueError("nodeJs")).rootPackageDir.resolve("yarn.lock")
|
nodeJs.rootPackageDir.resolve("yarn.lock")
|
||||||
}
|
}
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun resolve() {
|
fun resolve() {
|
||||||
resolutionManager.installIfNeeded(
|
npmResolutionManager.get()
|
||||||
args = args,
|
.installIfNeeded(
|
||||||
services = services,
|
args = args,
|
||||||
logger = logger
|
services = services,
|
||||||
) ?: throw (resolutionManager.state as KotlinNpmResolutionManager.ResolutionState.Error).wrappedException
|
logger = logger,
|
||||||
|
npmEnvironment,
|
||||||
|
yarnEnv
|
||||||
|
) ?: throw (npmResolutionManager.get().state as KotlinNpmResolutionManager.ResolutionState.Error).wrappedException
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+75
-60
@@ -11,92 +11,86 @@ import org.gradle.api.tasks.*
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.PackageJson
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.fakePackageJsonValue
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNpmResolutionManager
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
|
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.MayBeUpToDatePackageJsonTasksRegistry
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinCompilationNpmResolver
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinCompilationNpmResolver
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.PACKAGE_JSON_UMBRELLA_TASK_NAME
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.PACKAGE_JSON_UMBRELLA_TASK_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.PackageJsonProducerInputs
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
import org.jetbrains.kotlin.gradle.utils.chainedDisallowChanges
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.getValue
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
abstract class KotlinPackageJsonTask : DefaultTask() {
|
abstract class KotlinPackageJsonTask :
|
||||||
|
DefaultTask(),
|
||||||
|
UsesKotlinNpmResolutionManager,
|
||||||
|
UsesGradleNodeModulesCache,
|
||||||
|
UsesCompositeNodeModulesCache {
|
||||||
|
// Only in configuration phase
|
||||||
|
// Not part of configuration caching
|
||||||
|
|
||||||
init {
|
private val nodeJs: NodeJsRootExtension
|
||||||
onlyIf {
|
get() = project.rootProject.kotlinNodeJsExtension
|
||||||
npmResolutionManager.isConfiguringState()
|
|
||||||
|
private val rootResolver: KotlinRootNpmResolver
|
||||||
|
get() = nodeJs.resolver
|
||||||
|
|
||||||
|
private val compilationResolver: KotlinCompilationNpmResolver
|
||||||
|
get() = rootResolver[projectPath][compilationDisambiguatedName.get()]
|
||||||
|
|
||||||
|
private fun findDependentTasks(): Collection<Any> =
|
||||||
|
compilationResolver.compilationNpmResolution.internalDependencies.map { dependency ->
|
||||||
|
nodeJs.resolver[dependency.projectPath][dependency.compilationName].npmProject.packageJsonTaskPath
|
||||||
|
} + compilationResolver.compilationNpmResolution.internalCompositeDependencies.map { dependency ->
|
||||||
|
dependency.includedBuild?.task(":$PACKAGE_JSON_UMBRELLA_TASK_NAME") ?: error("includedBuild instance is not available")
|
||||||
|
dependency.includedBuild.task(":${RootPackageJsonTask.NAME}")
|
||||||
}
|
}
|
||||||
outputs.upToDateWhen {
|
|
||||||
// this way we will ensure that we need to resolve dependencies for the compilation in case of UP-TO-DATE task
|
|
||||||
// used in KotlinCompilationNpmResolver#getResolutionOrResolveIfForced
|
|
||||||
mayBeUpToDateTasksRegistry.get().markForNpmDependenciesResolve(it as KotlinPackageJsonTask)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transient
|
// -----
|
||||||
private lateinit var nodeJs: NodeJsRootExtension
|
|
||||||
|
|
||||||
private val npmResolutionManager by project.provider { nodeJs.npmResolutionManager }
|
private val projectPath = project.path
|
||||||
|
|
||||||
@Transient
|
|
||||||
private lateinit var compilation: KotlinJsCompilation
|
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
internal abstract val mayBeUpToDateTasksRegistry: Property<MayBeUpToDatePackageJsonTasksRegistry>
|
abstract val compilationDisambiguatedName: Property<String>
|
||||||
|
|
||||||
private val compilationDisambiguatedName by lazy {
|
private val packageJsonHandlers: List<PackageJson.() -> Unit>
|
||||||
compilation.disambiguatedName
|
get() = npmResolutionManager.get().parameters.packageJsonHandlers.get()
|
||||||
}
|
.getValue("$projectPath:${compilationDisambiguatedName.get()}")
|
||||||
|
|
||||||
@Input
|
|
||||||
val projectPath = project.path
|
|
||||||
|
|
||||||
private val compilationResolver
|
|
||||||
get() = npmResolutionManager.resolver[projectPath][compilationDisambiguatedName]
|
|
||||||
|
|
||||||
private val producer: KotlinCompilationNpmResolver.PackageJsonProducer
|
|
||||||
get() = compilationResolver.packageJsonProducer
|
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
val packageJsonCustomFields: Map<String, Any?> by lazy {
|
val packageJsonCustomFields: Map<String, Any?> by lazy {
|
||||||
PackageJson(fakePackageJsonValue, fakePackageJsonValue)
|
PackageJson(fakePackageJsonValue, fakePackageJsonValue)
|
||||||
.apply {
|
.apply {
|
||||||
compilation.packageJsonHandlers.forEach { it() }
|
packageJsonHandlers.forEach { it() }
|
||||||
}.customFields
|
}.customFields
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findDependentTasks(): Collection<Any> =
|
|
||||||
producer.internalDependencies.map { dependency ->
|
|
||||||
npmResolutionManager.resolver[dependency.projectPath][dependency.compilationName].npmProject.packageJsonTaskPath
|
|
||||||
} + producer.internalCompositeDependencies.map { dependency ->
|
|
||||||
dependency.includedBuild?.task(":$PACKAGE_JSON_UMBRELLA_TASK_NAME") ?: error("includedBuild instance is not available")
|
|
||||||
dependency.includedBuild.task(":${RootPackageJsonTask.NAME}")
|
|
||||||
}
|
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
internal val toolsNpmDependencies: List<String> by lazy {
|
internal val toolsNpmDependencies: List<String> by lazy {
|
||||||
nodeJs.taskRequirements
|
nodeJs.taskRequirements
|
||||||
.getCompilationNpmRequirements(projectPath, compilationDisambiguatedName)
|
.getCompilationNpmRequirements(projectPath, compilationDisambiguatedName.get())
|
||||||
.map { it.toString() }
|
.map { it.toString() }
|
||||||
.sorted()
|
.sorted()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nested inputs are processed in configuration phase
|
||||||
|
// so npmResolutionManager must not be used
|
||||||
@get:Nested
|
@get:Nested
|
||||||
internal val producerInputs: KotlinCompilationNpmResolver.PackageJsonProducerInputs by lazy {
|
internal val producerInputs: PackageJsonProducerInputs by lazy {
|
||||||
producer.inputs
|
compilationResolver.compilationNpmResolution.inputs
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:OutputFile
|
@get:OutputFile
|
||||||
val packageJson: File by lazy {
|
abstract val packageJson: Property<File>
|
||||||
compilationResolver.npmProject.packageJsonFile
|
|
||||||
}
|
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun resolve() {
|
fun resolve() {
|
||||||
compilationResolver.resolve()
|
npmResolutionManager.get().resolution.get()[projectPath][compilationDisambiguatedName.get()]
|
||||||
|
.resolve(
|
||||||
|
npmResolutionManager = npmResolutionManager.get(),
|
||||||
|
logger = logger
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -104,29 +98,50 @@ abstract class KotlinPackageJsonTask : DefaultTask() {
|
|||||||
val target = compilation.target
|
val target = compilation.target
|
||||||
val project = target.project
|
val project = target.project
|
||||||
val npmProject = compilation.npmProject
|
val npmProject = compilation.npmProject
|
||||||
val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
val nodeJsTaskProviders = project.rootProject.kotlinNodeJsExtension
|
||||||
|
|
||||||
val npmCachesSetupTask = nodeJs.npmCachesSetupTaskProvider
|
val npmCachesSetupTask = nodeJsTaskProviders.npmCachesSetupTaskProvider
|
||||||
val packageJsonTaskName = npmProject.packageJsonTaskName
|
val packageJsonTaskName = npmProject.packageJsonTaskName
|
||||||
val packageJsonUmbrella = nodeJs.packageJsonUmbrellaTaskProvider
|
val packageJsonUmbrella = nodeJsTaskProviders.packageJsonUmbrellaTaskProvider
|
||||||
|
val npmResolutionManager = project.kotlinNpmResolutionManager
|
||||||
|
val gradleNodeModules = GradleNodeModulesCache.registerIfAbsent(project, null, null)
|
||||||
|
val compositeNodeModules = CompositeNodeModulesCache.registerIfAbsent(project, null, null)
|
||||||
val packageJsonTask = project.registerTask<KotlinPackageJsonTask>(packageJsonTaskName) { task ->
|
val packageJsonTask = project.registerTask<KotlinPackageJsonTask>(packageJsonTaskName) { task ->
|
||||||
task.nodeJs = nodeJs
|
task.compilationDisambiguatedName.set(compilation.disambiguatedName)
|
||||||
task.compilation = compilation
|
|
||||||
task.description = "Create package.json file for $compilation"
|
task.description = "Create package.json file for $compilation"
|
||||||
task.group = NodeJsRootPlugin.TASKS_GROUP_NAME
|
task.group = NodeJsRootPlugin.TASKS_GROUP_NAME
|
||||||
val packageJsonStateService = MayBeUpToDatePackageJsonTasksRegistry.registerIfAbsent(project)
|
|
||||||
task.mayBeUpToDateTasksRegistry.value(packageJsonStateService).chainedDisallowChanges().also {
|
task.npmResolutionManager.apply {
|
||||||
task.usesService(packageJsonStateService)
|
set(npmResolutionManager)
|
||||||
|
disallowChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
task.gradleNodeModules.apply {
|
||||||
|
set(gradleNodeModules)
|
||||||
|
disallowChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
task.compositeNodeModules.apply {
|
||||||
|
set(compositeNodeModules)
|
||||||
|
disallowChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
task.packageJson.set(compilation.npmProject.packageJsonFile)
|
||||||
|
|
||||||
|
task.onlyIf {
|
||||||
|
it as KotlinPackageJsonTask
|
||||||
|
it.npmResolutionManager.get().isConfiguringState()
|
||||||
}
|
}
|
||||||
|
|
||||||
task.dependsOn(target.project.provider { task.findDependentTasks() })
|
task.dependsOn(target.project.provider { task.findDependentTasks() })
|
||||||
task.dependsOn(npmCachesSetupTask)
|
task.dependsOn(npmCachesSetupTask)
|
||||||
}
|
}
|
||||||
|
|
||||||
packageJsonUmbrella.configure { task ->
|
packageJsonUmbrella.configure { task ->
|
||||||
task.inputs.file(packageJsonTask.map { it.packageJson })
|
task.inputs.file(packageJsonTask.map { it.packageJson })
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeJs.rootPackageJsonTaskProvider!!.configure { it.mustRunAfter(packageJsonTask) }
|
nodeJsTaskProviders.rootPackageJsonTaskProvider.configure { it.mustRunAfter(packageJsonTask) }
|
||||||
|
|
||||||
return packageJsonTask
|
return packageJsonTask
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-12
@@ -8,22 +8,40 @@ package org.jetbrains.kotlin.gradle.targets.js.npm.tasks
|
|||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.*
|
||||||
import org.gradle.work.NormalizeLineEndings
|
import org.gradle.work.NormalizeLineEndings
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject
|
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.yarn.yarn
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
open class RootPackageJsonTask : DefaultTask() {
|
abstract class RootPackageJsonTask :
|
||||||
|
DefaultTask(),
|
||||||
|
UsesKotlinNpmResolutionManager {
|
||||||
init {
|
init {
|
||||||
check(project == project.rootProject)
|
check(project == project.rootProject)
|
||||||
|
|
||||||
onlyIf {
|
|
||||||
resolutionManager.isConfiguringState()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transient
|
// Only in configuration phase
|
||||||
private val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
// Not part of configuration caching
|
||||||
private val resolutionManager = nodeJs.npmResolutionManager
|
|
||||||
|
private val nodeJs
|
||||||
|
get() = project.rootProject.kotlinNodeJsExtension
|
||||||
|
|
||||||
|
private val yarn
|
||||||
|
get() = project.rootProject.yarn
|
||||||
|
|
||||||
|
private val rootResolver: KotlinRootNpmResolver
|
||||||
|
get() = nodeJs.resolver
|
||||||
|
|
||||||
|
// -----
|
||||||
|
|
||||||
|
private val npmEnvironment by lazy {
|
||||||
|
nodeJs.requireConfigured().asNpmEnvironment
|
||||||
|
}
|
||||||
|
|
||||||
|
private val yarnEnv by lazy {
|
||||||
|
yarn.requireConfigured().asYarnEnvironment
|
||||||
|
}
|
||||||
|
|
||||||
@get:OutputFile
|
@get:OutputFile
|
||||||
val rootPackageJson: File by lazy {
|
val rootPackageJson: File by lazy {
|
||||||
@@ -35,12 +53,15 @@ open class RootPackageJsonTask : DefaultTask() {
|
|||||||
@get:NormalizeLineEndings
|
@get:NormalizeLineEndings
|
||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
val packageJsonFiles: Collection<File> by lazy {
|
val packageJsonFiles: Collection<File> by lazy {
|
||||||
resolutionManager.packageJsonFiles
|
rootResolver.projectResolvers.values
|
||||||
|
.flatMap { it.compilationResolvers }
|
||||||
|
.map { it.compilationNpmResolution }
|
||||||
|
.map { it.npmProjectPackageJsonFile }
|
||||||
}
|
}
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun resolve() {
|
fun resolve() {
|
||||||
resolutionManager.prepare(logger)
|
npmResolutionManager.get().prepare(logger, npmEnvironment, yarnEnv)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+13
-31
@@ -14,7 +14,6 @@ import org.gradle.language.base.plugins.LifecycleBasePlugin
|
|||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJsDce
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJsDce
|
||||||
import org.jetbrains.kotlin.gradle.plugin.COMPILER_CLASSPATH_CONFIGURATION_NAME
|
import org.jetbrains.kotlin.gradle.plugin.COMPILER_CLASSPATH_CONFIGURATION_NAME
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
|
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.isTest
|
import org.jetbrains.kotlin.gradle.plugin.mpp.isTest
|
||||||
@@ -25,7 +24,7 @@ import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.*
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.*
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.ir.executeTaskBaseName
|
import org.jetbrains.kotlin.gradle.targets.js.ir.executeTaskBaseName
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
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.testing.KotlinJsTest
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KotlinKarma
|
import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KotlinKarma
|
||||||
@@ -33,7 +32,6 @@ import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.WebpackDevtool
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.WebpackDevtool
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.WebpackMajorVersion.Companion.choose
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.dependsOn
|
import org.jetbrains.kotlin.gradle.tasks.dependsOn
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
import org.jetbrains.kotlin.gradle.utils.doNotTrackStateCompat
|
import org.jetbrains.kotlin.gradle.utils.doNotTrackStateCompat
|
||||||
@@ -51,9 +49,6 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) :
|
|||||||
private val runTaskConfigurations: MutableList<Action<KotlinWebpack>> = mutableListOf()
|
private val runTaskConfigurations: MutableList<Action<KotlinWebpack>> = mutableListOf()
|
||||||
private val dceConfigurations: MutableList<Action<KotlinJsDce>> = mutableListOf()
|
private val dceConfigurations: MutableList<Action<KotlinJsDce>> = mutableListOf()
|
||||||
private val distribution: Distribution = createDefaultDistribution(project)
|
private val distribution: Distribution = createDefaultDistribution(project)
|
||||||
private val propertiesProvider = PropertiesProvider(project)
|
|
||||||
private val webpackMajorVersion
|
|
||||||
get() = propertiesProvider.webpackMajorVersion
|
|
||||||
|
|
||||||
override val testTaskDescription: String
|
override val testTaskDescription: String
|
||||||
get() = "Run all ${target.name} tests inside browser using karma and webpack"
|
get() = "Run all ${target.name} tests inside browser using karma and webpack"
|
||||||
@@ -138,7 +133,7 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) :
|
|||||||
devDceTaskProvider: TaskProvider<KotlinJsDceTask>
|
devDceTaskProvider: TaskProvider<KotlinJsDceTask>
|
||||||
) {
|
) {
|
||||||
val project = compilation.target.project
|
val project = compilation.target.project
|
||||||
val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
val nodeJs = project.rootProject.kotlinNodeJsExtension
|
||||||
|
|
||||||
val commonRunTask = registerSubTargetTask<Task>(disambiguateCamelCased(RUN_TASK_NAME)) {}
|
val commonRunTask = registerSubTargetTask<Task>(disambiguateCamelCased(RUN_TASK_NAME)) {}
|
||||||
|
|
||||||
@@ -156,33 +151,20 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) :
|
|||||||
listOf(compilation)
|
listOf(compilation)
|
||||||
) { task ->
|
) { task ->
|
||||||
task.outputDirectory.convention(distsDirectory).finalizeValueOnRead()
|
task.outputDirectory.convention(distsDirectory).finalizeValueOnRead()
|
||||||
webpackMajorVersion.choose(
|
task.args.add(0, "serve")
|
||||||
{ task.args.add(0, "serve") },
|
|
||||||
{ task.bin = "webpack-dev-server/bin/webpack-dev-server.js" }
|
|
||||||
)()
|
|
||||||
|
|
||||||
task.description = "start ${type.name.toLowerCaseAsciiOnly()} webpack dev server"
|
task.description = "start ${type.name.toLowerCaseAsciiOnly()} webpack dev server"
|
||||||
|
|
||||||
webpackMajorVersion.choose(
|
task.devServer = KotlinWebpackConfig.DevServer(
|
||||||
{
|
open = true,
|
||||||
task.devServer = KotlinWebpackConfig.DevServer(
|
static = mutableListOf(compilation.output.resourcesDir.canonicalPath),
|
||||||
open = true,
|
client = KotlinWebpackConfig.DevServer.Client(
|
||||||
static = mutableListOf(compilation.output.resourcesDir.canonicalPath),
|
KotlinWebpackConfig.DevServer.Client.Overlay(
|
||||||
client = KotlinWebpackConfig.DevServer.Client(
|
errors = true,
|
||||||
KotlinWebpackConfig.DevServer.Client.Overlay(
|
warnings = false
|
||||||
errors = true,
|
|
||||||
warnings = false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
},
|
)
|
||||||
{
|
)
|
||||||
task.devServer = KotlinWebpackConfig.DevServer(
|
|
||||||
open = true,
|
|
||||||
contentBase = mutableListOf(compilation.output.resourcesDir.canonicalPath)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)()
|
|
||||||
|
|
||||||
task.doNotTrackStateCompat("Tracked by external webpack tool")
|
task.doNotTrackStateCompat("Tracked by external webpack tool")
|
||||||
|
|
||||||
@@ -212,7 +194,7 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) :
|
|||||||
devDceTaskProvider: TaskProvider<KotlinJsDceTask>
|
devDceTaskProvider: TaskProvider<KotlinJsDceTask>
|
||||||
) {
|
) {
|
||||||
val project = compilation.target.project
|
val project = compilation.target.project
|
||||||
val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
val nodeJs = project.rootProject.kotlinNodeJsExtension
|
||||||
|
|
||||||
val processResourcesTask = target.project.tasks.named(compilation.processResourcesTaskName)
|
val processResourcesTask = target.project.tasks.named(compilation.processResourcesTaskName)
|
||||||
|
|
||||||
|
|||||||
+6
-8
@@ -20,8 +20,7 @@ import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsPlatformTestRun
|
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsPlatformTestRun
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsSubTargetDsl
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsSubTargetDsl
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolverPlugin
|
|
||||||
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.testing.KotlinJsTest
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
@@ -35,7 +34,8 @@ abstract class KotlinJsSubTarget(
|
|||||||
) : KotlinJsSubTargetDsl {
|
) : KotlinJsSubTargetDsl {
|
||||||
val project get() = target.project
|
val project get() = target.project
|
||||||
|
|
||||||
private val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
private val nodeJs = project.rootProject.kotlinNodeJsExtension
|
||||||
|
private val nodeJsTaskProviders = project.rootProject.kotlinNodeJsExtension
|
||||||
|
|
||||||
abstract val testTaskDescription: String
|
abstract val testTaskDescription: String
|
||||||
|
|
||||||
@@ -53,8 +53,6 @@ abstract class KotlinJsSubTarget(
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun configure() {
|
internal fun configure() {
|
||||||
NpmResolverPlugin.apply(project)
|
|
||||||
|
|
||||||
configureTests()
|
configureTests()
|
||||||
|
|
||||||
target.compilations.all {
|
target.compilations.all {
|
||||||
@@ -108,10 +106,10 @@ abstract class KotlinJsSubTarget(
|
|||||||
testJs.inputFileProperty.fileProvider(compileOutputFile)
|
testJs.inputFileProperty.fileProvider(compileOutputFile)
|
||||||
|
|
||||||
testJs.dependsOn(
|
testJs.dependsOn(
|
||||||
nodeJs.npmInstallTaskProvider,
|
nodeJsTaskProviders.npmInstallTaskProvider,
|
||||||
nodeJs.storeYarnLockTaskProvider,
|
nodeJsTaskProviders.storeYarnLockTaskProvider,
|
||||||
compileTask,
|
compileTask,
|
||||||
nodeJs.nodeJsSetupTaskProvider
|
nodeJsTaskProviders.nodeJsSetupTaskProvider
|
||||||
)
|
)
|
||||||
|
|
||||||
testJs.onlyIf {
|
testJs.onlyIf {
|
||||||
|
|||||||
+2
-14
@@ -14,7 +14,7 @@ import org.gradle.work.NormalizeLineEndings
|
|||||||
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.RequiredKotlinJsDependency
|
import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
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.targets.js.testing.karma.KotlinKarma
|
import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KotlinKarma
|
||||||
@@ -33,16 +33,12 @@ constructor(
|
|||||||
) : KotlinTest(),
|
) : KotlinTest(),
|
||||||
RequiresNpmDependencies {
|
RequiresNpmDependencies {
|
||||||
@Transient
|
@Transient
|
||||||
private val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
private val nodeJs = project.rootProject.kotlinNodeJsExtension
|
||||||
|
|
||||||
private val npmResolutionManager by project.provider { nodeJs.npmResolutionManager }
|
|
||||||
|
|
||||||
private val nodeExecutable by project.provider { nodeJs.requireConfigured().nodeExecutable }
|
private val nodeExecutable by project.provider { nodeJs.requireConfigured().nodeExecutable }
|
||||||
|
|
||||||
private val npmProjectDir by project.provider { compilation.npmProject.dir }
|
private val npmProjectDir by project.provider { compilation.npmProject.dir }
|
||||||
|
|
||||||
private val projectPath = project.path
|
|
||||||
|
|
||||||
@Input
|
@Input
|
||||||
var environment = mutableMapOf<String, String>()
|
var environment = mutableMapOf<String, String>()
|
||||||
|
|
||||||
@@ -110,9 +106,6 @@ constructor(
|
|||||||
val nodeJsArgs: MutableList<String> =
|
val nodeJsArgs: MutableList<String> =
|
||||||
mutableListOf()
|
mutableListOf()
|
||||||
|
|
||||||
override val nodeModulesRequired: Boolean
|
|
||||||
@Internal get() = testFramework!!.nodeModulesRequired
|
|
||||||
|
|
||||||
override val requiredNpmDependencies: Set<RequiredKotlinJsDependency>
|
override val requiredNpmDependencies: Set<RequiredKotlinJsDependency>
|
||||||
@Internal get() = testFramework!!.requiredNpmDependencies
|
@Internal get() = testFramework!!.requiredNpmDependencies
|
||||||
|
|
||||||
@@ -164,11 +157,6 @@ constructor(
|
|||||||
return testFramework
|
return testFramework
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun executeTests() {
|
|
||||||
npmResolutionManager.checkRequiredDependencies(task = this)
|
|
||||||
super.executeTests()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun createTestExecutionSpec(): TCServiceMessagesTestExecutionSpec {
|
override fun createTestExecutionSpec(): TCServiceMessagesTestExecutionSpec {
|
||||||
val forkOptions = DefaultProcessForkOptions(fileResolver)
|
val forkOptions = DefaultProcessForkOptions(fileResolver)
|
||||||
forkOptions.workingDir = npmProjectDir
|
forkOptions.workingDir = npmProjectDir
|
||||||
|
|||||||
-3
@@ -18,7 +18,4 @@ interface KotlinJsTestFramework : RequiresNpmDependencies {
|
|||||||
nodeJsArgs: MutableList<String>,
|
nodeJsArgs: MutableList<String>,
|
||||||
debug: Boolean
|
debug: Boolean
|
||||||
): TCServiceMessagesTestExecutionSpec
|
): TCServiceMessagesTestExecutionSpec
|
||||||
|
|
||||||
override val nodeModulesRequired: Boolean
|
|
||||||
get() = true
|
|
||||||
}
|
}
|
||||||
+11
-27
@@ -32,11 +32,10 @@ import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl.Companion.webp
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm
|
import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.jsQuoted
|
import org.jetbrains.kotlin.gradle.targets.js.jsQuoted
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
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.testing.*
|
import org.jetbrains.kotlin.gradle.targets.js.testing.*
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.WebpackMajorVersion
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.WebpackMajorVersion.Companion.choose
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinTest
|
import org.jetbrains.kotlin.gradle.tasks.KotlinTest
|
||||||
import org.jetbrains.kotlin.gradle.testing.internal.reportsDir
|
import org.jetbrains.kotlin.gradle.testing.internal.reportsDir
|
||||||
import org.jetbrains.kotlin.gradle.utils.appendLine
|
import org.jetbrains.kotlin.gradle.utils.appendLine
|
||||||
@@ -56,7 +55,7 @@ class KotlinKarma(
|
|||||||
private val npmProject = compilation.npmProject
|
private val npmProject = compilation.npmProject
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
private val nodeJs = project.rootProject.kotlinNodeJsExtension
|
||||||
private val nodeRootPackageDir by lazy { nodeJs.rootPackageDir }
|
private val nodeRootPackageDir by lazy { nodeJs.rootPackageDir }
|
||||||
private val versions = nodeJs.versions
|
private val versions = nodeJs.versions
|
||||||
|
|
||||||
@@ -81,8 +80,6 @@ class KotlinKarma(
|
|||||||
override val settingsState: String
|
override val settingsState: String
|
||||||
get() = "KotlinKarma($config)"
|
get() = "KotlinKarma($config)"
|
||||||
|
|
||||||
private val webpackMajorVersion = PropertiesProvider(project).webpackMajorVersion
|
|
||||||
|
|
||||||
val webpackConfig = KotlinWebpackConfig(
|
val webpackConfig = KotlinWebpackConfig(
|
||||||
configDirectory = project.projectDir.resolve("webpack.config.d"),
|
configDirectory = project.projectDir.resolve("webpack.config.d"),
|
||||||
optimization = KotlinWebpackConfig.Optimization(
|
optimization = KotlinWebpackConfig.Optimization(
|
||||||
@@ -94,13 +91,11 @@ class KotlinKarma(
|
|||||||
export = false,
|
export = false,
|
||||||
progressReporter = true,
|
progressReporter = true,
|
||||||
progressReporterPathFilter = nodeRootPackageDir,
|
progressReporterPathFilter = nodeRootPackageDir,
|
||||||
webpackMajorVersion = webpackMajorVersion,
|
|
||||||
rules = project.objects.webpackRulesContainer(),
|
rules = project.objects.webpackRulesContainer(),
|
||||||
experiments = mutableSetOf("topLevelAwait")
|
experiments = mutableSetOf("topLevelAwait")
|
||||||
)
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
requiredDependencies.add(versions.kotlinJsTestRunner)
|
|
||||||
requiredDependencies.add(versions.karma)
|
requiredDependencies.add(versions.karma)
|
||||||
|
|
||||||
useKotlinReporter()
|
useKotlinReporter()
|
||||||
@@ -266,23 +261,14 @@ class KotlinKarma(
|
|||||||
config.frameworks.add("webpack")
|
config.frameworks.add("webpack")
|
||||||
requiredDependencies.add(versions.karmaWebpack)
|
requiredDependencies.add(versions.karmaWebpack)
|
||||||
requiredDependencies.add(
|
requiredDependencies.add(
|
||||||
webpackMajorVersion.choose(
|
versions.webpack
|
||||||
versions.webpack,
|
|
||||||
versions.webpack4
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
requiredDependencies.add(
|
requiredDependencies.add(
|
||||||
webpackMajorVersion.choose(
|
versions.webpackCli
|
||||||
versions.webpackCli,
|
|
||||||
versions.webpackCli3
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
requiredDependencies.add(versions.formatUtil)
|
requiredDependencies.add(versions.formatUtil)
|
||||||
requiredDependencies.add(
|
requiredDependencies.add(
|
||||||
webpackMajorVersion.choose(
|
versions.sourceMapLoader
|
||||||
versions.sourceMapLoader,
|
|
||||||
versions.sourceMapLoader1
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
addPreprocessor("webpack")
|
addPreprocessor("webpack")
|
||||||
@@ -298,14 +284,12 @@ class KotlinKarma(
|
|||||||
// noinspection JSUnnecessarySemicolon
|
// noinspection JSUnnecessarySemicolon
|
||||||
;(function(config) {
|
;(function(config) {
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
${
|
${
|
||||||
if (webpackMajorVersion != WebpackMajorVersion.V4) {
|
"""
|
||||||
"""
|
// https://github.com/webpack/webpack/issues/12951
|
||||||
// https://github.com/webpack/webpack/issues/12951
|
const PatchSourceMapSource = require('kotlin-test-js-runner/webpack-5-debug');
|
||||||
const PatchSourceMapSource = require('kotlin-test-js-runner/webpack-5-debug');
|
config.plugins.push(new PatchSourceMapSource())
|
||||||
config.plugins.push(new PatchSourceMapSource())
|
"""
|
||||||
"""
|
|
||||||
} else ""
|
|
||||||
}
|
}
|
||||||
config.plugins.push(new webpack.SourceMapDevToolPlugin({
|
config.plugins.push(new webpack.SourceMapDevToolPlugin({
|
||||||
moduleFilenameTemplate: "[absolute-resource-path]"
|
moduleFilenameTemplate: "[absolute-resource-path]"
|
||||||
|
|||||||
+2
-2
@@ -15,6 +15,7 @@ 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.internal.parseNodeJsStackTraceAsJvm
|
import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
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.testing.KotlinJsTest
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTestFramework
|
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTestFramework
|
||||||
@@ -25,7 +26,7 @@ class KotlinMocha(@Transient override val compilation: KotlinJsCompilation, priv
|
|||||||
@Transient
|
@Transient
|
||||||
private val project: Project = compilation.target.project
|
private val project: Project = compilation.target.project
|
||||||
private val npmProject = compilation.npmProject
|
private val npmProject = compilation.npmProject
|
||||||
private val versions = NodeJsRootPlugin.apply(project.rootProject).versions
|
private val versions = project.rootProject.kotlinNodeJsExtension.versions
|
||||||
private val isTeamCity = project.providers.gradleProperty(TCServiceMessagesTestExecutor.TC_PROJECT_PROPERTY)
|
private val isTeamCity = project.providers.gradleProperty(TCServiceMessagesTestExecutor.TC_PROJECT_PROPERTY)
|
||||||
|
|
||||||
override val settingsState: String
|
override val settingsState: String
|
||||||
@@ -33,7 +34,6 @@ class KotlinMocha(@Transient override val compilation: KotlinJsCompilation, priv
|
|||||||
|
|
||||||
override val requiredNpmDependencies: Set<RequiredKotlinJsDependency>
|
override val requiredNpmDependencies: Set<RequiredKotlinJsDependency>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
versions.kotlinJsTestRunner,
|
|
||||||
versions.mocha,
|
versions.mocha,
|
||||||
versions.sourceMapSupport,
|
versions.sourceMapSupport,
|
||||||
versions.formatUtil
|
versions.formatUtil
|
||||||
|
|||||||
+8
-10
@@ -6,15 +6,15 @@
|
|||||||
package org.jetbrains.kotlin.gradle.targets.js.typescript
|
package org.jetbrains.kotlin.gradle.targets.js.typescript
|
||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.tasks.*
|
|
||||||
import org.gradle.api.provider.Property
|
|
||||||
import org.gradle.api.file.DirectoryProperty
|
import org.gradle.api.file.DirectoryProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
import org.gradle.api.tasks.*
|
||||||
import org.gradle.work.NormalizeLineEndings
|
import org.gradle.work.NormalizeLineEndings
|
||||||
import org.jetbrains.kotlin.gradle.internal.execWithProgress
|
import org.jetbrains.kotlin.gradle.internal.execWithProgress
|
||||||
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.ir.KotlinIrJsGeneratedTSValidationStrategy
|
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinIrJsGeneratedTSValidationStrategy
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
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 javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -30,14 +30,13 @@ constructor(
|
|||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
@Transient
|
@Transient
|
||||||
protected val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
protected val nodeJs = project.rootProject.kotlinNodeJsExtension
|
||||||
|
|
||||||
@get:Internal
|
private val versions = nodeJs.versions
|
||||||
override val nodeModulesRequired: Boolean get() = false
|
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
override val requiredNpmDependencies: Set<RequiredKotlinJsDependency>
|
override val requiredNpmDependencies: Set<RequiredKotlinJsDependency>
|
||||||
get() = setOf(nodeJs.versions.typescript)
|
get() = setOf(versions.typescript)
|
||||||
|
|
||||||
@get:SkipWhenEmpty
|
@get:SkipWhenEmpty
|
||||||
@get:NormalizeLineEndings
|
@get:NormalizeLineEndings
|
||||||
@@ -69,9 +68,8 @@ constructor(
|
|||||||
|
|
||||||
val message = "Oops, Kotlin/JS compiler generated invalid d.ts files."
|
val message = "Oops, Kotlin/JS compiler generated invalid d.ts files."
|
||||||
|
|
||||||
when (validationStrategy) {
|
if (validationStrategy == KotlinIrJsGeneratedTSValidationStrategy.ERROR) {
|
||||||
KotlinIrJsGeneratedTSValidationStrategy.ERROR -> error(message)
|
error(message)
|
||||||
KotlinIrJsGeneratedTSValidationStrategy.IGNORE -> {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-11
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinWebpackRulesContainer
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl.Companion.webpackRulesContainer
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl.Companion.webpackRulesContainer
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
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.targets.js.webpack.KotlinWebpackConfig.Mode
|
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode
|
||||||
@@ -55,9 +56,8 @@ constructor(
|
|||||||
private val objects: ObjectFactory
|
private val objects: ObjectFactory
|
||||||
) : DefaultTask(), RequiresNpmDependencies, WebpackRulesDsl, UsesBuildMetricsService {
|
) : DefaultTask(), RequiresNpmDependencies, WebpackRulesDsl, UsesBuildMetricsService {
|
||||||
@Transient
|
@Transient
|
||||||
private val nodeJs = NodeJsRootPlugin.apply(project.rootProject)
|
private val nodeJs = project.rootProject.kotlinNodeJsExtension
|
||||||
private val versions = nodeJs.versions
|
private val versions = nodeJs.versions
|
||||||
private val resolutionManager = nodeJs.npmResolutionManager
|
|
||||||
private val rootPackageDir by lazy { nodeJs.rootPackageDir }
|
private val rootPackageDir by lazy { nodeJs.rootPackageDir }
|
||||||
|
|
||||||
private val npmProject = compilation.npmProject
|
private val npmProject = compilation.npmProject
|
||||||
@@ -202,9 +202,6 @@ constructor(
|
|||||||
@Internal
|
@Internal
|
||||||
var generateConfigOnly: Boolean = false
|
var generateConfigOnly: Boolean = false
|
||||||
|
|
||||||
@Input
|
|
||||||
val webpackMajorVersion = PropertiesProvider(project).webpackMajorVersion
|
|
||||||
|
|
||||||
fun webpackConfigApplier(body: Action<KotlinWebpackConfig>) {
|
fun webpackConfigApplier(body: Action<KotlinWebpackConfig>) {
|
||||||
webpackConfigAppliers.add(body)
|
webpackConfigAppliers.add(body)
|
||||||
}
|
}
|
||||||
@@ -234,7 +231,6 @@ constructor(
|
|||||||
devtool = devtool,
|
devtool = devtool,
|
||||||
sourceMaps = sourceMaps,
|
sourceMaps = sourceMaps,
|
||||||
resolveFromModulesFirst = resolveFromModulesFirst,
|
resolveFromModulesFirst = resolveFromModulesFirst,
|
||||||
webpackMajorVersion = webpackMajorVersion
|
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun createRunner(): KotlinWebpackRunner {
|
private fun createRunner(): KotlinWebpackRunner {
|
||||||
@@ -262,9 +258,6 @@ constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val nodeModulesRequired: Boolean
|
|
||||||
@Internal get() = true
|
|
||||||
|
|
||||||
override val requiredNpmDependencies: Set<RequiredKotlinJsDependency>
|
override val requiredNpmDependencies: Set<RequiredKotlinJsDependency>
|
||||||
@Internal get() = createWebpackConfig(true).getRequiredDependencies(versions)
|
@Internal get() = createWebpackConfig(true).getRequiredDependencies(versions)
|
||||||
|
|
||||||
@@ -272,8 +265,6 @@ constructor(
|
|||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun doExecute() {
|
fun doExecute() {
|
||||||
resolutionManager.checkRequiredDependencies(task = this)
|
|
||||||
|
|
||||||
val runner = createRunner()
|
val runner = createRunner()
|
||||||
|
|
||||||
if (generateConfigOnly) {
|
if (generateConfigOnly) {
|
||||||
|
|||||||
+9
-31
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.gradle.targets.js.appendConfigsFromDir
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinWebpackRulesContainer
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinWebpackRulesContainer
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.jsQuoted
|
import org.jetbrains.kotlin.gradle.targets.js.jsQuoted
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.webpack.WebpackMajorVersion.Companion.choose
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.appendLine
|
import org.jetbrains.kotlin.gradle.utils.appendLine
|
||||||
import org.jetbrains.kotlin.gradle.utils.relativeOrAbsolute
|
import org.jetbrains.kotlin.gradle.utils.relativeOrAbsolute
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -49,6 +48,8 @@ data class KotlinWebpackConfig(
|
|||||||
@get:NormalizeLineEndings
|
@get:NormalizeLineEndings
|
||||||
@get:InputDirectory
|
@get:InputDirectory
|
||||||
var configDirectory: File? = null,
|
var configDirectory: File? = null,
|
||||||
|
@Internal
|
||||||
|
var reportEvaluatedConfigFile: File? = null,
|
||||||
@Input
|
@Input
|
||||||
@Optional
|
@Optional
|
||||||
var devServer: DevServer? = null,
|
var devServer: DevServer? = null,
|
||||||
@@ -72,9 +73,7 @@ data class KotlinWebpackConfig(
|
|||||||
@Optional
|
@Optional
|
||||||
var progressReporterPathFilter: File? = null,
|
var progressReporterPathFilter: File? = null,
|
||||||
@Input
|
@Input
|
||||||
var resolveFromModulesFirst: Boolean = false,
|
var resolveFromModulesFirst: Boolean = false
|
||||||
@Input
|
|
||||||
val webpackMajorVersion: WebpackMajorVersion = WebpackMajorVersion.V5
|
|
||||||
) : WebpackRulesDsl {
|
) : WebpackRulesDsl {
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
@@ -94,36 +93,23 @@ data class KotlinWebpackConfig(
|
|||||||
|
|
||||||
fun getRequiredDependencies(versions: NpmVersions) =
|
fun getRequiredDependencies(versions: NpmVersions) =
|
||||||
mutableSetOf<RequiredKotlinJsDependency>().also {
|
mutableSetOf<RequiredKotlinJsDependency>().also {
|
||||||
it.add(versions.kotlinJsTestRunner)
|
|
||||||
it.add(
|
it.add(
|
||||||
webpackMajorVersion.choose(
|
versions.webpack
|
||||||
versions.webpack,
|
|
||||||
versions.webpack4
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
it.add(
|
it.add(
|
||||||
webpackMajorVersion.choose(
|
versions.webpackCli
|
||||||
versions.webpackCli,
|
|
||||||
versions.webpackCli3
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
it.add(versions.formatUtil)
|
it.add(versions.formatUtil)
|
||||||
|
|
||||||
if (sourceMaps) {
|
if (sourceMaps) {
|
||||||
it.add(
|
it.add(
|
||||||
webpackMajorVersion.choose(
|
versions.sourceMapLoader
|
||||||
versions.sourceMapLoader,
|
|
||||||
versions.sourceMapLoader1
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (devServer != null) {
|
if (devServer != null) {
|
||||||
it.add(
|
it.add(
|
||||||
webpackMajorVersion.choose(
|
versions.webpackDevServer
|
||||||
versions.webpackDevServer,
|
|
||||||
versions.webpackDevServer3
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,16 +280,8 @@ data class KotlinWebpackConfig(
|
|||||||
enforce: "pre"
|
enforce: "pre"
|
||||||
});
|
});
|
||||||
config.devtool = ${devtool?.let { "'$it'" } ?: false};
|
config.devtool = ${devtool?.let { "'$it'" } ?: false};
|
||||||
${
|
${
|
||||||
webpackMajorVersion.choose(
|
"config.ignoreWarnings = [/Failed to parse source map/]"
|
||||||
"config.ignoreWarnings = [/Failed to parse source map/]",
|
|
||||||
"""
|
|
||||||
config.stats = config.stats || {}
|
|
||||||
Object.assign(config.stats, config.stats, {
|
|
||||||
warningsFilter: [/Failed to parse source map/]
|
|
||||||
})
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|||||||
+5
-28
@@ -5,55 +5,43 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.targets.js.yarn
|
package org.jetbrains.kotlin.gradle.targets.js.yarn
|
||||||
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.internal.service.ServiceRegistry
|
import org.gradle.internal.service.ServiceRegistry
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
|
||||||
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.NpmDependency
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmEnvironment
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmEnvironment
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution
|
import org.jetbrains.kotlin.gradle.targets.js.npm.YarnEnvironment
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.PreparedKotlinCompilationNpmResolution
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class Yarn : NpmApi {
|
class Yarn : NpmApi {
|
||||||
private val yarnWorkspaces = YarnWorkspaces()
|
private val yarnWorkspaces = YarnWorkspaces()
|
||||||
|
|
||||||
private fun getDelegate(project: Project): NpmApi =
|
|
||||||
yarnWorkspaces
|
|
||||||
|
|
||||||
override fun setup(project: Project) =
|
|
||||||
getDelegate(project.rootProject).setup(project)
|
|
||||||
|
|
||||||
override fun preparedFiles(nodeJs: NpmEnvironment): Collection<File> =
|
override fun preparedFiles(nodeJs: NpmEnvironment): Collection<File> =
|
||||||
yarnWorkspaces.preparedFiles(nodeJs)
|
yarnWorkspaces.preparedFiles(nodeJs)
|
||||||
|
|
||||||
override fun prepareRootProject(
|
override fun prepareRootProject(
|
||||||
rootProject: Project?,
|
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NpmEnvironment,
|
||||||
rootProjectName: String,
|
rootProjectName: String,
|
||||||
rootProjectVersion: String,
|
rootProjectVersion: String,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
subProjects: Collection<KotlinCompilationNpmResolution>,
|
subProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
resolutions: Map<String, String>,
|
resolutions: Map<String, String>,
|
||||||
forceFullResolve: Boolean
|
|
||||||
) = yarnWorkspaces
|
) = yarnWorkspaces
|
||||||
.prepareRootProject(
|
.prepareRootProject(
|
||||||
rootProject,
|
|
||||||
nodeJs,
|
nodeJs,
|
||||||
rootProjectName,
|
rootProjectName,
|
||||||
rootProjectVersion,
|
rootProjectVersion,
|
||||||
logger,
|
logger,
|
||||||
subProjects,
|
subProjects,
|
||||||
resolutions,
|
resolutions,
|
||||||
forceFullResolve
|
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun resolveRootProject(
|
override fun resolveRootProject(
|
||||||
services: ServiceRegistry,
|
services: ServiceRegistry,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NpmEnvironment,
|
||||||
yarn: YarnEnv,
|
yarn: YarnEnvironment,
|
||||||
npmProjects: Collection<KotlinCompilationNpmResolution>,
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
cliArgs: List<String>
|
cliArgs: List<String>
|
||||||
) {
|
) {
|
||||||
yarnWorkspaces
|
yarnWorkspaces
|
||||||
@@ -66,15 +54,4 @@ class Yarn : NpmApi {
|
|||||||
cliArgs
|
cliArgs
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resolveDependency(
|
|
||||||
npmResolution: KotlinCompilationNpmResolution,
|
|
||||||
dependency: NpmDependency,
|
|
||||||
transitive: Boolean
|
|
||||||
) = getDelegate(npmResolution.project)
|
|
||||||
.resolveDependency(
|
|
||||||
npmResolution,
|
|
||||||
dependency,
|
|
||||||
transitive
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
+2
-115
@@ -5,31 +5,21 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.targets.js.yarn
|
package org.jetbrains.kotlin.gradle.targets.js.yarn
|
||||||
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.internal.service.ServiceRegistry
|
import org.gradle.internal.service.ServiceRegistry
|
||||||
import org.jetbrains.kotlin.gradle.internal.execWithProgress
|
import org.jetbrains.kotlin.gradle.internal.execWithProgress
|
||||||
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.NpmDependency
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency.Scope.PEER
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmEnvironment
|
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmEnvironment
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution
|
import org.jetbrains.kotlin.gradle.targets.js.npm.YarnEnvironment
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
abstract class YarnBasics : NpmApi {
|
abstract class YarnBasics : NpmApi {
|
||||||
|
|
||||||
private val nonTransitiveResolvedDependencies = mutableMapOf<NpmDependency, Set<File>>()
|
|
||||||
private val transitiveResolvedDependencies = mutableMapOf<NpmDependency, Set<File>>()
|
|
||||||
|
|
||||||
override fun setup(project: Project) {
|
|
||||||
YarnPlugin.apply(project).executeSetup()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun yarnExec(
|
fun yarnExec(
|
||||||
services: ServiceRegistry,
|
services: ServiceRegistry,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NpmEnvironment,
|
||||||
yarn: YarnEnv,
|
yarn: YarnEnvironment,
|
||||||
dir: File,
|
dir: File,
|
||||||
description: String,
|
description: String,
|
||||||
args: List<String>
|
args: List<String>
|
||||||
@@ -69,107 +59,4 @@ abstract class YarnBasics : NpmApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resolveDependency(
|
|
||||||
npmResolution: KotlinCompilationNpmResolution,
|
|
||||||
dependency: NpmDependency,
|
|
||||||
transitive: Boolean
|
|
||||||
): Set<File> {
|
|
||||||
val files = (if (transitive) {
|
|
||||||
transitiveResolvedDependencies
|
|
||||||
} else {
|
|
||||||
nonTransitiveResolvedDependencies
|
|
||||||
})[dependency]
|
|
||||||
|
|
||||||
if (files != null) {
|
|
||||||
return files
|
|
||||||
}
|
|
||||||
|
|
||||||
val npmProject = npmResolution.npmProject
|
|
||||||
|
|
||||||
val all = mutableSetOf<File>()
|
|
||||||
|
|
||||||
npmProject.resolve(dependency.key)?.let {
|
|
||||||
if (it.isFile) all.add(it)
|
|
||||||
if (it.path.endsWith(".js")) {
|
|
||||||
val baseName = it.path.removeSuffix(".js")
|
|
||||||
val metaJs = File(baseName + ".meta.js")
|
|
||||||
if (metaJs.isFile) all.add(metaJs)
|
|
||||||
val kjsmDir = File(baseName)
|
|
||||||
if (kjsmDir.isDirectory) {
|
|
||||||
kjsmDir.walkTopDown()
|
|
||||||
.filter { it.extension == "kjsm" }
|
|
||||||
.forEach { all.add(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nonTransitiveResolvedDependencies[dependency] = all
|
|
||||||
|
|
||||||
if (transitive) {
|
|
||||||
dependency.dependencies.forEach {
|
|
||||||
resolveDependency(
|
|
||||||
npmResolution,
|
|
||||||
it,
|
|
||||||
transitive
|
|
||||||
).also { files ->
|
|
||||||
all.addAll(files)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
transitiveResolvedDependencies[dependency] = all
|
|
||||||
}
|
|
||||||
|
|
||||||
return all
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun yarnLockReadTransitiveDependencies(
|
|
||||||
nodeWorkDir: File,
|
|
||||||
srcDependenciesList: Collection<NpmDependency>
|
|
||||||
) {
|
|
||||||
val yarnLock = nodeWorkDir
|
|
||||||
.resolve("yarn.lock")
|
|
||||||
.takeIf { it.isFile }
|
|
||||||
?: return
|
|
||||||
|
|
||||||
val entryRegistry = YarnEntryRegistry(yarnLock)
|
|
||||||
val visited = mutableMapOf<NpmDependency, NpmDependency>()
|
|
||||||
|
|
||||||
fun resolveRecursively(src: NpmDependency) {
|
|
||||||
if (src.scope == PEER) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val copy = visited[src]
|
|
||||||
if (copy != null) {
|
|
||||||
src.resolvedVersion = copy.resolvedVersion
|
|
||||||
src.integrity = copy.integrity
|
|
||||||
src.dependencies.addAll(copy.dependencies)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
visited[src] = src
|
|
||||||
|
|
||||||
val deps = entryRegistry.find(src.key, src.version)
|
|
||||||
|
|
||||||
src.resolvedVersion = deps.version
|
|
||||||
src.integrity = deps.integrity
|
|
||||||
|
|
||||||
deps.dependencies.mapTo(src.dependencies) { dep ->
|
|
||||||
val scopedName = dep.scopedName
|
|
||||||
val child = NpmDependency(
|
|
||||||
project = src.project,
|
|
||||||
name = scopedName.toString(),
|
|
||||||
version = dep.version ?: "*"
|
|
||||||
)
|
|
||||||
child.parent = src
|
|
||||||
|
|
||||||
resolveRecursively(child)
|
|
||||||
|
|
||||||
child
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
srcDependenciesList.forEach { src ->
|
|
||||||
resolveRecursively(src)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
-50
@@ -11,56 +11,6 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.includedRange
|
|||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.intersect
|
import org.jetbrains.kotlin.gradle.targets.js.npm.intersect
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal class YarnEntryRegistry(private val lockFile: File) {
|
|
||||||
private val entryMap = YarnLock.parse(lockFile)
|
|
||||||
.entries
|
|
||||||
.associateBy { it.dependencyKey }
|
|
||||||
|
|
||||||
fun find(packageKey: String, version: String): YarnLock.Entry {
|
|
||||||
val key = dependencyKey(packageKey, version)
|
|
||||||
val entry = entryMap[key]
|
|
||||||
|
|
||||||
if (entry != null) {
|
|
||||||
return entry
|
|
||||||
}
|
|
||||||
|
|
||||||
entryMap.entries
|
|
||||||
.firstOrNull { (_, entry) ->
|
|
||||||
if (entry.version == null) {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
(includedRange(version) intersect includedRange(entry.version)) != null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?.let { return it.value }
|
|
||||||
|
|
||||||
throw GradleException(
|
|
||||||
"Cannot find $key in yarn.lock"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val YarnLock.Entry.dependencyKey: String
|
|
||||||
get() = key.correctDependencyKey()
|
|
||||||
|
|
||||||
private fun dependencyKey(packageKey: String, version: String) =
|
|
||||||
YarnLock.dependencyKey(packageKey, version).correctDependencyKey()
|
|
||||||
|
|
||||||
private fun String.correctDependencyKey(): String =
|
|
||||||
when {
|
|
||||||
GITHUB_MARKER in this -> replace(GITHUB_MARKER, SEPARATOR)
|
|
||||||
FILE_MARKER in this -> {
|
|
||||||
val location = substringAfter(FILE_MARKER)
|
|
||||||
val path = lockFile
|
|
||||||
.parentFile
|
|
||||||
.resolve(location)
|
|
||||||
.canonicalPath
|
|
||||||
|
|
||||||
replaceAfter(FILE_MARKER, path)
|
|
||||||
}
|
|
||||||
else -> this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val SEPARATOR = "@"
|
private const val SEPARATOR = "@"
|
||||||
|
|
||||||
private const val FILE_MARKER = "${SEPARATOR}$FILE_VERSION_PREFIX"
|
private const val FILE_MARKER = "${SEPARATOR}$FILE_VERSION_PREFIX"
|
||||||
|
|||||||
+2
-2
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
|
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.Serializable
|
|
||||||
|
|
||||||
data class YarnEnv(
|
data class YarnEnv(
|
||||||
val downloadUrl: String,
|
val downloadUrl: String,
|
||||||
@@ -20,4 +19,5 @@ data class YarnEnv(
|
|||||||
val yarnLockMismatchReport: YarnLockMismatchReport,
|
val yarnLockMismatchReport: YarnLockMismatchReport,
|
||||||
val reportNewYarnLock: Boolean,
|
val reportNewYarnLock: Boolean,
|
||||||
val yarnLockAutoReplace: Boolean,
|
val yarnLockAutoReplace: Boolean,
|
||||||
) : Serializable
|
val yarnResolutions: List<YarnResolution>
|
||||||
|
)
|
||||||
|
|||||||
+2
-2
@@ -11,12 +11,12 @@ 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.PackageJson
|
import org.jetbrains.kotlin.gradle.targets.js.npm.PackageJson
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.fileVersion
|
import org.jetbrains.kotlin.gradle.targets.js.npm.fileVersion
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.PreparedKotlinCompilationNpmResolution
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class YarnImportedPackagesVersionResolver(
|
class YarnImportedPackagesVersionResolver(
|
||||||
private val logger: Logger,
|
private val logger: Logger,
|
||||||
private val npmProjects: Collection<KotlinCompilationNpmResolution>,
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
private val nodeJsWorldDir: File
|
private val nodeJsWorldDir: File
|
||||||
) {
|
) {
|
||||||
private val resolvedVersion = mutableMapOf<String, ResolvedNpmDependency>()
|
private val resolvedVersion = mutableMapOf<String, ResolvedNpmDependency>()
|
||||||
|
|||||||
-154
@@ -1,154 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.targets.js.yarn
|
|
||||||
|
|
||||||
import com.google.gson.stream.JsonReader
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.PackageJson
|
|
||||||
import java.io.File
|
|
||||||
import java.io.StringReader
|
|
||||||
|
|
||||||
data class YarnLock(val entries: List<Entry>) {
|
|
||||||
data class Entry(
|
|
||||||
val key: String,
|
|
||||||
val version: String?,
|
|
||||||
val resolved: String?,
|
|
||||||
val integrity: String?,
|
|
||||||
val dependencies: List<Dependency>
|
|
||||||
)
|
|
||||||
|
|
||||||
data class Dependency(val key: String, val version: String?) {
|
|
||||||
val scopedName: PackageJson.ScopedName
|
|
||||||
get() = PackageJson.scopedName(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun dependencyKey(packageKey: String, version: String) = "$packageKey@$version"
|
|
||||||
|
|
||||||
private class Node(val parent: Node?, val value: String? = null) {
|
|
||||||
var indent: String? = null
|
|
||||||
val children = mutableMapOf<String, Node>()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun parse(yarnLock: File): YarnLock {
|
|
||||||
val root = parseTree(yarnLock)
|
|
||||||
|
|
||||||
return YarnLock(root.children.map {
|
|
||||||
val values = it.value.children
|
|
||||||
Entry(
|
|
||||||
it.key,
|
|
||||||
values["version"]?.value,
|
|
||||||
values["resolved"]?.value,
|
|
||||||
values["integrity"]?.value,
|
|
||||||
values["dependencies"]?.children?.map { dep ->
|
|
||||||
Dependency(dep.key, dep.value.value)
|
|
||||||
} ?: listOf()
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseTree(yarnLock: File): Node {
|
|
||||||
val root = Node(null)
|
|
||||||
var parent = root
|
|
||||||
var onNewLevel = true
|
|
||||||
yarnLock.useLines {
|
|
||||||
it.forEach { line ->
|
|
||||||
if (!line.startsWith("#")) {
|
|
||||||
var i = 0
|
|
||||||
while (i < line.length && line[i].isWhitespace()) i++
|
|
||||||
val indentPos = i
|
|
||||||
val indent = line.substring(0, indentPos)
|
|
||||||
|
|
||||||
val key = line.endsWith(":")
|
|
||||||
|
|
||||||
if (line.isNotEmpty()) {
|
|
||||||
val values = parseLine(line, indentPos)
|
|
||||||
|
|
||||||
if (onNewLevel) {
|
|
||||||
parent.indent = indent
|
|
||||||
onNewLevel = false
|
|
||||||
} else {
|
|
||||||
while (indent != parent.indent!!) {
|
|
||||||
parent = parent.parent!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val child = Node(parent, if (values.size > 1) values[1] else null)
|
|
||||||
if (key) {
|
|
||||||
values.forEach {
|
|
||||||
parent.children[it] = child
|
|
||||||
}
|
|
||||||
parent = child
|
|
||||||
onNewLevel = true
|
|
||||||
} else {
|
|
||||||
parent.children[values[0]] = child
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return root
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseLine(line: String, indentPos: Int): List<String> {
|
|
||||||
val quotedLineResult = replaceQuoted(line.removeSuffix(":"))
|
|
||||||
|
|
||||||
return quotedLineResult
|
|
||||||
.parse(indentPos)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun replaceQuoted(line: String): QuotedLineResult {
|
|
||||||
var result: String = line
|
|
||||||
val quotedValues = QUOTED_VALUE.findAll(line)
|
|
||||||
.flatMap { it.groupValues.drop(1).asSequence() }
|
|
||||||
.toList()
|
|
||||||
|
|
||||||
quotedValues.forEachIndexed { index, item ->
|
|
||||||
result = result.replace(
|
|
||||||
"""
|
|
||||||
"$item"
|
|
||||||
""".trimIndent(),
|
|
||||||
"""
|
|
||||||
"$$index"
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return QuotedLineResult(
|
|
||||||
result,
|
|
||||||
quotedValues
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private data class QuotedLineResult(
|
|
||||||
val value: String,
|
|
||||||
val quotedValues: List<String>
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun QuotedLineResult.parse(indentPos: Int): List<String> {
|
|
||||||
return value
|
|
||||||
.substring(indentPos)
|
|
||||||
.split(" ")
|
|
||||||
.map { value ->
|
|
||||||
val withoutComma = value.removeSuffix(",")
|
|
||||||
if (withoutComma.startsWith("\"")) {
|
|
||||||
val (index) = QUOTED_PLACEHOLDER.find(withoutComma)!!.destructured
|
|
||||||
val restoredValue = """
|
|
||||||
"${quotedValues[index.toInt()]}"
|
|
||||||
""".trimIndent()
|
|
||||||
|
|
||||||
try {
|
|
||||||
JsonReader(StringReader(restoredValue)).nextString()
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
restoredValue.removePrefix("\"").removeSuffix("\"")
|
|
||||||
}
|
|
||||||
} else withoutComma
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val QUOTED_VALUE = """"(.+?)"""".toRegex()
|
|
||||||
private val QUOTED_PLACEHOLDER = """\$(\d+)""".toRegex()
|
|
||||||
+18
-4
@@ -11,6 +11,8 @@ import org.gradle.api.tasks.TaskProvider
|
|||||||
import org.jetbrains.kotlin.gradle.utils.markResolvable
|
import org.jetbrains.kotlin.gradle.utils.markResolvable
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector
|
import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNpmResolutionManager
|
||||||
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.resolver.implementing
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.implementing
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask
|
import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask
|
||||||
@@ -30,10 +32,12 @@ open class YarnPlugin : Plugin<Project> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val yarnRootExtension = this.extensions.create(YarnRootExtension.YARN, YarnRootExtension::class.java, this)
|
val yarnRootExtension = this.extensions.create(YarnRootExtension.YARN, YarnRootExtension::class.java, this)
|
||||||
val nodeJs = NodeJsRootPlugin.apply(this)
|
NodeJsRootPlugin.apply(project)
|
||||||
|
val nodeJs = this.kotlinNodeJsExtension
|
||||||
|
val nodeJsTaskProviders = this.kotlinNodeJsExtension
|
||||||
|
|
||||||
val setupTask = registerTask<YarnSetupTask>(YarnSetupTask.NAME) {
|
val setupTask = registerTask<YarnSetupTask>(YarnSetupTask.NAME) {
|
||||||
it.dependsOn(nodeJs.nodeJsSetupTaskProvider)
|
it.dependsOn(nodeJsTaskProviders.nodeJsSetupTaskProvider)
|
||||||
|
|
||||||
it.configuration = provider {
|
it.configuration = provider {
|
||||||
this.project.configurations.detachedConfiguration(this.project.dependencies.create(it.ivyDependency))
|
this.project.configurations.detachedConfiguration(this.project.dependencies.create(it.ivyDependency))
|
||||||
@@ -43,9 +47,19 @@ open class YarnPlugin : Plugin<Project> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val rootPackageJson = tasks.register(RootPackageJsonTask.NAME, RootPackageJsonTask::class.java) { task ->
|
val rootPackageJson = tasks.register(RootPackageJsonTask.NAME, RootPackageJsonTask::class.java) { task ->
|
||||||
task.dependsOn(nodeJs.npmCachesSetupTaskProvider)
|
task.dependsOn(nodeJsTaskProviders.npmCachesSetupTaskProvider)
|
||||||
task.group = NodeJsRootPlugin.TASKS_GROUP_NAME
|
task.group = NodeJsRootPlugin.TASKS_GROUP_NAME
|
||||||
task.description = "Create root package.json"
|
task.description = "Create root package.json"
|
||||||
|
|
||||||
|
task.npmResolutionManager.apply {
|
||||||
|
set(project.kotlinNpmResolutionManager)
|
||||||
|
disallowChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
task.onlyIf {
|
||||||
|
it as RootPackageJsonTask
|
||||||
|
it.npmResolutionManager.get().isConfiguringState()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configureRequiresNpmDependencies(project, rootPackageJson)
|
configureRequiresNpmDependencies(project, rootPackageJson)
|
||||||
@@ -62,7 +76,7 @@ open class YarnPlugin : Plugin<Project> {
|
|||||||
it.description = "Clean unused local yarn version"
|
it.description = "Clean unused local yarn version"
|
||||||
}
|
}
|
||||||
|
|
||||||
val packageJsonUmbrella = nodeJs
|
val packageJsonUmbrella = nodeJsTaskProviders
|
||||||
.packageJsonUmbrellaTaskProvider
|
.packageJsonUmbrellaTaskProvider
|
||||||
|
|
||||||
yarnRootExtension.rootPackageJsonTaskProvider.configure {
|
yarnRootExtension.rootPackageJsonTaskProvider.configure {
|
||||||
|
|||||||
+2
-29
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.PlatformHelper
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.PlatformHelper
|
||||||
import org.gradle.api.Action
|
import org.gradle.api.Action
|
||||||
import org.gradle.api.Incubating
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.tasks.TaskProvider
|
import org.gradle.api.tasks.TaskProvider
|
||||||
import org.jetbrains.kotlin.gradle.internal.ConfigurationPhaseAware
|
import org.jetbrains.kotlin.gradle.internal.ConfigurationPhaseAware
|
||||||
@@ -20,7 +19,6 @@ import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
open class YarnRootExtension(
|
open class YarnRootExtension(
|
||||||
@Transient
|
|
||||||
val project: Project
|
val project: Project
|
||||||
) : ConfigurationPhaseAware<YarnEnv>() {
|
) : ConfigurationPhaseAware<YarnEnv>() {
|
||||||
init {
|
init {
|
||||||
@@ -60,7 +58,7 @@ open class YarnRootExtension(
|
|||||||
.withType(RootPackageJsonTask::class.java)
|
.withType(RootPackageJsonTask::class.java)
|
||||||
.named(RootPackageJsonTask.NAME)
|
.named(RootPackageJsonTask.NAME)
|
||||||
|
|
||||||
var resolutions: MutableList<YarnResolution> = mutableListOf()
|
var resolutions: MutableList<YarnResolution> by Property(mutableListOf())
|
||||||
|
|
||||||
fun resolution(path: String, configure: Action<YarnResolution>) {
|
fun resolution(path: String, configure: Action<YarnResolution>) {
|
||||||
resolutions.add(
|
resolutions.add(
|
||||||
@@ -75,21 +73,6 @@ open class YarnRootExtension(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Incubating
|
|
||||||
fun disableGranularWorkspaces() {
|
|
||||||
val packageJsonUmbrella = NodeJsRootPlugin.apply(project)
|
|
||||||
.packageJsonUmbrellaTaskProvider
|
|
||||||
|
|
||||||
rootPackageJsonTaskProvider.configure {
|
|
||||||
it.dependsOn(packageJsonUmbrella)
|
|
||||||
}
|
|
||||||
|
|
||||||
project.allprojects
|
|
||||||
.forEach {
|
|
||||||
it.tasks.implementing(RequiresNpmDependencies::class).all {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun finalizeConfiguration(): YarnEnv {
|
override fun finalizeConfiguration(): YarnEnv {
|
||||||
val cleanableStore = CleanableStore[installationDir.path]
|
val cleanableStore = CleanableStore[installationDir.path]
|
||||||
|
|
||||||
@@ -116,20 +99,10 @@ open class YarnRootExtension(
|
|||||||
yarnLockMismatchReport = yarnLockMismatchReport,
|
yarnLockMismatchReport = yarnLockMismatchReport,
|
||||||
reportNewYarnLock = reportNewYarnLock,
|
reportNewYarnLock = reportNewYarnLock,
|
||||||
yarnLockAutoReplace = yarnLockAutoReplace,
|
yarnLockAutoReplace = yarnLockAutoReplace,
|
||||||
|
yarnResolutions = resolutions
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun executeSetup() {
|
|
||||||
NodeJsRootPlugin.apply(project).executeSetup()
|
|
||||||
|
|
||||||
if (!download) return
|
|
||||||
|
|
||||||
val yarnSetupTask = yarnSetupTaskProvider.get()
|
|
||||||
yarnSetupTask.actions.forEach {
|
|
||||||
it.execute(yarnSetupTask)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val YARN: String = "kotlinYarn"
|
const val YARN: String = "kotlinYarn"
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn
|
|||||||
|
|
||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.artifacts.Configuration
|
import org.gradle.api.artifacts.Configuration
|
||||||
|
import org.gradle.api.file.ArchiveOperations
|
||||||
import org.gradle.api.file.FileSystemOperations
|
import org.gradle.api.file.FileSystemOperations
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.*
|
||||||
@@ -15,24 +16,23 @@ import org.jetbrains.kotlin.gradle.logging.kotlinInfo
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.extractWithUpToDate
|
import org.jetbrains.kotlin.gradle.targets.js.extractWithUpToDate
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin
|
||||||
import org.jetbrains.kotlin.gradle.utils.ArchiveOperationsCompat
|
|
||||||
import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
|
import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
open class YarnSetupTask : DefaultTask() {
|
abstract class YarnSetupTask : DefaultTask() {
|
||||||
@Transient
|
@Transient
|
||||||
private val settings = project.yarn
|
private val settings = project.yarn
|
||||||
private val env by lazy { settings.requireConfigured() }
|
private val env by lazy { settings.requireConfigured() }
|
||||||
|
|
||||||
private val shouldDownload = settings.download
|
private val shouldDownload = settings.download
|
||||||
|
|
||||||
private val archiveOperations = ArchiveOperationsCompat(project)
|
@get:Inject
|
||||||
|
abstract internal val archiveOperations: ArchiveOperations
|
||||||
|
|
||||||
@get:Inject
|
@get:Inject
|
||||||
internal open val fileHasher: FileHasher
|
abstract internal val fileHasher: FileHasher
|
||||||
get() = error("Should be injected")
|
|
||||||
|
|
||||||
@get:Inject
|
@get:Inject
|
||||||
internal open val fs: FileSystemOperations
|
internal open val fs: FileSystemOperations
|
||||||
|
|||||||
+8
-19
@@ -5,14 +5,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.targets.js.yarn
|
package org.jetbrains.kotlin.gradle.targets.js.yarn
|
||||||
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.internal.service.ServiceRegistry
|
import org.gradle.internal.service.ServiceRegistry
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
|
import org.jetbrains.kotlin.gradle.targets.js.npm.*
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmEnvironment
|
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.PreparedKotlinCompilationNpmResolution
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.PackageJson
|
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class YarnWorkspaces : YarnBasics() {
|
class YarnWorkspaces : YarnBasics() {
|
||||||
@@ -25,18 +21,13 @@ class YarnWorkspaces : YarnBasics() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun prepareRootProject(
|
override fun prepareRootProject(
|
||||||
rootProject: Project?,
|
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NpmEnvironment,
|
||||||
rootProjectName: String,
|
rootProjectName: String,
|
||||||
rootProjectVersion: String,
|
rootProjectVersion: String,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
subProjects: Collection<KotlinCompilationNpmResolution>,
|
subProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
resolutions: Map<String, String>,
|
resolutions: Map<String, String>,
|
||||||
forceFullResolve: Boolean
|
|
||||||
) {
|
) {
|
||||||
if (forceFullResolve) {
|
|
||||||
rootProject?.let { setup(it) }
|
|
||||||
}
|
|
||||||
return prepareRootPackageJson(
|
return prepareRootPackageJson(
|
||||||
nodeJs,
|
nodeJs,
|
||||||
rootProjectName,
|
rootProjectName,
|
||||||
@@ -52,7 +43,7 @@ class YarnWorkspaces : YarnBasics() {
|
|||||||
rootProjectName: String,
|
rootProjectName: String,
|
||||||
rootProjectVersion: String,
|
rootProjectVersion: String,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
npmProjects: Collection<KotlinCompilationNpmResolution>,
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
resolutions: Map<String, String>
|
resolutions: Map<String, String>
|
||||||
) {
|
) {
|
||||||
val rootPackageJsonFile = preparedFiles(nodeJs).single()
|
val rootPackageJsonFile = preparedFiles(nodeJs).single()
|
||||||
@@ -71,8 +62,8 @@ class YarnWorkspaces : YarnBasics() {
|
|||||||
services: ServiceRegistry,
|
services: ServiceRegistry,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
nodeJs: NpmEnvironment,
|
nodeJs: NpmEnvironment,
|
||||||
yarn: YarnEnv,
|
yarn: YarnEnvironment,
|
||||||
npmProjects: Collection<KotlinCompilationNpmResolution>,
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
cliArgs: List<String>
|
cliArgs: List<String>
|
||||||
) {
|
) {
|
||||||
val nodeJsWorldDir = nodeJs.rootPackageDir
|
val nodeJsWorldDir = nodeJs.rootPackageDir
|
||||||
@@ -86,15 +77,13 @@ class YarnWorkspaces : YarnBasics() {
|
|||||||
NpmApi.resolveOperationDescription("yarn"),
|
NpmApi.resolveOperationDescription("yarn"),
|
||||||
cliArgs
|
cliArgs
|
||||||
)
|
)
|
||||||
|
|
||||||
yarnLockReadTransitiveDependencies(nodeJsWorldDir, npmProjects.flatMap { it.externalNpmDependencies })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveRootProjectWorkspacesPackageJson(
|
private fun saveRootProjectWorkspacesPackageJson(
|
||||||
rootProjectName: String,
|
rootProjectName: String,
|
||||||
rootProjectVersion: String,
|
rootProjectVersion: String,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
npmProjects: Collection<KotlinCompilationNpmResolution>,
|
npmProjects: Collection<PreparedKotlinCompilationNpmResolution>,
|
||||||
resolutions: Map<String, String>,
|
resolutions: Map<String, String>,
|
||||||
rootPackageJsonFile: File
|
rootPackageJsonFile: File
|
||||||
) {
|
) {
|
||||||
@@ -102,7 +91,7 @@ class YarnWorkspaces : YarnBasics() {
|
|||||||
val rootPackageJson = PackageJson(rootProjectName, rootProjectVersion)
|
val rootPackageJson = PackageJson(rootProjectName, rootProjectVersion)
|
||||||
rootPackageJson.private = true
|
rootPackageJson.private = true
|
||||||
|
|
||||||
val npmProjectWorkspaces = npmProjects.map { it.npmProject.dir.relativeTo(nodeJsWorldDir).path }
|
val npmProjectWorkspaces = npmProjects.map { it.npmProjectDir.relativeTo(nodeJsWorldDir).path }
|
||||||
val importedProjectWorkspaces =
|
val importedProjectWorkspaces =
|
||||||
YarnImportedPackagesVersionResolver(logger, npmProjects, nodeJsWorldDir).resolveAndUpdatePackages()
|
YarnImportedPackagesVersionResolver(logger, npmProjects, nodeJsWorldDir).resolveAndUpdatePackages()
|
||||||
|
|
||||||
|
|||||||
-39
@@ -53,45 +53,6 @@ internal fun checkGradleCompatibility(
|
|||||||
internal val AbstractArchiveTask.archivePathCompatible: File
|
internal val AbstractArchiveTask.archivePathCompatible: File
|
||||||
get() = archiveFile.get().asFile
|
get() = archiveFile.get().asFile
|
||||||
|
|
||||||
internal class ArchiveOperationsCompat(@Transient private val project: Project) : Serializable {
|
|
||||||
private val archiveOperations: Any? = try {
|
|
||||||
(project as ProjectInternal).services.get(ArchiveOperations::class.java)
|
|
||||||
} catch (e: NoClassDefFoundError) {
|
|
||||||
// Gradle version < 6.6
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun zipTree(obj: Any): FileTree {
|
|
||||||
return when (archiveOperations) {
|
|
||||||
is ArchiveOperations -> archiveOperations.zipTree(obj)
|
|
||||||
else -> project.zipTree(obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun tarTree(obj: Any): FileTree {
|
|
||||||
return when (archiveOperations) {
|
|
||||||
is ArchiveOperations -> archiveOperations.tarTree(obj)
|
|
||||||
else -> project.tarTree(obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class FileSystemOperationsCompat(@Transient private val project: Project) : Serializable {
|
|
||||||
private val fileSystemOperations: Any? = try {
|
|
||||||
(project as ProjectInternal).services.get(FileSystemOperations::class.java)
|
|
||||||
} catch (e: NoClassDefFoundError) {
|
|
||||||
// Gradle version < 6.0
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun copy(action: (CopySpec) -> Unit): WorkResult? {
|
|
||||||
return when (fileSystemOperations) {
|
|
||||||
is FileSystemOperations -> fileSystemOperations.copy(action)
|
|
||||||
else -> project.copy(action)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gradle dropped out getOwnerBuildOperationId. Workaround to build correct plugin for Gradle < 6.8
|
// Gradle dropped out getOwnerBuildOperationId. Workaround to build correct plugin for Gradle < 6.8
|
||||||
// See https://github.com/gradle/gradle/commit/0296f4441ae69ad608cfef6a90fef3fdf314fa2c
|
// See https://github.com/gradle/gradle/commit/0296f4441ae69ad608cfef6a90fef3fdf314fa2c
|
||||||
internal interface LegacyTestDescriptorInternal : TestDescriptor {
|
internal interface LegacyTestDescriptorInternal : TestDescriptor {
|
||||||
|
|||||||
Reference in New Issue
Block a user