Files
Nikolay Chashnikovandintellij-monorepo-bot 2d8a1208d6 IJPL-201068 runtime module repository: include paths to module-level libraries to classpath of corresponding modules
Before, module-level libraries were translated to separate RuntimeModuleDescriptor in the runtime module repository, and dependencies on them were added to RuntimeModuleDescriptor instance corresponding to the JPS module. However, it didn't work well when IDE is started from source code, and output of the content module isn't merged with the module's libraries, causing problems like IJPL-201068 and IJPL-233281. Also, it greatly increased number of elements in the runtime module repository. Now paths to library JARs are added to the module classpath, and no separate RuntimeModuleDescriptor instances are created for module-level libraries. This will also make it simpler to reuse the runtime module repository for computing dependencies of modules at runtime (IJPL-157803).

GitOrigin-RevId: ce62725e98a8202bd80afaa3639f1c53fd50521c
2026-02-04 12:09:18 +00:00

219 lines
7.8 KiB
Kotlin

// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.devkit.runtimeModuleRepository.jps.build
import org.jetbrains.jps.model.java.JavaResourceRootType
import org.jetbrains.jps.model.java.JpsJavaDependencyScope
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.java.JpsJavaLibraryType
import org.jetbrains.jps.model.library.JpsOrderRootType
import org.jetbrains.jps.model.serialization.JpsMavenSettings
import org.jetbrains.jps.util.JpsPathUtil
import kotlin.io.path.Path
class RuntimeModuleRepositoryBuilderTest : RuntimeModuleRepositoryTestCase() {
fun `test module with tests`() {
addModule("a", withTests = true)
buildAndCheck {
descriptor("a")
testDescriptor("a.tests", "a")
}
}
fun `test module without sources`() {
addModule("a", withTests = false, withSources = false)
buildAndCheck {
descriptor("a", resourceDirName = null)
}
}
fun `test module with resources only`() {
val module = addModule("a", withTests = false, withSources = false)
module.addSourceRoot(getUrl("a/res"), JavaResourceRootType.RESOURCE)
buildAndCheck {
descriptor("a")
}
}
fun `test dependency`() {
val a = addModule("a", withTests = false)
addModule("b", a, withTests = false)
buildAndCheck {
descriptor("a")
descriptor("b", "a")
}
}
fun `test transitive dependency`() {
val a = addModule("a", withTests = false)
val b = addModule("b", a, withTests = false)
addModule("c", b, withTests = false)
buildAndCheck {
descriptor("a")
descriptor("b", "a")
descriptor("c", "b")
}
}
fun `test dependency with tests`() {
val a = addModule("a", withTests = true)
addModule("b", a, withTests = true)
buildAndCheck {
descriptor("a")
testDescriptor("a.tests", "a")
descriptor("b", "a")
testDescriptor("b.tests", "b", "a.tests")
}
}
fun `test dependency on test only module with non-standard name`() {
val aTests = addModule("a.test", withSources = false, withTests = true)
val b = addModule("b", withTests = true)
val dependency = b.dependenciesList.addModuleDependency(aTests)
JpsJavaExtensionService.getInstance().getOrCreateDependencyExtension(dependency).scope = JpsJavaDependencyScope.TEST
buildAndCheck {
descriptor("a.test", resourceDirName = null)
testDescriptor("a.test.tests", "a.test", resourceDirName = "a.test")
descriptor("b")
testDescriptor("b.tests", "b", "a.test.tests")
}
}
fun `test transitive dependency via module without tests`() {
val a = addModule("a", withTests = true)
val b = addModule("b", a, withTests = false)
addModule("c", b, withTests = true)
buildAndCheck {
descriptor("a")
descriptor("b", "a")
descriptor("c", "b")
testDescriptor("a.tests", "a")
testDescriptor("c.tests", "c", "a.tests")
}
}
fun `test transitive dependency via module without tests but with test module-level library`() {
val a = addModule("a", withTests = true)
val b = addModule("b", a, withTests = false)
val lib = b.libraryCollection.addLibrary("lib", JpsJavaLibraryType.INSTANCE)
val dependency = b.dependenciesList.addLibraryDependency(lib)
JpsJavaExtensionService.getInstance().getOrCreateDependencyExtension(dependency).scope = JpsJavaDependencyScope.TEST
lib.addRoot(getUrl("project/lib"), JpsOrderRootType.COMPILED)
addModule("c", b, withTests = true)
buildAndCheck {
descriptor("a")
descriptor("b", "a")
descriptor("c", "b")
testDescriptor("a.tests", "a")
descriptor("c.tests", listOf("test/c", $$"$PROJECT_DIR$/lib"), listOf("c", "a.tests"))
}
}
fun `test do not add unnecessary transitive dependencies via module without tests`() {
val a = addModule("a", withTests = true)
val b = addModule("b", withTests = false)
val c = addModule("c", a, b, withTests = false)
addModule("d", c, withTests = true)
buildAndCheck {
descriptor("a")
descriptor("b")
descriptor("c", "a", "b")
descriptor("d", "c")
testDescriptor("a.tests", "a")
testDescriptor("d.tests", "d", "a.tests")
}
}
fun `test circular dependency with tests`() {
val a = addModule("a", withTests = true)
val b = addModule("b", a, withTests = true)
val dependency = a.dependenciesList.addModuleDependency(b)
JpsJavaExtensionService.getInstance().getOrCreateDependencyExtension(dependency).scope = JpsJavaDependencyScope.RUNTIME
buildAndCheck {
descriptor("a", "b")
testDescriptor("a.tests", "a", "b.tests")
descriptor("b", "a")
testDescriptor("b.tests", "b", "a.tests")
}
}
fun `test circular dependency without tests`() {
val a = addModule("a", withTests = false)
val b = addModule("b", a, withTests = false)
val dependency = a.dependenciesList.addModuleDependency(b)
JpsJavaExtensionService.getInstance().getOrCreateDependencyExtension(dependency).scope = JpsJavaDependencyScope.RUNTIME
addModule("c", b, withTests = true)
buildAndCheck {
descriptor("a", "b")
descriptor("b", "a")
descriptor("c", "b")
testDescriptor("c.tests", "c")
}
}
fun `test separate module for tests`() {
val a = addModule("a", withTests = false)
addModule("a.tests", a, withTests = true, withSources = false)
buildAndCheck {
descriptor("a")
testDescriptor("a.tests", "a", resourceDirName = "a.tests")
}
}
fun `test module with production roots named like a test module`() {
val name = "a.tests.actually.not"
addModule(name, withTests = false)
buildAndCheck {
descriptor(name)
descriptor(name)
}
}
fun `test module library`() {
val a = addModule("a", withTests = false)
val lib = a.libraryCollection.addLibrary("lib", JpsJavaLibraryType.INSTANCE)
a.dependenciesList.addLibraryDependency(lib)
lib.addRoot(getUrl("project/lib"), JpsOrderRootType.COMPILED)
buildAndCheck {
descriptor("a",listOf("production/a", $$"$PROJECT_DIR$/lib"), emptyList())
}
}
fun `test project library`() {
val a = addModule("a", withTests = false)
val lib = myProject.libraryCollection.addLibrary("lib", JpsJavaLibraryType.INSTANCE)
a.dependenciesList.addLibraryDependency(lib)
lib.addRoot(getUrl("project/lib"), JpsOrderRootType.COMPILED)
buildAndCheck {
descriptor("a", "lib.lib")
descriptor("lib.lib", listOf($$"$PROJECT_DIR$/lib"), emptyList())
}
}
fun `test library with roots from Maven repository`() {
val a = addModule("a", withTests = false)
val lib = myProject.libraryCollection.addLibrary("lib", JpsJavaLibraryType.INSTANCE)
a.dependenciesList.addLibraryDependency(lib)
val mavenRepoRoot = Path(JpsMavenSettings.getMavenRepositoryPath())
val relativeLibPath = "org/jetbrains/annotations/26.0.2/annotations-26.0.2.jar"
lib.addRoot(JpsPathUtil.getLibraryRootUrl(mavenRepoRoot.resolve(relativeLibPath)), JpsOrderRootType.COMPILED)
buildAndCheck {
descriptor("a", "lib.lib")
descriptor("lib.lib", listOf($$"$MAVEN_REPOSITORY$/$$relativeLibPath"), emptyList())
}
}
fun `test library with test scope`() {
val a = addModule("a", withTests = true)
val lib = myProject.libraryCollection.addLibrary("lib", JpsJavaLibraryType.INSTANCE)
val dependency = a.dependenciesList.addLibraryDependency(lib)
JpsJavaExtensionService.getInstance().getOrCreateDependencyExtension(dependency).scope = JpsJavaDependencyScope.TEST
lib.addRoot(getUrl("project/lib"), JpsOrderRootType.COMPILED)
buildAndCheck {
descriptor("a")
testDescriptor("a.tests", "a", "lib.lib")
descriptor("lib.lib", listOf($$"$PROJECT_DIR$/lib"), emptyList())
}
}
}