From ae37cc30a107a36dc01480e33a120d2e120e6bac Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Mon, 12 Mar 2018 20:53:32 +0300 Subject: [PATCH] JS: Use the same output paths for JPS and Maven-based builds #KT-22586 Fixed --- .../kotlin/idea/maven/KotlinMavenImporter.kt | 40 +++++++++++ .../idea/maven/KotlinMavenImporterTest.kt | 71 +++++++++++++++++++ .../kotlin/jps/build/KotlinJpsBuildTest.kt | 11 ++- .../kotlin/jps/JpsKotlinCompilerSettings.kt | 16 ++++- .../kotlin/jps/build/KotlinBuilder.kt | 6 +- .../KotlinBuilderModuleScriptGenerator.kt | 9 ++- .../expected-output.txt | 16 +++++ .../kotlinProject.iml | 32 +++++++++ .../kotlinProject.ipr | 14 ++++ .../src/main.kt | 3 + .../src/main/kotlin/main.kt | 3 + .../src/test/kotlin/test.kt | 3 + 12 files changed, 218 insertions(+), 6 deletions(-) create mode 100644 jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/expected-output.txt create mode 100644 jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/kotlinProject.iml create mode 100644 jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/kotlinProject.ipr create mode 100644 jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/src/main.kt create mode 100644 jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/src/main/kotlin/main.kt create mode 100644 jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/src/test/kotlin/test.kt diff --git a/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt b/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt index 147f18d7358..07843544fc9 100644 --- a/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt +++ b/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt @@ -22,11 +22,14 @@ import com.intellij.openapi.components.Storage import com.intellij.openapi.components.StoragePathMacros import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider import com.intellij.openapi.module.Module +import com.intellij.openapi.roots.CompilerModuleExtension +import com.intellij.openapi.roots.ModifiableRootModel import com.intellij.openapi.roots.OrderEnumerator import com.intellij.openapi.roots.OrderRootType import com.intellij.openapi.roots.impl.libraries.LibraryEx import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.util.AsyncResult +import com.intellij.util.PathUtil import org.jdom.Element import org.jdom.Text import org.jetbrains.idea.maven.importing.MavenImporter @@ -139,6 +142,39 @@ class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_ } } + private fun configureJSOutputPaths( + mavenProject: MavenProject, + modifiableRootModel: ModifiableRootModel, + facetSettings: KotlinFacetSettings, + mavenPlugin: MavenPlugin + ) { + fun parentPath(path: String): String = + File(path).absoluteFile.parentFile.absolutePath + + val sharedOutputFile = mavenPlugin.configurationElement?.getChild("outputFile")?.text + + val compilerModuleExtension = modifiableRootModel.getModuleExtension(CompilerModuleExtension::class.java) ?: return + val buildDirectory = mavenProject.buildDirectory + + val executions = mavenPlugin.executions + + executions.forEach { + val explicitOutputFile = it.configurationElement?.getChild("outputFile")?.text ?: sharedOutputFile + if (PomFile.KotlinGoals.Js in it.goals) { + // see org.jetbrains.kotlin.maven.K2JSCompilerMojo + val outputFilePath = PathUtil.toSystemDependentName(explicitOutputFile ?: "$buildDirectory/js/${mavenProject.mavenId.artifactId}.js") + compilerModuleExtension.setCompilerOutputPath(parentPath(outputFilePath)) + facetSettings.productionOutputPath = outputFilePath + } + if (PomFile.KotlinGoals.TestJs in it.goals) { + // see org.jetbrains.kotlin.maven.KotlinTestJSCompilerMojo + val outputFilePath = PathUtil.toSystemDependentName(explicitOutputFile ?: "$buildDirectory/test-js/${mavenProject.mavenId.artifactId}-tests.js") + compilerModuleExtension.setCompilerOutputPathForTests(parentPath(outputFilePath)) + facetSettings.testOutputPath = outputFilePath + } + } + } + private fun getCompilerArgumentsByConfigurationElement( mavenProject: MavenProject, configuration: Element?, @@ -215,6 +251,7 @@ class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_ val platform = detectPlatform(mavenProject) kotlinFacet.configureFacet(compilerVersion, LanguageFeature.Coroutines.defaultState, platform, modifiableModelsProvider) + val facetSettings = kotlinFacet.configuration.settings val configuredPlatform = kotlinFacet.configuration.settings.targetPlatformKind!! val configuration = mavenPlugin.configurationElement val sharedArguments = getCompilerArgumentsByConfigurationElement(mavenProject, configuration, configuredPlatform) @@ -225,6 +262,9 @@ class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_ if (executionArguments != null) { parseCompilerArgumentsToFacet(executionArguments, emptyList(), kotlinFacet, modifiableModelsProvider) } + if (facetSettings.compilerArguments is K2JSCompilerArguments) { + configureJSOutputPaths(mavenProject, modifiableModelsProvider.getModifiableRootModel(module), facetSettings, mavenPlugin) + } MavenProjectImportHandler.getInstances(module.project).forEach { it(kotlinFacet, mavenProject) } setImplementedModuleName(kotlinFacet, mavenProject, module) kotlinFacet.noVersionAutoAdvance() diff --git a/idea/idea-maven/test/org/jetbrains/kotlin/idea/maven/KotlinMavenImporterTest.kt b/idea/idea-maven/test/org/jetbrains/kotlin/idea/maven/KotlinMavenImporterTest.kt index 89b4dcbece9..5bdb11696ce 100644 --- a/idea/idea-maven/test/org/jetbrains/kotlin/idea/maven/KotlinMavenImporterTest.kt +++ b/idea/idea-maven/test/org/jetbrains/kotlin/idea/maven/KotlinMavenImporterTest.kt @@ -20,9 +20,11 @@ import com.intellij.openapi.application.Result import com.intellij.openapi.application.WriteAction import com.intellij.openapi.projectRoots.JavaSdk import com.intellij.openapi.projectRoots.ProjectJdkTable +import com.intellij.openapi.roots.CompilerModuleExtension import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.impl.libraries.LibraryEx +import com.intellij.util.PathUtil import junit.framework.TestCase import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments @@ -632,6 +634,75 @@ class KotlinMavenImporterTest : MavenImportingTestCase() { Assert.assertTrue(ModuleRootManager.getInstance(getModule("project")).sdk!!.sdkType is KotlinSdkType) } + fun testJsCustomOutputPaths() { + createProjectSubDirs("src/main/kotlin", "src/test/kotlin") + importProject( + """ + test + project + 1.0.0 + + + + org.jetbrains.kotlin + kotlin-stdlib-js + $kotlinVersion + + + + + src/main/kotlin + + + + kotlin-maven-plugin + org.jetbrains.kotlin + $kotlinVersion + + + + compile + compile + + js + + + ${'$'}{project.basedir}/prod/main.js + + + + test-compile + test-compile + + test-js + + + ${'$'}{project.basedir}/test/test.js + + + + + + + """ + ) + + assertModules("project") + assertImporterStatePresent() + + val projectBasePath = myProjectsManager.projects.first().file.parent.path + + with(facetSettings) { + Assert.assertEquals("$projectBasePath/prod/main.js", PathUtil.toSystemIndependentName(productionOutputPath)) + Assert.assertEquals("$projectBasePath/test/test.js", PathUtil.toSystemIndependentName(testOutputPath)) + } + + with (CompilerModuleExtension.getInstance(getModule("project"))!!) { + Assert.assertEquals("$projectBasePath/prod", PathUtil.toSystemIndependentName(compilerOutputUrl)) + Assert.assertEquals("$projectBasePath/test", PathUtil.toSystemIndependentName(compilerOutputUrlForTests)) + } + } + fun testFacetSplitConfiguration() { createProjectSubDirs("src/main/kotlin", "src/main/kotlin.jvm", "src/test/kotlin", "src/test/kotlin.jvm") diff --git a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/KotlinJpsBuildTest.kt b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/KotlinJpsBuildTest.kt index c9131cc476d..15240773946 100644 --- a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/KotlinJpsBuildTest.kt +++ b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/KotlinJpsBuildTest.kt @@ -262,6 +262,13 @@ open class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() { return list.toTypedArray() } + fun testKotlinJavaScriptProjectWithCustomOutputPaths() { + initProject(JS_STDLIB) + buildAllModules().assertSuccessful() + + checkOutputFilesList(File(workDir, "target")) + } + fun testKotlinJavaScriptProjectWithSourceMap() { initProject(JS_STDLIB) buildAllModules().assertSuccessful() @@ -686,7 +693,7 @@ open class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() { } - private fun checkOutputFilesList() { + private fun checkOutputFilesList(outputDir: File = productionOutputDir) { if (!expectedOutputFile.exists()) { expectedOutputFile.writeText("") throw IllegalStateException("$expectedOutputFile did not exist. Created empty file.") @@ -694,7 +701,7 @@ open class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() { val sb = StringBuilder() val p = Printer(sb, " ") - productionOutputDir.printFilesRecursively(p) + outputDir.printFilesRecursively(p) UsefulTestCase.assertSameLinesWithFile(expectedOutputFile.canonicalPath, sb.toString(), true) } diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/JpsKotlinCompilerSettings.kt b/jps-plugin/src/org/jetbrains/kotlin/jps/JpsKotlinCompilerSettings.kt index f54ec737ba3..512b45fc59a 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/JpsKotlinCompilerSettings.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/JpsKotlinCompilerSettings.kt @@ -115,4 +115,18 @@ class JpsKotlinCompilerSettings : JpsElementBase() { } val JpsModule.targetPlatform: TargetPlatformKind<*>? - get() = kotlinFacetExtension?.settings?.targetPlatformKind \ No newline at end of file + get() = kotlinFacetExtension?.settings?.targetPlatformKind + +val JpsModule.productionOutputFilePath: String? + get() { + val facetSettings = kotlinFacetExtension?.settings ?: return null + if (facetSettings.useProjectSettings) return null + return facetSettings.productionOutputPath + } + +val JpsModule.testOutputFilePath: String? + get() { + val facetSettings = kotlinFacetExtension?.settings ?: return null + if (facetSettings.useProjectSettings) return null + return facetSettings.testOutputPath + } \ No newline at end of file diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt b/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt index abd199ac521..fad89465a20 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt @@ -56,6 +56,8 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.jps.JpsKotlinCompilerSettings import org.jetbrains.kotlin.jps.build.JpsJsModuleUtils.getOutputMetaFile import org.jetbrains.kotlin.jps.incremental.* +import org.jetbrains.kotlin.jps.productionOutputFilePath +import org.jetbrains.kotlin.jps.testOutputFilePath import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.modules.TargetId @@ -681,7 +683,9 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) { val representativeModule = representativeTarget.module val moduleName = representativeModule.name - val outputFile = JpsJsModuleUtils.getOutputFile(outputDir, moduleName, representativeTarget.isTests) + val isTests = representativeTarget.isTests + val explicitOutputPath = if (isTests) representativeModule.testOutputFilePath else representativeModule.productionOutputFilePath + val outputFile = explicitOutputPath?.let { File(it) } ?: JpsJsModuleUtils.getOutputFile(outputDir, moduleName, isTests) val libraries = JpsJsModuleUtils.getLibraryFilesAndDependencies(representativeTarget) val compilerSettings = JpsKotlinCompilerSettings.getCompilerSettings(representativeModule) val k2JsArguments = JpsKotlinCompilerSettings.getK2JsCompilerArguments(representativeModule) diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilderModuleScriptGenerator.kt b/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilderModuleScriptGenerator.kt index 04b2855d212..47584a2cf2d 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilderModuleScriptGenerator.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilderModuleScriptGenerator.kt @@ -34,6 +34,8 @@ import org.jetbrains.jps.model.module.JpsSdkDependency import org.jetbrains.kotlin.build.JvmSourceRoot import org.jetbrains.kotlin.config.IncrementalCompilation import org.jetbrains.kotlin.jps.build.JpsUtils.getAllDependencies +import org.jetbrains.kotlin.jps.productionOutputFilePath +import org.jetbrains.kotlin.jps.testOutputFilePath import org.jetbrains.kotlin.modules.KotlinModuleXmlBuilder import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.utils.addIfNotNull @@ -161,8 +163,11 @@ object KotlinBuilderModuleScriptGenerator { } } - fun getOutputDirSafe(target: ModuleBuildTarget): File = - target.outputDir ?: throw ProjectBuildException("No output directory found for " + target) + fun getOutputDirSafe(target: ModuleBuildTarget): File { + val explicitOutputPath = if (target.isTests) target.module.testOutputFilePath else target.module.productionOutputFilePath + val explicitOutputDir = explicitOutputPath?.let { File(it).absoluteFile.parentFile } + return explicitOutputDir ?: target.outputDir ?: throw ProjectBuildException("No output directory found for " + target) + } fun getProductionModulesWhichInternalsAreVisible(from: ModuleBuildTarget): List { if (!from.isTests) return emptyList() diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/expected-output.txt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/expected-output.txt new file mode 100644 index 00000000000..2d80d94ec34 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/expected-output.txt @@ -0,0 +1,16 @@ +my_js/ + lib/ + kotlin.js + kotlin.meta.js + myproject/ + root-package.kjsm + myproject.js + myproject.meta.js +my_test-js/ + lib/ + kotlin.js + kotlin.meta.js + myproject-tests/ + root-package.kjsm + myproject-tests.js + myproject-tests.meta.js \ No newline at end of file diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/kotlinProject.iml b/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/kotlinProject.iml new file mode 100644 index 00000000000..2b070ee7b93 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/kotlinProject.iml @@ -0,0 +1,32 @@ + + + + + + $MODULE_DIR$/target/my_js/myproject.js + $MODULE_DIR$/target/my_test-js/myproject-tests.js + + + + + + + + + + + + + + + + + + + diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/kotlinProject.ipr b/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/kotlinProject.ipr new file mode 100644 index 00000000000..90747786771 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/kotlinProject.ipr @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/src/main.kt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/src/main.kt new file mode 100644 index 00000000000..adb5b33c573 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/src/main.kt @@ -0,0 +1,3 @@ +fun main(args: Array) { + +} \ No newline at end of file diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/src/main/kotlin/main.kt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/src/main/kotlin/main.kt new file mode 100644 index 00000000000..adb5b33c573 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/src/main/kotlin/main.kt @@ -0,0 +1,3 @@ +fun main(args: Array) { + +} \ No newline at end of file diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/src/test/kotlin/test.kt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/src/test/kotlin/test.kt new file mode 100644 index 00000000000..442858bd7b3 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithCustomOutputPaths/src/test/kotlin/test.kt @@ -0,0 +1,3 @@ +fun test() { + +} \ No newline at end of file