diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/GradleNodeModulesBuilder.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/GradleNodeModulesBuilder.kt index 2f3f40c4595..1cefa9e8216 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/GradleNodeModulesBuilder.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/GradleNodeModulesBuilder.kt @@ -10,9 +10,7 @@ import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.ResolvedArtifact import org.gradle.api.artifacts.ResolvedDependency import org.gradle.api.artifacts.component.ProjectComponentIdentifier -import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions import org.jetbrains.kotlin.gradle.internal.ProcessedFilesCache -import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation internal class GradleNodeModulesBuilder(val project: Project) : AutoCloseable { companion object { @@ -28,6 +26,8 @@ internal class GradleNodeModulesBuilder(val project: Project) : AutoCloseable { GradleNodeModule(it, dir.resolve(it)) } + val projects = mutableSetOf() + fun visitConfiguration(configuration: Configuration) { if (configuration.isCanBeResolved) { configuration.resolvedConfiguration.firstLevelModuleDependencies.forEach { @@ -57,7 +57,13 @@ internal class GradleNodeModulesBuilder(val project: Project) : AutoCloseable { } artifacts.forEach { artifact -> - if (artifact.id.componentIdentifier !is ProjectComponentIdentifier) { + val componentIdentifier = artifact.id.componentIdentifier + if (componentIdentifier is ProjectComponentIdentifier) { + val dependentProject = project.findProject(componentIdentifier.projectPath) + ?: error("Cannot find project ${componentIdentifier.projectPath}") + + projects.add(dependentProject) + } else { cache.getOrCompute(artifact.file) { lazyDirName } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmDependency.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmDependency.kt index 822c91c1328..ece0b028ea5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmDependency.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmDependency.kt @@ -56,14 +56,14 @@ data class NpmDependency( return when (result) { is AlreadyInProgress -> null is AlreadyResolved -> { - check(this in result.resolution.dependencies) { + check(this in result.resolution.npmPackage!!.npmDependencies) { "Project hierarchy is already resolved in NPM without $this" } result.resolution } is ResolvedNow -> { - check(this in result.resolution.dependencies) { + check(this in result.resolution.npmPackage!!.npmDependencies) { "$this was not visited during resolution" } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolver.kt index 5daa6289aba..5b5eb1816a3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolver.kt @@ -28,7 +28,7 @@ import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile /** * Generates `package.json` file for projects with npm or js dependencies and - * runs selected [NodeJsRootExtension.packageManager] to download and install it. + * runs selected [NodeJsRootExtension.packageManager] to download and install all of it's dependencies. * * All [NpmDependency] for configurations related to kotlin/js will be added to `package.json`. * For external gradle modules, fake npm packages will be created and added to `package.json` @@ -45,14 +45,10 @@ internal class NpmResolver private constructor(val rootProject: Project) { val resolved = process?.resolved - return if (resolved != null) AlreadyResolved(resolved) + return if (resolved != null) AlreadyResolved(ProjectData[project]!!.resolved!!) else { - val resolver = NpmResolver(rootProject) - check(resolver.resolve(rootProject, null)) - val resolution = ResolvedProject(resolver.npmPackages, resolver.requiredByTasks) - ProjectData[rootProject]!!.resolved = resolution - - ResolvedNow(resolution) + NpmResolver(rootProject).resolve(rootProject, null)!! + ResolvedNow(ProjectData[project]!!.resolved!!) } } @@ -61,7 +57,7 @@ internal class NpmResolver private constructor(val rootProject: Project) { ?: error("NPM dependencies should be resolved$reason") fun checkRequiredDependencies(project: Project, target: RequiresNpmDependencies) { - val required = requireResolved(project, "before $target execution").requiredByTasks + val required = requireResolved(project, "before $target execution").taskDependencies val targetRequired = required[target]?.toSet() ?: setOf() target.requiredNpmDependencies.forEach { @@ -98,13 +94,9 @@ internal class NpmResolver private constructor(val rootProject: Project) { } class ResolvedProject( - val npmPackages: Collection, - val requiredByTasks: Map> - ) { - val dependencies by lazy { - npmPackages.flatMapTo(mutableSetOf()) { it.npmDependencies } - } - } + val npmPackage: NpmPackage?, + val taskDependencies: Map> + ) class NpmPackage( val project: Project, @@ -128,19 +120,15 @@ internal class NpmResolver private constructor(val rootProject: Project) { packageManagerInstalled = true } + private fun getOrResolve(project: Project, parentGradleModules: GradleNodeModulesBuilder?): ResolvedProject { + return (ProjectData[project] ?: resolve(project, parentGradleModules)!!).resolved!! + } + private fun resolve( project: Project, parentGradleModules: GradleNodeModulesBuilder? - ): Boolean { - val existedProcess = ProjectData[project] - if (existedProcess != null) { - if (existedProcess.resolved != null) error("yarn dependencies for $project already resolved") - else { - // called inside resolution of classpath (from visitTarget) - // we should return as we are already in progress - return false - } - } else ProjectData().also { + ): ProjectData? { + val result = ProjectData().also { ProjectData[project] = it } @@ -149,10 +137,10 @@ internal class NpmResolver private constructor(val rootProject: Project) { else GradleNodeModulesBuilder(project) project.subprojects.forEach { - resolve(it, gradleModules) + getOrResolve(it, gradleModules) } - val npmPackage = extractNpmPackage(project, gradleModules) + val npmPackage = extractNpmPackage(project, gradleModules, parentGradleModules) if (npmPackage != null) { npmPackage.savePackageJson(gson) @@ -162,6 +150,8 @@ internal class NpmResolver private constructor(val rootProject: Project) { npmPackages.add(npmPackage) } + result.resolved = ResolvedProject(npmPackage, requiredByTasks) + if (project == rootProject) { if (npmPackages.isNotEmpty()) { requirePackageManagerSetup() @@ -173,12 +163,13 @@ internal class NpmResolver private constructor(val rootProject: Project) { gradleModules.close() } - return true + return result } private fun extractNpmPackage( project: Project, - gradleComponents: GradleNodeModulesBuilder + gradleComponents: GradleNodeModulesBuilder, + parentGradleModules: GradleNodeModulesBuilder? ): NpmPackage? { val packageJson = PackageJson(project.name, project.version.toString()) val npmDependencies = mutableSetOf() @@ -192,6 +183,12 @@ internal class NpmResolver private constructor(val rootProject: Project) { val relativePath = it.path.relativeTo(NpmProject[project].nodeWorkDir) packageJson.dependencies[it.name] = "file:$relativePath" } + gradleComponents.projects.forEach { + val npmPackage = getOrResolve(it, parentGradleModules).npmPackage + if (npmPackage != null) { + packageJson.dependencies[npmPackage.packageJson.name] = npmPackage.packageJson.version + } + } } project.nodeJs.packageJsonHandlers.forEach { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/Yarn.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/Yarn.kt index 3e0382d9cea..faf718282da 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/Yarn.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/Yarn.kt @@ -111,8 +111,8 @@ object Yarn : NpmApi { return false } - override fun shouldHoistGradleNodeModules(project: Project): Boolean = - project.rootProject.yarn.useWorkspaces +// override fun shouldHoistGradleNodeModules(project: Project): Boolean = +// project.rootProject.yarn.useWorkspaces @Suppress("EXPOSED_PARAMETER_TYPE") override fun resolveRootProject(