JPS: don't consider that production target of module "B" is depends on test target of module "A" when "B" depends on "A"

#KT-12595 Fixed
This commit is contained in:
Zalim Bashorov
2016-06-14 21:09:42 +03:00
committed by Zalim Bashorov
parent a17b0dd1b5
commit 0e428ca10c
5 changed files with 112 additions and 7 deletions
@@ -26,6 +26,7 @@ import com.intellij.testFramework.UsefulTestCase
import com.intellij.util.ArrayUtil
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.io.ZipUtil
import org.jetbrains.jps.ModuleChunk
import org.jetbrains.jps.api.CanceledStatus
import org.jetbrains.jps.builders.BuildResult
import org.jetbrains.jps.builders.CompileScopeTestBuilder
@@ -33,16 +34,23 @@ import org.jetbrains.jps.builders.JpsBuildTestCase
import org.jetbrains.jps.builders.TestProjectBuilderLogger
import org.jetbrains.jps.builders.impl.BuildDataPathsImpl
import org.jetbrains.jps.builders.logging.BuildLoggingManager
import org.jetbrains.jps.cmdline.ProjectDescriptor
import org.jetbrains.jps.incremental.BuilderRegistry
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.IncProjectBuilder
import org.jetbrains.jps.incremental.ModuleLevelBuilder
import org.jetbrains.jps.incremental.messages.BuildMessage
import org.jetbrains.jps.incremental.messages.CompilerMessage
import org.jetbrains.jps.model.JpsModuleRootModificationUtil
import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.jps.model.java.JpsJavaDependencyScope
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.module.JpsModule
import org.jetbrains.jps.util.JpsPathUtil
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.incremental.CacheVersion
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.test.KotlinTestUtils
@@ -754,18 +762,66 @@ class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
doTest()
}
fun testGetDependentTargets() {
fun addModuleWithSourceAndTestRoot(name: String): JpsModule {
return addModule(name, "src/").apply {
contentRootsList.addUrl(JpsPathUtil.pathToUrl("test/"))
addSourceRoot(JpsPathUtil.pathToUrl("test/"), JavaSourceRootType.TEST_SOURCE)
}
}
val a = addModuleWithSourceAndTestRoot("a")
val b = addModuleWithSourceAndTestRoot("b")
val c = addModuleWithSourceAndTestRoot("c")
val b2 = addModuleWithSourceAndTestRoot("b2")
val c2 = addModuleWithSourceAndTestRoot("c2")
JpsModuleRootModificationUtil.addDependency(b, a, JpsJavaDependencyScope.COMPILE, /*exported =*/ true)
JpsModuleRootModificationUtil.addDependency(c, b, JpsJavaDependencyScope.COMPILE, /*exported =*/ false)
JpsModuleRootModificationUtil.addDependency(b2, a, JpsJavaDependencyScope.COMPILE, /*exported =*/ false)
JpsModuleRootModificationUtil.addDependency(c2, b2, JpsJavaDependencyScope.COMPILE, /*exported =*/ false)
val actual = StringBuilder()
buildCustom(CanceledStatus.NULL, TestProjectBuilderLogger(), BuildResult()) {
project.setTestingContext(TestingContext(LookupTracker.DO_NOTHING, object: BuildLogger {
override fun buildStarted(context: CompileContext, chunk: ModuleChunk) {
actual.append("Targets dependent on ${chunk.targets.joinToString() }:\n")
actual.append(getDependentTargets(chunk, context).map { it.toString() }.sorted().joinToString("\n"))
actual.append("\n---------\n")
}
override fun actionsOnCacheVersionChanged(actions: List<CacheVersion.Action>) {}
override fun buildFinished(exitCode: ModuleLevelBuilder.ExitCode) {}
override fun markedAsDirty(files: Iterable<File>) {}
}))
}
val expectedFile = File(getCurrentTestDataRoot(), "expected.txt")
KotlinTestUtils.assertEqualsToFile(expectedFile, actual.toString())
}
private fun BuildResult.checkErrors() {
val actualErrors = getMessages(BuildMessage.Kind.ERROR)
.map { it as CompilerMessage }
.map { "${it.messageText} at line ${it.line}, column ${it.column}" }.sorted().joinToString("\n")
val projectRoot = File(AbstractKotlinJpsBuildTestCase.TEST_DATA_PATH + "general/" + getTestName(false))
val expectedFile = File(projectRoot, "errors.txt")
val expectedFile = File(getCurrentTestDataRoot(), "errors.txt")
KotlinTestUtils.assertEqualsToFile(expectedFile, actualErrors)
}
private fun buildCustom(canceledStatus: CanceledStatus, logger: TestProjectBuilderLogger,buildResult: BuildResult) {
private fun getCurrentTestDataRoot() = File(AbstractKotlinJpsBuildTestCase.TEST_DATA_PATH + "general/" + getTestName(false))
private fun buildCustom(
canceledStatus: CanceledStatus,
logger: TestProjectBuilderLogger,
buildResult: BuildResult,
setupProject: ProjectDescriptor.() -> Unit = {}
) {
val scopeBuilder = CompileScopeTestBuilder.make().all()
val descriptor = this.createProjectDescriptor(BuildLoggingManager(logger))
descriptor.setupProject()
try {
val builder = IncProjectBuilder(descriptor, BuilderRegistry.getInstance(), this.myBuildParams, canceledStatus, null, true)
builder.addMessageHandler(buildResult)
@@ -142,7 +142,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
val actualExitCode = if (proposedExitCode == OK && fsOperations.hasMarkedDirty) ADDITIONAL_PASS_REQUIRED else proposedExitCode
LOG.info("Build result: " + actualExitCode)
LOG.debug("Build result: " + actualExitCode)
context.testingContext?.buildLogger?.buildFinished(actualExitCode)
@@ -820,14 +820,15 @@ private fun getIncrementalCaches(chunk: ModuleChunk, context: CompileContext): M
return chunkCaches
}
private fun getDependentTargets(
fun getDependentTargets(
compilingChunk: ModuleChunk,
context: CompileContext
): Set<ModuleBuildTarget> {
val classpathKind = JpsJavaClasspathKind.compile(compilingChunk.targets.any { it.isTests })
val compilingChunkIsTests = compilingChunk.targets.any { it.isTests }
val classpathKind = JpsJavaClasspathKind.compile(compilingChunkIsTests)
fun dependsOnCompilingChunk(target: BuildTarget<*>): Boolean {
if (target !is ModuleBuildTarget) return false
if (target !is ModuleBuildTarget || compilingChunkIsTests && !target.isTests) return false
val dependencies = getDependenciesRecursively(target.module, classpathKind)
return ContainerUtil.intersects(dependencies, compilingChunk.modules)
@@ -0,0 +1,42 @@
Targets dependent on Module 'a' production:
Module 'a' tests
Module 'b' production
Module 'b' tests
Module 'b2' production
Module 'b2' tests
Module 'c' production
Module 'c' tests
---------
Targets dependent on Module 'a' tests:
Module 'b' tests
Module 'b2' tests
Module 'c' tests
---------
Targets dependent on Module 'b2' production:
Module 'b2' tests
Module 'c2' production
Module 'c2' tests
---------
Targets dependent on Module 'b2' tests:
Module 'c2' tests
---------
Targets dependent on Module 'c2' production:
Module 'c2' tests
---------
Targets dependent on Module 'c2' tests:
---------
Targets dependent on Module 'b' production:
Module 'b' tests
Module 'c' production
Module 'c' tests
---------
Targets dependent on Module 'b' tests:
Module 'c' tests
---------
Targets dependent on Module 'c' production:
Module 'c' tests
---------
Targets dependent on Module 'c' tests:
---------
@@ -0,0 +1,3 @@
fun foo() {
}
@@ -0,0 +1,3 @@
fun test() {
}