[Gradle, JS] Replace close on prepare
#KT-34832 fixed
This commit is contained in:
+1
-5
@@ -19,7 +19,7 @@ internal class DukatRootResolverPlugin(val resolver: KotlinRootNpmResolver) : Ro
|
||||
return listOf(plugin)
|
||||
}
|
||||
|
||||
override fun resolve(resolution: KotlinRootNpmResolution) {
|
||||
override fun close(resolution: KotlinRootNpmResolution) {
|
||||
if (resolver.forceFullResolve) {
|
||||
// inside idea import
|
||||
compilations.forEach {
|
||||
@@ -27,8 +27,4 @@ internal class DukatRootResolverPlugin(val resolver: KotlinRootNpmResolver) : Ro
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close(resolution: KotlinRootNpmResolution) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
+48
-54
@@ -93,12 +93,25 @@ class KotlinNpmResolutionManager(private val nodeJsSettings: NodeJsRootExtension
|
||||
get() = resolver.compilations.map { it.npmProject }
|
||||
}
|
||||
|
||||
open class Prepared(val resolved: KotlinRootNpmResolution) : ResolutionState() {
|
||||
open class Prepared(val preparedInstallation: KotlinRootNpmResolver.Installation) : ResolutionState() {
|
||||
override val npmProjects: List<NpmProject>
|
||||
get() = resolved.projects.values.flatMap { it.npmProjects.map { it.npmProject } }
|
||||
get() = npmProjectsByProjectResolutions(preparedInstallation.projectResolutions)
|
||||
}
|
||||
|
||||
class Installed(resolved: KotlinRootNpmResolution) : Prepared(resolved)
|
||||
class Installed(val resolved: KotlinRootNpmResolution) : ResolutionState() {
|
||||
override val npmProjects: List<NpmProject>
|
||||
get() = npmProjectsByProjectResolutions(resolved.projects)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun npmProjectsByProjectResolutions(
|
||||
resolutions: Map<Project, KotlinProjectNpmResolution>
|
||||
): List<NpmProject> {
|
||||
return resolutions
|
||||
.values
|
||||
.flatMap { it.npmProjects.map { it.npmProject } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Incubating
|
||||
@@ -107,49 +120,29 @@ class KotlinNpmResolutionManager(private val nodeJsSettings: NodeJsRootExtension
|
||||
internal fun requireConfiguringState(): KotlinRootNpmResolver =
|
||||
(this.state as? ResolutionState.Configuring ?: error("NPM Dependencies already resolved and installed")).resolver
|
||||
|
||||
internal fun prepare() = prepareIfNeeded(requireNotInstalled = true)
|
||||
internal fun prepare() = prepareIfNeeded(requireNotPrepared = true)
|
||||
|
||||
internal fun installIfNeeded(
|
||||
reason: String = "",
|
||||
reason: String? = "",
|
||||
args: List<String> = emptyList()
|
||||
): KotlinRootNpmResolution {
|
||||
if (state is ResolutionState.Installed) {
|
||||
return (state as ResolutionState.Installed).resolved
|
||||
synchronized(this) {
|
||||
if (state is ResolutionState.Installed) {
|
||||
return (state as ResolutionState.Installed).resolved
|
||||
}
|
||||
|
||||
val installUpToDate = nodeJsSettings.npmInstallTask.state.upToDate
|
||||
val forceUpToDate = installUpToDate && !forceFullResolve
|
||||
|
||||
val installation = prepareIfNeeded(requireUpToDateReason = reason)
|
||||
val resolution = installation
|
||||
.install(forceUpToDate, args)
|
||||
state = ResolutionState.Installed(resolution)
|
||||
|
||||
installation.closePlugins(resolution)
|
||||
|
||||
return resolution
|
||||
}
|
||||
|
||||
val installUpToDate = nodeJsSettings.npmInstallTask.state.upToDate
|
||||
val forceUpToDate = installUpToDate && !forceFullResolve
|
||||
|
||||
val npmResolution = prepareIfNeeded(requireUpToDateReason = reason)
|
||||
val npmResolutions = npmResolution
|
||||
.projects
|
||||
.values
|
||||
.flatMap { it.npmProjects }
|
||||
|
||||
// we need manual up-to-date checking to avoid call package manager during
|
||||
// idea import if nothing was changed
|
||||
// we should call it even kotlinNpmInstall task is up-to-date (skipPackageManager is true)
|
||||
// because our upToDateChecks saves state for next execution
|
||||
val upToDateChecks = npmResolutions.map {
|
||||
PackageJsonUpToDateCheck(it.npmProject)
|
||||
}
|
||||
val upToDate = forceUpToDate || upToDateChecks.all { it.upToDate }
|
||||
|
||||
nodeJsSettings.packageManager.resolveRootProject(
|
||||
nodeJsSettings.rootProject,
|
||||
npmResolutions,
|
||||
upToDate,
|
||||
args
|
||||
)
|
||||
|
||||
upToDateChecks.forEach { it.commit() }
|
||||
|
||||
return ResolutionState.Installed((state as ResolutionState.Prepared).resolved)
|
||||
.apply {
|
||||
state = this
|
||||
npmResolution.plugins
|
||||
.forEach { it.resolve(npmResolution) }
|
||||
}.resolved
|
||||
}
|
||||
|
||||
internal fun requireAlreadyInstalled(project: Project, reason: String = ""): KotlinProjectNpmResolution =
|
||||
@@ -161,39 +154,40 @@ class KotlinNpmResolutionManager(private val nodeJsSettings: NodeJsRootExtension
|
||||
/**
|
||||
* @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 requireNotInstalled Check that project is not resolved
|
||||
* @param requireNotPrepared Check that project is not prepared
|
||||
*/
|
||||
private fun prepareIfNeeded(
|
||||
requireUpToDateReason: String? = null,
|
||||
requireNotInstalled: Boolean = false
|
||||
): KotlinRootNpmResolution {
|
||||
fun alreadyResolved(resolution: KotlinRootNpmResolution): KotlinRootNpmResolution {
|
||||
if (requireNotInstalled) error("Project already resolved")
|
||||
return resolution
|
||||
requireNotPrepared: Boolean = false
|
||||
): KotlinRootNpmResolver.Installation {
|
||||
fun alreadyResolved(installation: KotlinRootNpmResolver.Installation): KotlinRootNpmResolver.Installation {
|
||||
if (requireNotPrepared) error("Project already prepared")
|
||||
return installation
|
||||
}
|
||||
|
||||
val state0 = this.state
|
||||
return when (state0) {
|
||||
is ResolutionState.Prepared -> alreadyResolved(state0.resolved)
|
||||
is ResolutionState.Prepared -> alreadyResolved(state0.preparedInstallation)
|
||||
is ResolutionState.Configuring -> {
|
||||
synchronized(this) {
|
||||
val state1 = this.state
|
||||
when (state1) {
|
||||
is ResolutionState.Prepared -> alreadyResolved(state1.resolved)
|
||||
is ResolutionState.Prepared -> alreadyResolved(state1.preparedInstallation)
|
||||
is ResolutionState.Configuring -> {
|
||||
val upToDate = nodeJsSettings.rootPackageJsonTask.state.upToDate
|
||||
if (requireUpToDateReason != null && !upToDate) {
|
||||
error("NPM dependencies should be resolved $requireUpToDateReason")
|
||||
}
|
||||
|
||||
state1.resolver.close().also {
|
||||
state1.resolver.prepareInstallation().also {
|
||||
this.state = ResolutionState.Prepared(it)
|
||||
state1.resolver.closePlugins(it)
|
||||
}
|
||||
}
|
||||
is ResolutionState.Installed -> error("Project already installed")
|
||||
}
|
||||
}
|
||||
}
|
||||
is ResolutionState.Installed -> error("Project already installed")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,19 +196,19 @@ class KotlinNpmResolutionManager(private val nodeJsSettings: NodeJsRootExtension
|
||||
|
||||
val resolvedProject =
|
||||
if (forceFullResolve) {
|
||||
prepareIfNeeded()
|
||||
installIfNeeded()[project]
|
||||
installIfNeeded(reason = null)[project]
|
||||
} else {
|
||||
// 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)
|
||||
val state0 = state
|
||||
when (state0) {
|
||||
is ResolutionState.Prepared -> state0.resolved[project]
|
||||
is ResolutionState.Prepared -> state0.preparedInstallation[project]
|
||||
is ResolutionState.Configuring -> {
|
||||
return null
|
||||
//error("Cannot use NpmDependency before :kotlinNpmInstall task execution")
|
||||
}
|
||||
is ResolutionState.Installed -> state0.resolved[project]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -10,6 +10,5 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinCompilationNpmR
|
||||
|
||||
internal interface RootResolverPlugin {
|
||||
fun createCompilationResolverPlugins(resolver: KotlinCompilationNpmResolver): List<CompilationResolverPlugin>
|
||||
fun resolve(resolution: KotlinRootNpmResolution)
|
||||
fun close(resolution: KotlinRootNpmResolution)
|
||||
}
|
||||
+1
-3
@@ -6,12 +6,10 @@
|
||||
package org.jetbrains.kotlin.gradle.targets.js.npm.resolved
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.jetbrains.kotlin.gradle.targets.js.npm.plugins.RootResolverPlugin
|
||||
|
||||
internal class KotlinRootNpmResolution(
|
||||
val rootProject: Project,
|
||||
val projects: Map<Project, KotlinProjectNpmResolution>,
|
||||
val plugins: List<RootResolverPlugin>
|
||||
internal val projects: Map<Project, KotlinProjectNpmResolution>
|
||||
) {
|
||||
operator fun get(project: Project) = projects[project] ?: KotlinProjectNpmResolution.empty(project)
|
||||
}
|
||||
+74
-22
@@ -15,8 +15,10 @@ import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension
|
||||
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.PackageJsonUpToDateCheck
|
||||
import org.jetbrains.kotlin.gradle.targets.js.npm.plugins.RootResolverPlugin
|
||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinCompilationNpmResolution
|
||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinProjectNpmResolution
|
||||
import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.KotlinRootNpmResolution
|
||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||
|
||||
@@ -36,7 +38,14 @@ internal class KotlinRootNpmResolver internal constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private var closed: Boolean = false
|
||||
enum class State {
|
||||
CONFIGURING,
|
||||
PROJECTS_CLOSED,
|
||||
INSTALLED
|
||||
}
|
||||
|
||||
@Volatile
|
||||
private var state: State = State.CONFIGURING
|
||||
|
||||
val gradleNodeModules = GradleNodeModulesCache(nodeJs)
|
||||
val compositeNodeModules = CompositeNodeModulesCache(nodeJs)
|
||||
@@ -47,7 +56,7 @@ internal class KotlinRootNpmResolver internal constructor(
|
||||
|
||||
@Synchronized
|
||||
fun addProject(target: Project) {
|
||||
check(!closed) { alreadyResolvedMessage("add new project: $target") }
|
||||
check(state == State.CONFIGURING) { alreadyResolvedMessage("add new project: $target") }
|
||||
projectResolvers[target] = KotlinProjectNpmResolver(target, this)
|
||||
}
|
||||
|
||||
@@ -87,32 +96,75 @@ internal class KotlinRootNpmResolver internal constructor(
|
||||
/**
|
||||
* Don't use directly, use [KotlinNpmResolutionManager.installIfNeeded] instead.
|
||||
*/
|
||||
internal fun close(): KotlinRootNpmResolution {
|
||||
check(!closed)
|
||||
closed = true
|
||||
internal fun prepareInstallation(): Installation {
|
||||
synchronized(this@KotlinRootNpmResolver) {
|
||||
check(state == State.CONFIGURING) {
|
||||
"Projects must be configuring"
|
||||
}
|
||||
state = State.PROJECTS_CLOSED
|
||||
|
||||
val projectResolutions = projectResolvers.values
|
||||
.map { it.close() }
|
||||
.associateBy { it.project }
|
||||
val allNpmPackages = projectResolutions.values.flatMap { it.npmProjects }
|
||||
val projectResolutions = projectResolvers.values
|
||||
.map { it.close() }
|
||||
.associateBy { it.project }
|
||||
val allNpmPackages = projectResolutions.values.flatMap { it.npmProjects }
|
||||
|
||||
gradleNodeModules.close()
|
||||
gradleNodeModules.close()
|
||||
|
||||
nodeJs.packageManager.prepareRootProject(
|
||||
rootProject,
|
||||
allNpmPackages
|
||||
)
|
||||
nodeJs.packageManager.prepareRootProject(
|
||||
rootProject,
|
||||
allNpmPackages
|
||||
)
|
||||
|
||||
return KotlinRootNpmResolution(
|
||||
rootProject,
|
||||
projectResolutions,
|
||||
plugins
|
||||
)
|
||||
return Installation(
|
||||
projectResolutions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun closePlugins(resolution: KotlinRootNpmResolution) {
|
||||
plugins.forEach {
|
||||
it.close(resolution)
|
||||
open inner class Installation(val projectResolutions: Map<Project, KotlinProjectNpmResolution>) {
|
||||
operator fun get(project: Project) =
|
||||
projectResolutions[project] ?: KotlinProjectNpmResolution.empty(project)
|
||||
|
||||
internal fun install(
|
||||
forceUpToDate: Boolean,
|
||||
args: List<String>
|
||||
): KotlinRootNpmResolution {
|
||||
synchronized(this@KotlinRootNpmResolver) {
|
||||
check(state == State.PROJECTS_CLOSED) {
|
||||
"Projects must be closed"
|
||||
}
|
||||
state = State.INSTALLED
|
||||
|
||||
val allNpmPackages = projectResolutions
|
||||
.values
|
||||
.flatMap { it.npmProjects }
|
||||
|
||||
// we need manual up-to-date checking to avoid call package manager during
|
||||
// idea import if nothing was changed
|
||||
// we should call it even kotlinNpmInstall task is up-to-date (skipPackageManager is true)
|
||||
// because our upToDateChecks saves state for next execution
|
||||
val upToDateChecks = allNpmPackages.map {
|
||||
PackageJsonUpToDateCheck(it.npmProject)
|
||||
}
|
||||
val upToDate = forceUpToDate || upToDateChecks.all { it.upToDate }
|
||||
|
||||
nodeJs.packageManager.resolveRootProject(
|
||||
nodeJs.rootProject,
|
||||
allNpmPackages,
|
||||
upToDate,
|
||||
args
|
||||
)
|
||||
|
||||
upToDateChecks.forEach { it.commit() }
|
||||
|
||||
return KotlinRootNpmResolution(rootProject, projectResolutions)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun closePlugins(resolution: KotlinRootNpmResolution) {
|
||||
plugins.forEach {
|
||||
it.close(resolution)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user