JPS tests: restore MPP tests runner, support new MPP model

This commit is contained in:
Sergey Rostov
2018-09-04 16:10:56 +03:00
parent 808e83a01e
commit 4975ef7db5
12 changed files with 286 additions and 74 deletions
@@ -67,12 +67,18 @@ fun getModificationsToPerform(
val underscore = fileName.indexOf("_") val underscore = fileName.indexOf("_")
if (underscore != -1) { if (underscore != -1) {
val module = fileName.substring(0, underscore) var moduleName = fileName.substring(0, underscore)
var moduleFileName = fileName.substring(underscore + 1)
if (moduleName.all { it.isDigit() }) {
val (moduleName1, moduleFileName1) = moduleFileName.split("_")
moduleName = moduleName1
moduleFileName = moduleFileName1
}
assert(moduleNames != null) { "File name has module prefix, but multi-module environment is absent" } assert(moduleNames != null) { "File name has module prefix, but multi-module environment is absent" }
assert(module in moduleNames!!) { "Module not found for file with prefix: $fileName" } assert(moduleName in moduleNames!!) { "Module not found for file with prefix: $fileName" }
return Pair(module, fileName.substring(underscore + 1)) return Pair(moduleName, moduleFileName)
} }
assert(moduleNames == null) { "Test is multi-module, but file has no module prefix: $fileName" } assert(moduleNames == null) { "Test is multi-module, but file has no module prefix: $fileName" }
@@ -43,12 +43,13 @@ import org.jetbrains.jps.model.JpsModuleRootModificationUtil
import org.jetbrains.jps.model.java.JpsJavaExtensionService import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.library.sdk.JpsSdk import org.jetbrains.jps.model.library.sdk.JpsSdk
import org.jetbrains.jps.util.JpsPathUtil import org.jetbrains.jps.util.JpsPathUtil
import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments
import org.jetbrains.kotlin.config.IncrementalCompilation import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.incremental.LookupSymbol import org.jetbrains.kotlin.incremental.LookupSymbol
import org.jetbrains.kotlin.incremental.storage.version.CacheAttributesDiff import org.jetbrains.kotlin.incremental.storage.version.CacheAttributesDiff
import org.jetbrains.kotlin.incremental.storage.version.CacheVersionManager import org.jetbrains.kotlin.incremental.storage.version.CacheVersionManager
import org.jetbrains.kotlin.incremental.testingUtils.* import org.jetbrains.kotlin.incremental.testingUtils.*
import org.jetbrains.kotlin.jps.build.dependeciestxt.DependenciesTxtBuilder import org.jetbrains.kotlin.jps.build.dependeciestxt.ModulesTxtBuilder
import org.jetbrains.kotlin.jps.build.dependeciestxt.ModulesTxt import org.jetbrains.kotlin.jps.build.dependeciestxt.ModulesTxt
import org.jetbrains.kotlin.jps.incremental.CompositeLookupsCacheAttributesManager import org.jetbrains.kotlin.jps.incremental.CompositeLookupsCacheAttributesManager
import org.jetbrains.kotlin.jps.incremental.getKotlinCache import org.jetbrains.kotlin.jps.incremental.getKotlinCache
@@ -145,7 +146,10 @@ abstract class AbstractIncrementalJpsTest(
protected open val mockConstantSearch: Callbacks.ConstantAffectionResolver? protected open val mockConstantSearch: Callbacks.ConstantAffectionResolver?
get() = MockJavaConstantSearch(workDir) get() = MockJavaConstantSearch(workDir)
private fun build(scope: CompileScopeTestBuilder = CompileScopeTestBuilder.make().allModules()): MakeResult { private fun build(
name: String?,
scope: CompileScopeTestBuilder = CompileScopeTestBuilder.make().allModules()
): MakeResult {
val workDirPath = FileUtil.toSystemIndependentName(workDir.absolutePath) val workDirPath = FileUtil.toSystemIndependentName(workDir.absolutePath)
val logger = MyLogger(workDirPath) val logger = MyLogger(workDirPath)
@@ -182,9 +186,19 @@ abstract class AbstractIncrementalJpsTest(
.map { it.messageText } .map { it.messageText }
.map { it.replace("^.+:\\d+:\\s+".toRegex(), "").trim() } .map { it.replace("^.+:\\d+:\\s+".toRegex(), "").trim() }
.joinToString("\n") .joinToString("\n")
return MakeResult(logger.log + "$COMPILATION_FAILED\n" + errorMessages + "\n", true, null) return MakeResult(
log = logger.log + "$COMPILATION_FAILED\n" + errorMessages + "\n",
makeFailed = true,
mappingsDump = null,
name = name
)
} else { } else {
return MakeResult(logger.log, false, createMappingsDump(projectDescriptor)) return MakeResult(
log = logger.log,
makeFailed = false,
mappingsDump = createMappingsDump(projectDescriptor),
name = name
)
} }
} finally { } finally {
projectDescriptor.dataManager.flush(false) projectDescriptor.dataManager.flush(false)
@@ -193,7 +207,7 @@ abstract class AbstractIncrementalJpsTest(
} }
private fun initialMake(): MakeResult { private fun initialMake(): MakeResult {
val makeResult = build() val makeResult = build(null)
val initBuildLogFile = File(testDataDir, "init-build.log") val initBuildLogFile = File(testDataDir, "init-build.log")
if (initBuildLogFile.exists()) { if (initBuildLogFile.exists()) {
@@ -205,12 +219,12 @@ abstract class AbstractIncrementalJpsTest(
return makeResult return makeResult
} }
private fun make(): MakeResult { private fun make(name: String?): MakeResult {
return build() return build(name)
} }
private fun rebuild(): MakeResult { private fun rebuild(): MakeResult {
return build(CompileScopeTestBuilder.rebuild().allModules()) return build(null, CompileScopeTestBuilder.rebuild().allModules())
} }
private fun rebuildAndCheckOutput(makeOverallResult: MakeResult) { private fun rebuildAndCheckOutput(makeOverallResult: MakeResult) {
@@ -250,18 +264,23 @@ abstract class AbstractIncrementalJpsTest(
rebuildAndCheckOutput(makeOverallResult) rebuildAndCheckOutput(makeOverallResult)
} }
private fun readModulesConfig(): ModulesTxt? { open val modulesTxtFile
val dependenciesTxtFile = File(testDataDir, "dependencies.txt") get() = File(testDataDir, "dependencies.txt")
if (!dependenciesTxtFile.exists()) return null
return DependenciesTxtBuilder().readFile(dependenciesTxtFile) private fun readModulesTxt(): ModulesTxt? {
if (!modulesTxtFile.exists()) return null
return ModulesTxtBuilder().readFile(modulesTxtFile)
} }
protected open fun createBuildLog(incrementalMakeResults: List<AbstractIncrementalJpsTest.MakeResult>): String = protected open fun createBuildLog(incrementalMakeResults: List<AbstractIncrementalJpsTest.MakeResult>): String =
buildString { buildString {
incrementalMakeResults.forEachIndexed { i, makeResult -> incrementalMakeResults.forEachIndexed { i, makeResult ->
if (i > 0) append("\n") if (i > 0) append("\n")
append("================ Step #${i + 1} =================\n\n") if (makeResult.name != null) {
append("================ Step #${i + 1} ${makeResult.name} =================\n\n")
} else {
append("================ Step #${i + 1} =================\n\n")
}
append(makeResult.log) append(makeResult.log)
} }
} }
@@ -363,13 +382,29 @@ abstract class AbstractIncrementalJpsTest(
return byteArrayOutputStream.toString() return byteArrayOutputStream.toString()
} }
protected data class MakeResult(val log: String, val makeFailed: Boolean, val mappingsDump: String?) protected data class MakeResult(
val log: String,
val makeFailed: Boolean,
val mappingsDump: String?,
val name: String? = null
)
open val testDataSrc: File
get() = testDataDir
private fun performModificationsAndMake(moduleNames: Collection<String>?): List<MakeResult> { private fun performModificationsAndMake(moduleNames: Collection<String>?): List<MakeResult> {
val results = arrayListOf<MakeResult>() val results = arrayListOf<MakeResult>()
val modifications = getModificationsToPerform(testDataDir, moduleNames, allowNoFilesWithSuffixInTestData, TouchPolicy.TIMESTAMP) val modifications = getModificationsToPerform(
testDataSrc,
moduleNames,
allowNoFilesWithSuffixInTestData,
TouchPolicy.TIMESTAMP
)
for (step in modifications) { val stepsTxt = File(testDataSrc, "steps.txt")
val modificationNames = if (stepsTxt.exists()) stepsTxt.readLines() else null
modifications.forEachIndexed { index, step ->
step.forEach { it.perform(workDir, mapWorkingToOriginalFile) } step.forEach { it.perform(workDir, mapWorkingToOriginalFile) }
performAdditionalModifications(step) performAdditionalModifications(step)
if (moduleNames == null) { if (moduleNames == null) {
@@ -378,7 +413,9 @@ abstract class AbstractIncrementalJpsTest(
moduleNames.forEach { preProcessSources(File(workDir, "$it/src")) } moduleNames.forEach { preProcessSources(File(workDir, "$it/src")) }
} }
results.add(make()) val name = modificationNames?.getOrNull(index)
val makeResult = make(name)
results.add(makeResult)
} }
return results return results
} }
@@ -386,21 +423,25 @@ abstract class AbstractIncrementalJpsTest(
protected open fun performAdditionalModifications(modifications: List<Modification>) { protected open fun performAdditionalModifications(modifications: List<Modification>) {
} }
protected open fun generateModuleSources(modulesTxt: ModulesTxt) {
}
// null means one module // null means one module
private fun configureModules(): ModulesTxt? { private fun configureModules(): ModulesTxt? {
JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myProject).outputUrl = JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myProject).outputUrl =
JpsPathUtil.pathToUrl(getAbsolutePath("out")) JpsPathUtil.pathToUrl(getAbsolutePath("out"))
val jdk = addJdk("my jdk") val jdk = addJdk("my jdk")
val moduleDependencies = readModulesConfig() val modulesTxt = readModulesTxt()
mapWorkingToOriginalFile = hashMapOf() mapWorkingToOriginalFile = hashMapOf()
if (moduleDependencies == null) configureSingleModuleProject(jdk) if (modulesTxt == null) configureSingleModuleProject(jdk)
else configureMultiModuleProject(moduleDependencies, jdk) else configureMultiModuleProject(modulesTxt, jdk)
addStdlib() addStdlib()
return moduleDependencies return modulesTxt
} }
private fun configureSingleModuleProject(jdk: JpsSdk<JpsDummyElement>?) { private fun configureSingleModuleProject(jdk: JpsSdk<JpsDummyElement>?) {
@@ -413,11 +454,14 @@ abstract class AbstractIncrementalJpsTest(
preProcessSources(sourceDestinationDir) preProcessSources(sourceDestinationDir)
} }
protected open val ModulesTxt.Module.sourceFilePrefix: String
get() = "${name}_"
private fun configureMultiModuleProject( private fun configureMultiModuleProject(
moduleDependencies: ModulesTxt, modulesTxt: ModulesTxt,
jdk: JpsSdk<JpsDummyElement>? jdk: JpsSdk<JpsDummyElement>?
) { ) {
moduleDependencies.modules.forEach { module -> modulesTxt.modules.forEach { module ->
module.jpsModule = addModule( module.jpsModule = addModule(
module.name, module.name,
arrayOf(getAbsolutePath("${module.name}/src")), arrayOf(getAbsolutePath("${module.name}/src")),
@@ -428,27 +472,37 @@ abstract class AbstractIncrementalJpsTest(
val kotlinFacetSettings = module.kotlinFacetSettings val kotlinFacetSettings = module.kotlinFacetSettings
if (kotlinFacetSettings != null) { if (kotlinFacetSettings != null) {
val compilerArguments = kotlinFacetSettings.compilerArguments
if (compilerArguments is K2MetadataCompilerArguments) {
val out = getAbsolutePath("${module.name}/out")
File(out).mkdirs()
compilerArguments.destination = out
}
module.jpsModule.container.setChild( module.jpsModule.container.setChild(
JpsKotlinFacetModuleExtension.KIND, JpsKotlinFacetModuleExtension.KIND,
JpsKotlinFacetModuleExtension(kotlinFacetSettings!!) JpsKotlinFacetModuleExtension(kotlinFacetSettings)
) )
} }
val sourceDirName = "${module.name}/src"
val filePrefix = "${module.name}_"
val sourceDestinationDir = File(workDir, sourceDirName)
val sourcesMapping = copyTestSources(testDataDir, sourceDestinationDir, filePrefix)
mapWorkingToOriginalFile.putAll(sourcesMapping)
preProcessSources(sourceDestinationDir)
} }
moduleDependencies.dependencies.forEach { modulesTxt.dependencies.forEach {
JpsModuleRootModificationUtil.addDependency( JpsModuleRootModificationUtil.addDependency(
it.from.jpsModule, it.to.jpsModule, it.from.jpsModule, it.to.jpsModule,
it.scope, it.exported it.scope, it.exported
) )
} }
// configure module contents
generateModuleSources(modulesTxt)
modulesTxt.modules.forEach { module ->
val sourceDirName = "${module.name}/src"
val sourceDestinationDir = File(workDir, sourceDirName)
val sourcesMapping = copyTestSources(testDataDir, sourceDestinationDir, module.sourceFilePrefix)
mapWorkingToOriginalFile.putAll(sourcesMapping)
preProcessSources(sourceDestinationDir)
}
} }
protected open fun addStdlib() { protected open fun addStdlib() {
@@ -544,9 +598,4 @@ abstract class AbstractIncrementalJpsTest(
internal val ProjectDescriptor.allModuleTargets: Collection<ModuleBuildTarget> internal val ProjectDescriptor.allModuleTargets: Collection<ModuleBuildTarget>
get() = buildTargetIndex.allTargets.filterIsInstance<ModuleBuildTarget>() get() = buildTargetIndex.allTargets.filterIsInstance<ModuleBuildTarget>()
private class DependencyDescriptor(val name: String, val exported: Boolean)
private fun parseDependency(dependency: String): DependencyDescriptor =
DependencyDescriptor(dependency.removeSuffix(EXPORTED_SUFFIX), dependency.endsWith(EXPORTED_SUFFIX))
private val EXPORTED_SUFFIX = "[exported]" private val EXPORTED_SUFFIX = "[exported]"
@@ -5,8 +5,32 @@
package org.jetbrains.kotlin.jps.build package org.jetbrains.kotlin.jps.build
import org.jetbrains.kotlin.jps.build.dependeciestxt.ModulesTxt
import org.jetbrains.kotlin.jps.build.dependeciestxt.MppJpsIncTestsGenerator
import java.io.File
abstract class AbstractMultiplatformJpsTest : AbstractIncrementalJpsTest() { abstract class AbstractMultiplatformJpsTest : AbstractIncrementalJpsTest() {
override fun doTest(testDataPath: String) { override val modulesTxtFile: File
// temporary ignore jps-plugin/testData/incremental/multiplatform/multiModule tests get() = File(testDataDir.parent, "dependencies.txt").also {
check(it.exists()) {
"`dependencies.txt` should be in parent dir. " +
"See jps-plugin/testData/incremental/multiplatform/multiModule/README.md for details"
}
}
override val testDataSrc: File
get() = File(workDir, "generatedTestDataSources")
override fun generateModuleSources(modulesTxt: ModulesTxt) {
testDataSrc.mkdirs()
val testCaseName = testDataDir.name
val generator = MppJpsIncTestsGenerator(modulesTxt) { testDataSrc }
val testCase = generator.testCases.find { it.name == testCaseName } ?: error("Unsupported test case name: $testCaseName")
testCase.generate()
} }
override val ModulesTxt.Module.sourceFilePrefix: String
get() = indexedName
} }
@@ -181,6 +181,91 @@ public class MultiplatformJpsTestGenerated extends AbstractMultiplatformJpsTest
} }
} }
@TestMetadata("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class SimpleNewMpp extends AbstractMultiplatformJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInSimpleNewMpp() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true);
}
@TestMetadata("editingCKotlin")
public void testEditingCKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp/editingCKotlin/");
}
@TestMetadata("editingPJsKotlin")
public void testEditingPJsKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp/editingPJsKotlin/");
}
@TestMetadata("editingPJvmJava")
public void testEditingPJvmJava() throws Exception {
runTest("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp/editingPJvmJava/");
}
@TestMetadata("editingPJvmKotlin")
public void testEditingPJvmKotlin() throws Exception {
runTest("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp/editingPJvmKotlin/");
}
@TestMetadata("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp/editingCKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingCKotlin extends AbstractMultiplatformJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInEditingCKotlin() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp/editingCKotlin"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp/editingPJsKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingPJsKotlin extends AbstractMultiplatformJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInEditingPJsKotlin() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp/editingPJsKotlin"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp/editingPJvmJava")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingPJvmJava extends AbstractMultiplatformJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInEditingPJvmJava() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp/editingPJvmJava"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp/editingPJvmKotlin")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EditingPJvmKotlin extends AbstractMultiplatformJpsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInEditingPJvmKotlin() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/multiplatform/multiModule/simpleNewMpp/editingPJvmKotlin"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, true);
}
}
}
@TestMetadata("jps-plugin/testData/incremental/multiplatform/multiModule/ultimate") @TestMetadata("jps-plugin/testData/incremental/multiplatform/multiModule/ultimate")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -12,6 +12,9 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments
import org.jetbrains.kotlin.config.CompilerSettings import org.jetbrains.kotlin.config.CompilerSettings
import org.jetbrains.kotlin.config.KotlinFacetSettings import org.jetbrains.kotlin.config.KotlinFacetSettings
import org.jetbrains.kotlin.config.KotlinModuleKind.COMPILATION_AND_SOURCE_SET_HOLDER
import org.jetbrains.kotlin.config.KotlinModuleKind.SOURCE_SET_HOLDER
import org.jetbrains.kotlin.jps.build.dependeciestxt.ModulesTxt.Dependency.Kind.*
import org.jetbrains.kotlin.platform.impl.isCommon import org.jetbrains.kotlin.platform.impl.isCommon
import org.jetbrains.kotlin.platform.impl.isJvm import org.jetbrains.kotlin.platform.impl.isJvm
import java.io.File import java.io.File
@@ -20,7 +23,7 @@ import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.memberProperties import kotlin.reflect.full.memberProperties
/** /**
* Dependencies description file. * Modules description file.
* See [README.md] for more details. * See [README.md] for more details.
*/ */
data class ModulesTxt( data class ModulesTxt(
@@ -46,13 +49,18 @@ data class ModulesTxt(
val usages = mutableListOf<Dependency>() val usages = mutableListOf<Dependency>()
val isCommonModule val isCommonModule
get() = kotlinFacetSettings?.platform.isCommon get() =
kotlinFacetSettings?.platform.isCommon ||
kotlinFacetSettings?.kind == SOURCE_SET_HOLDER
val isJvmModule val isJvmModule
get() = kotlinFacetSettings?.platform.isJvm get() = kotlinFacetSettings?.platform.isJvm
val expectedBy val expectedBy
get() = dependencies.filter { it.expectedBy } get() = dependencies.filter {
it.kind == EXPECTED_BY ||
it.kind == INCLUDE
}
@Flag @Flag
var edit: Boolean = false var edit: Boolean = false
@@ -79,20 +87,26 @@ data class ModulesTxt(
val from: Module, val from: Module,
val to: Module, val to: Module,
val scope: JpsJavaDependencyScope, val scope: JpsJavaDependencyScope,
val expectedBy: Boolean, val kind: Kind,
val exported: Boolean val exported: Boolean
) { ) {
val effectivelyExported val effectivelyExported
get() = expectedBy || exported get() = kind == EXPECTED_BY || exported
init { init {
from.dependencies.add(this) from.dependencies.add(this)
to.usages.add(this) to.usages.add(this)
} }
enum class Kind {
DEPENDENCY,
EXPECTED_BY,
INCLUDE
}
} }
} }
class DependenciesTxtBuilder { class ModulesTxtBuilder {
val modules = mutableMapOf<String, ModuleRef>() val modules = mutableMapOf<String, ModuleRef>()
private val dependencies = mutableListOf<DependencyBuilder>() private val dependencies = mutableListOf<DependencyBuilder>()
@@ -112,7 +126,13 @@ class DependenciesTxtBuilder {
if (kotlinFacetSettings != null) { if (kotlinFacetSettings != null) {
kotlinFacetSettings.implementedModuleNames = kotlinFacetSettings.implementedModuleNames =
result.dependencies.asSequence() result.dependencies.asSequence()
.filter { it.expectedBy } .filter { it.kind == EXPECTED_BY }
.map { it.to.name }
.toList()
kotlinFacetSettings.sourceSetNames =
result.dependencies.asSequence()
.filter { it.kind == INCLUDE }
.map { it.to.name } .map { it.to.name }
.toList() .toList()
} }
@@ -127,12 +147,20 @@ class DependenciesTxtBuilder {
val from: ModuleRef, val from: ModuleRef,
val to: ModuleRef, val to: ModuleRef,
val scope: JpsJavaDependencyScope, val scope: JpsJavaDependencyScope,
val expectedBy: Boolean, val kind: ModulesTxt.Dependency.Kind,
val exported: Boolean val exported: Boolean
) { ) {
fun build(): ModulesTxt.Dependency { fun build(): ModulesTxt.Dependency {
if (expectedBy) check(to.actual.isCommonModule) { "$this: ${to.actual} is not common module" } when (kind) {
return ModulesTxt.Dependency(from.actual, to.actual, scope, expectedBy, exported) DEPENDENCY -> Unit
EXPECTED_BY -> check(to.actual.isCommonModule) {
"$this: ${to.actual} is not common module"
}
INCLUDE -> check(to.actual.kotlinFacetSettings?.kind == SOURCE_SET_HOLDER) {
"$this: ${to.actual} is not source set holder"
}
}
return ModulesTxt.Dependency(from.actual, to.actual, scope, kind, exported)
} }
} }
@@ -141,14 +169,11 @@ class DependenciesTxtBuilder {
parseDeclaration(line) parseDeclaration(line)
} }
// module.build() requires built dependencies // dependencies need to be build first: module.build() requires it
val dependencies = dependencies.map { it.build() } val dependencies = dependencies.map { it.build() }
return ModulesTxt( val modules = modules.values.mapIndexed { index, moduleRef -> moduleRef.build(index) }
file,
fileTitle, return ModulesTxt(file, fileTitle, modules, dependencies)
modules.values.mapIndexed { index, moduleRef -> moduleRef.build(index) },
dependencies
)
} }
private fun parseDeclaration(line: String) = doParseDeclaration(removeComments(line)) private fun parseDeclaration(line: String) = doParseDeclaration(removeComments(line))
@@ -200,11 +225,11 @@ class DependenciesTxtBuilder {
val name = def.value.trim() val name = def.value.trim()
val module = ModulesTxt.Module(name) val module = ModulesTxt.Module(name)
val kotlinFacetSettings = KotlinFacetSettings() val settings = KotlinFacetSettings()
module.kotlinFacetSettings = kotlinFacetSettings module.kotlinFacetSettings = settings
kotlinFacetSettings.useProjectSettings = false settings.useProjectSettings = false
kotlinFacetSettings.compilerSettings = CompilerSettings().also { settings.compilerSettings = CompilerSettings().also {
it.additionalArguments = "-version -Xmulti-platform" it.additionalArguments = "-version -Xmulti-platform"
} }
@@ -215,9 +240,11 @@ class DependenciesTxtBuilder {
def.flags.forEach { flag -> def.flags.forEach { flag ->
when (flag) { when (flag) {
"common" -> kotlinFacetSettings.compilerArguments = K2MetadataCompilerArguments() "sourceSetHolder" -> settings.kind = SOURCE_SET_HOLDER
"jvm" -> kotlinFacetSettings.compilerArguments = K2JVMCompilerArguments() "compilationAndSourceSetHolder" -> settings.kind = COMPILATION_AND_SOURCE_SET_HOLDER
"js" -> kotlinFacetSettings.compilerArguments = K2JSCompilerArguments() "common" -> settings.compilerArguments = K2MetadataCompilerArguments()
"jvm" -> settings.compilerArguments = K2JVMCompilerArguments()
"js" -> settings.compilerArguments = K2JSCompilerArguments()
else -> { else -> {
val flagProperty = ModulesTxt.Module.flags[flag] val flagProperty = ModulesTxt.Module.flags[flag]
if (flagProperty != null) flagProperty.set(module, true) if (flagProperty != null) flagProperty.set(module, true)
@@ -243,13 +270,18 @@ class DependenciesTxtBuilder {
} else { } else {
var exported = false var exported = false
var scope: JpsJavaDependencyScope? = null var scope: JpsJavaDependencyScope? = null
var expectedBy = false var kind: ModulesTxt.Dependency.Kind = DEPENDENCY
fun setScope(newScope: JpsJavaDependencyScope) { fun setScope(newScope: JpsJavaDependencyScope) {
check(scope == null) { "`$this: $from -> $to` dependency is already flagged as $scope" } check(scope == null) { "`$this: $from -> $to` dependency is already flagged as $scope" }
scope = newScope scope = newScope
} }
fun setKind(newKind: ModulesTxt.Dependency.Kind) {
check(kind == DEPENDENCY) { "`$this: $from -> $to` dependency is already flagged as $kind" }
kind = newKind
}
flags.forEach { flag -> flags.forEach { flag ->
when (flag) { when (flag) {
"exported" -> exported = true "exported" -> exported = true
@@ -257,7 +289,8 @@ class DependenciesTxtBuilder {
"test" -> setScope(JpsJavaDependencyScope.TEST) "test" -> setScope(JpsJavaDependencyScope.TEST)
"runtime" -> setScope(JpsJavaDependencyScope.RUNTIME) "runtime" -> setScope(JpsJavaDependencyScope.RUNTIME)
"provided" -> setScope(JpsJavaDependencyScope.PROVIDED) "provided" -> setScope(JpsJavaDependencyScope.PROVIDED)
"expectedBy" -> expectedBy = true "expectedBy" -> setKind(EXPECTED_BY)
"include" -> setKind(INCLUDE)
else -> error("Unknown dependency flag `$flag`") else -> error("Unknown dependency flag `$flag`")
} }
} }
@@ -266,7 +299,7 @@ class DependenciesTxtBuilder {
from = moduleRef(from), from = moduleRef(from),
to = moduleRef(to), to = moduleRef(to),
scope = scope ?: JpsJavaDependencyScope.COMPILE, scope = scope ?: JpsJavaDependencyScope.COMPILE,
expectedBy = expectedBy, kind = kind,
exported = exported exported = exported
).also { ).also {
dependencies.add(it) dependencies.add(it)
@@ -15,7 +15,7 @@ fun actualizeMppJpsIncTestCaseDirs(rootDir: String, dir: String) {
val dependenciesTxtFile = File(dirFile, "dependencies.txt") val dependenciesTxtFile = File(dirFile, "dependencies.txt")
if (dependenciesTxtFile.exists()) { if (dependenciesTxtFile.exists()) {
val fileTitle = "$dir/${dirFile.name}/dependencies.txt" val fileTitle = "$dir/${dirFile.name}/dependencies.txt"
val dependenciesTxt = DependenciesTxtBuilder().readFile(dependenciesTxtFile, fileTitle) val dependenciesTxt = ModulesTxtBuilder().readFile(dependenciesTxtFile, fileTitle)
MppJpsIncTestsGenerator(dependenciesTxt) { File(dirFile, it.name) } MppJpsIncTestsGenerator(dependenciesTxt) { File(dirFile, it.name) }
.actualizeTestCasesDirs(dirFile) .actualizeTestCasesDirs(dirFile)
@@ -178,7 +178,13 @@ class MppJpsIncTestsGenerator(val txt: ModulesTxt, val testCaseDirProvider: (Tes
override fun generate() { override fun generate() {
generateBaseContent() generateBaseContent()
check(commonModule.isCommonModule) check(commonModule.isCommonModule)
val implModules = commonModule.usages.filter { it.expectedBy }.map { it.from } val implModules = commonModule.usages
.asSequence()
.filter {
it.kind == ModulesTxt.Dependency.Kind.EXPECTED_BY ||
it.kind == ModulesTxt.Dependency.Kind.INCLUDE
}
.map { it.from }
commonModule.contentsSettings = ModuleContentSettings(commonModule, serviceNameSuffix = "New") commonModule.contentsSettings = ModuleContentSettings(commonModule, serviceNameSuffix = "New")
implModules.forEach { implModule -> implModules.forEach { implModule ->
@@ -22,7 +22,8 @@ Referring to undefined module is allowed (`jvm` module will be created at this c
This modules can be defined after reference. Several declarations for same module is not allowed. This modules can be defined after reference. Several declarations for same module is not allowed.
Supported module flags: Supported module flags:
- `common` - `common` (old MPP)
- `sourceSetHolder`, `compilationAndSourceSetHolder` (new MPP)
- `jvm` (default) - `jvm` (default)
- `js` - `js`
- `edit`, `editJvm`, `editExcpetActual` - see jps-plugin/testData/incremental/multiplatform/multiModule/README.md - `edit`, `editJvm`, `editExcpetActual` - see jps-plugin/testData/incremental/multiplatform/multiModule/README.md
@@ -32,5 +33,6 @@ Supported dependency flags:
- `test` - `test`
- `runtime` - `runtime`
- `provided` - `provided`
- `expectedBy` - `expectedBy` (old MPP)
- `included` (new MPP)
- `exproted` - `exproted`
@@ -0,0 +1,7 @@
c [sourceSetHolder, edit, editExpectActual]
pJvm [compilationAndSourceSetHolder, jvm, edit, editJvm]
pJvm -> c [include]
pJs [compilationAndSourceSetHolder, js, edit]
pJs -> c [include]