diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt index 1b173f235a8..a4479386895 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -136,6 +136,7 @@ import org.jetbrains.jet.types.AbstractJetTypeBindingTest import org.jetbrains.jet.plugin.debugger.evaluate.AbstractCodeFragmentCompletionHandlerTest import org.jetbrains.jet.plugin.coverage.AbstractKotlinCoverageOutputFilesTest import org.jetbrains.k2js.test.semantics.AbstractDynamicTest +import org.jetbrains.k2js.test.semantics.AbstractMultiModuleTest fun main(args: Array) { System.setProperty("java.awt.headless", "true") @@ -692,6 +693,10 @@ fun main(args: Array) { testClass(javaClass()) { model("dynamic/cases") } + + testClass(javaClass()) { + model("multiModule/cases", extension = null, recursive=false) + } } testGroup("js/js.tests/test", "compiler/testData") { diff --git a/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java b/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java index 6d4940f4732..7bda865a769 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java @@ -42,6 +42,7 @@ import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.k2js.JavaScript; import org.jetbrains.k2js.config.Config; import org.jetbrains.k2js.config.EcmaVersion; +import org.jetbrains.k2js.config.LibrarySourcesConfig; import org.jetbrains.k2js.config.LibrarySourcesConfigWithCaching; import org.jetbrains.k2js.facade.Status; import org.jetbrains.k2js.facade.MainCallParameters; @@ -51,6 +52,7 @@ import org.jetbrains.k2js.translate.context.Namer; import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -143,13 +145,24 @@ public abstract class BasicTest extends KotlinTestWithEnvironment { @NotNull String testName, @NotNull MainCallParameters mainCallParameters, @NotNull Iterable ecmaVersions + ) throws Exception { + generateJavaScriptFiles(files, testName, mainCallParameters, ecmaVersions, TEST_MODULE, null); + } + + protected void generateJavaScriptFiles( + @NotNull List files, + @NotNull String testName, + @NotNull MainCallParameters mainCallParameters, + @NotNull Iterable ecmaVersions, + @NotNull String moduleName, + @Nullable List libraries ) throws Exception { Project project = getProject(); List allFiles = withAdditionalKotlinFiles(files); List jetFiles = createJetFileList(project, allFiles, null); for (EcmaVersion version : ecmaVersions) { - Config config = createConfig(getProject(), TEST_MODULE, version); + Config config = createConfig(getProject(), moduleName, version, libraries); File outputFile = new File(getOutputFilePath(testName, version)); translateFiles(jetFiles, outputFile, mainCallParameters, config); @@ -265,9 +278,20 @@ public abstract class BasicTest extends KotlinTestWithEnvironment { } @NotNull - private Config createConfig(@NotNull Project project, @NotNull String moduleId, @NotNull EcmaVersion ecmaVersion) { - return new LibrarySourcesConfigWithCaching(project, moduleId, ecmaVersion, - shouldGenerateSourcemap(), IS_INLINE_ENABLED, shouldBeTranslateAsUnitTestClass()); + private Config createConfig(@NotNull Project project, @NotNull String moduleId, @NotNull EcmaVersion ecmaVersion, @Nullable List libraries) { + if (libraries == null) { + return new LibrarySourcesConfigWithCaching(project, moduleId, ecmaVersion, shouldGenerateSourcemap(), IS_INLINE_ENABLED, shouldBeTranslateAsUnitTestClass()); + } + else { + return new LibrarySourcesConfig(project, moduleId, librariesWithJsStdlib(libraries), ecmaVersion, shouldGenerateSourcemap(), IS_INLINE_ENABLED); + } + } + + @NotNull + private static List librariesWithJsStdlib(List libraries) { + List result = new ArrayList(libraries); + result.addAll(0, LibrarySourcesConfigWithCaching.JS_STDLIB); + return result; } @NotNull @@ -341,5 +365,4 @@ public abstract class BasicTest extends KotlinTestWithEnvironment { return path.substring(start, end); } - } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/MultipleModulesTranslationTest.kt b/js/js.tests/test/org/jetbrains/k2js/test/MultipleModulesTranslationTest.kt new file mode 100644 index 00000000000..7280ead119a --- /dev/null +++ b/js/js.tests/test/org/jetbrains/k2js/test/MultipleModulesTranslationTest.kt @@ -0,0 +1,98 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.k2js.test + +import org.jetbrains.k2js.config.EcmaVersion +import org.jetbrains.k2js.facade.MainCallParameters +import org.jetbrains.k2js.test.BasicTest +import org.jetbrains.k2js.test.rhino.RhinoFunctionResultChecker + +import java.io.File +import java.util.ArrayList + +import org.jetbrains.k2js.test.utils.JsTestUtils.getAllFilesInDir +import java.util.HashMap +import java.util.LinkedHashMap +import java.util.Collections + +public abstract class MultipleModulesTranslationTest(main: String) : BasicTest(main) { + + private val MAIN_MODULE_NAME: String = "main" + private var dependencies: Map>? = null + + override fun checkFooBoxIsOkByPath(filePath: String) { + val dirName = getTestName(true) + dependencies = readModuleDependencies(filePath) + + for ((moduleName, dependencies) in dependencies) { + translateModule(dirName, filePath, moduleName, *dependencies) + } + + val filename = getInputFilePath(getModuleDirectoryName(dirName, MAIN_MODULE_NAME) + File.separator + MAIN_MODULE_NAME + ".kt") + val packageName = getPackageName(filename) + runMultiModuleTest(dirName, packageName, BasicTest.TEST_FUNCTION, "OK") + } + + private fun runMultiModuleTest(dirName: String, packageName: String, functionName: String, expectedResult: Any) { + val moduleDirectoryName = getModuleDirectoryName(dirName, MAIN_MODULE_NAME) + runRhinoTests(moduleDirectoryName, BasicTest.DEFAULT_ECMA_VERSIONS, RhinoFunctionResultChecker(MAIN_MODULE_NAME, packageName, functionName, expectedResult)) + } + + private fun translateModule(dirName: String, pathToDir: String, moduleName: String, vararg dependencies: String) { + val moduleDirectoryName = getModuleDirectoryName(dirName, moduleName) + val fullFilePaths = getAllFilesInDir(pathToDir + File.separator + moduleName) + val libraries = ArrayList() + for (dependencyName in dependencies) { + libraries.add("@" + dependencyName) + libraries.add(pathToDir + File.separator + dependencyName) + } + generateJavaScriptFiles(fullFilePaths, moduleDirectoryName, MainCallParameters.noCall(), BasicTest.DEFAULT_ECMA_VERSIONS, moduleName, libraries) + } + + override fun additionalJsFiles(ecmaVersion: EcmaVersion): List { + val result = super.additionalJsFiles(ecmaVersion) + val dirName = getTestName(true) + assert(dependencies != null, "dependencies should not be null") + + for (moduleName in dependencies!!.keySet()) { + if (moduleName != MAIN_MODULE_NAME) { + result.add(getOutputFilePath(getModuleDirectoryName(dirName, moduleName), ecmaVersion)) + } + } + + return result + } + + private fun readModuleDependencies(testDataDir: String): Map> { + val dependenciesTxt = File(testDataDir, "dependencies.txt") + assert(dependenciesTxt.exists(), "moduleDependencies should not be null") + + val result = LinkedHashMap>() + for (line in dependenciesTxt.readLines()) { + val split = line.split("->") + val module = split[0] + val dependencies = if (split.size() > 1) split[1].split(",") else array() + + result[module] = dependencies//.toList() + } + + return result + } + + + private fun getModuleDirectoryName(dirName: String, moduleName: String) = dirName + File.separator + moduleName +} diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/AbstractMultiModuleTest.kt b/js/js.tests/test/org/jetbrains/k2js/test/semantics/AbstractMultiModuleTest.kt new file mode 100644 index 00000000000..088eee97b2f --- /dev/null +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/AbstractMultiModuleTest.kt @@ -0,0 +1,5 @@ +package org.jetbrains.k2js.test.semantics + +import org.jetbrains.k2js.test.MultipleModulesTranslationTest + +public abstract class AbstractMultiModuleTest : MultipleModulesTranslationTest("multiModule/") \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MultiModuleTestGenerated.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MultiModuleTestGenerated.java new file mode 100644 index 00000000000..84a68c9494a --- /dev/null +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MultiModuleTestGenerated.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.k2js.test.semantics; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.jet.JUnit3RunnerWithInners; +import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.test.InnerTestClasses; +import org.jetbrains.jet.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("js/js.translator/testData/multiModule/cases") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class MultiModuleTestGenerated extends AbstractMultiModuleTest { + public void testAllFilesPresentInCases() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/multiModule/cases"), Pattern.compile("^([^\\.]+)$"), false); + } + + @TestMetadata("useElementsFromDefaultPackageInAnotherModule") + public void testUseElementsFromDefaultPackageInAnotherModule() throws Exception { + String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/multiModule/cases/useElementsFromDefaultPackageInAnotherModule/"); + doTest(fileName); + } +} diff --git a/js/js.translator/testData/multiModule/cases/useElementsFromDefaultPackageInAnotherModule/dependencies.txt b/js/js.translator/testData/multiModule/cases/useElementsFromDefaultPackageInAnotherModule/dependencies.txt new file mode 100644 index 00000000000..6db4872a51a --- /dev/null +++ b/js/js.translator/testData/multiModule/cases/useElementsFromDefaultPackageInAnotherModule/dependencies.txt @@ -0,0 +1,2 @@ +module1-> +main->module1 \ No newline at end of file diff --git a/js/js.translator/testData/multiModule/cases/useElementsFromDefaultPackageInAnotherModule/main/main.kt b/js/js.translator/testData/multiModule/cases/useElementsFromDefaultPackageInAnotherModule/main/main.kt new file mode 100644 index 00000000000..2d31465abf0 --- /dev/null +++ b/js/js.translator/testData/multiModule/cases/useElementsFromDefaultPackageInAnotherModule/main/main.kt @@ -0,0 +1,7 @@ +fun box(): String { + + assertEquals("A: invoked from module", f("A")) + assertEquals(10, A(10).x) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/multiModule/cases/useElementsFromDefaultPackageInAnotherModule/module1/module1.kt b/js/js.translator/testData/multiModule/cases/useElementsFromDefaultPackageInAnotherModule/module1/module1.kt new file mode 100644 index 00000000000..efb9d92629d --- /dev/null +++ b/js/js.translator/testData/multiModule/cases/useElementsFromDefaultPackageInAnotherModule/module1/module1.kt @@ -0,0 +1,3 @@ +public fun f(s: String): String = "${s}: invoked from module" + +public class A(val x: Int) \ No newline at end of file