diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java b/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java index aadbc36b946..ed298228f3d 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/js/K2JSCompiler.java @@ -25,8 +25,6 @@ import com.intellij.util.Function; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; -import kotlin.Unit; -import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.analyzer.AnalysisResult; @@ -140,11 +138,15 @@ public class K2JSCompiler extends CLICompiler { configuration.put(CommonConfigurationKeys.MODULE_NAME, FileUtil.getNameWithoutExtension(outputFile)); JsConfig config = new LibrarySourcesConfig(project, configuration); - if (config.checkLibFilesAndReportErrors(new Function1() { + if (config.checkLibFilesAndReportErrors(new JsConfig.Reporter() { @Override - public Unit invoke(String message) { + public void error(@NotNull String message) { messageCollector.report(CompilerMessageSeverity.ERROR, message, CompilerMessageLocation.NO_LOCATION); - return Unit.INSTANCE; + } + + @Override + public void warning(@NotNull String message) { + messageCollector.report(CompilerMessageSeverity.WARNING, message, CompilerMessageLocation.NO_LOCATION); } })) { return COMPILATION_ERROR; 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 a1b902c814a..030c6284145 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 @@ -33,7 +33,6 @@ import org.jetbrains.jps.builders.CompileScopeTestBuilder import org.jetbrains.jps.builders.JpsBuildTestCase import org.jetbrains.jps.builders.TestProjectBuilderLogger import org.jetbrains.jps.builders.impl.BuildDataPathsImpl -import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerImpl import org.jetbrains.jps.builders.logging.BuildLoggingManager import org.jetbrains.jps.cmdline.ProjectDescriptor import org.jetbrains.jps.incremental.BuilderRegistry @@ -50,13 +49,10 @@ 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.config.KotlinCompilerVersion -import org.jetbrains.kotlin.daemon.common.COMPILE_DAEMON_ENABLED_PROPERTY import org.jetbrains.kotlin.incremental.CacheVersion import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.withIC import org.jetbrains.kotlin.jps.build.KotlinJpsBuildTest.LibraryDependency.* -import org.jetbrains.kotlin.load.kotlin.DeserializedDescriptorResolver import org.jetbrains.kotlin.load.kotlin.DeserializedDescriptorResolver.Companion.TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils import org.jetbrains.kotlin.name.FqName @@ -376,6 +372,26 @@ class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() { assertEquals(Collections.EMPTY_SET, contentOfOutputDir(PROJECT_NAME)) } + fun testKotlinJavaScriptProjectWithTests() { + initProject(JS_STDLIB) + makeAll().assertSuccessful() + } + + fun testKotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies() { + initProject(JS_STDLIB) + makeAll().assertSuccessful() + } + + fun testKotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency() { + initProject(JS_STDLIB) + val buildResult = makeAll() + buildResult.assertSuccessful() + + val warnings = buildResult.getMessages(BuildMessage.Kind.WARNING) + assertEquals("Warning about duplicate module definition: $warnings", 1, warnings.size) + assertEquals("Module \"srcAndTests\" is defined in more, than one file", warnings.first().messageText) + } + fun testExcludeFolderInSourceRoot() { doTest() diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/build/JpsJsModuleUtils.kt b/jps-plugin/src/org/jetbrains/kotlin/jps/build/JpsJsModuleUtils.kt index b329ce89e8d..9dc917535ce 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/build/JpsJsModuleUtils.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/build/JpsJsModuleUtils.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.jps.build import com.intellij.util.Consumer import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType import org.jetbrains.jps.incremental.ModuleBuildTarget +import org.jetbrains.jps.model.java.JavaSourceRootType import org.jetbrains.jps.model.java.JpsJavaModuleType import org.jetbrains.jps.model.library.JpsOrderRootType import org.jetbrains.jps.model.module.JpsModule @@ -47,12 +48,21 @@ object JpsJsModuleUtils { fun getDependencyModulesAndSources(target: ModuleBuildTarget, result: MutableList) { JpsUtils.getAllDependencies(target).processModules(object : Consumer { override fun consume(module: JpsModule) { - if (module == target.module || module.moduleType != JpsJavaModuleType.INSTANCE) return + if (module.moduleType != JpsJavaModuleType.INSTANCE) return - val moduleBuildTarget = ModuleBuildTarget(module, JavaModuleBuildTargetType.PRODUCTION) - val outputDir = KotlinBuilderModuleScriptGenerator.getOutputDirSafe(moduleBuildTarget) - val metaInfoFile = getOutputMetaFile(outputDir, module.name) - result.add(metaInfoFile.absolutePath) + for (root in module.sourceRoots) { + val isTestSource = root.rootType == JavaSourceRootType.TEST_SOURCE + + if (module == target.module && isTestSource == target.isTests) continue + + if (!isTestSource || target.isTests) { + val targetType = if (isTestSource) JavaModuleBuildTargetType.TEST else JavaModuleBuildTargetType.PRODUCTION + val moduleBuildTarget = ModuleBuildTarget(module, targetType) + val outputDir = KotlinBuilderModuleScriptGenerator.getOutputDirSafe(moduleBuildTarget) + val metaInfoFile = getOutputMetaFile(outputDir, module.name) + result.add(metaInfoFile.absolutePath) + } + } } }) } diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTests/kotlinProject.iml b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTests/kotlinProject.iml new file mode 100644 index 00000000000..350676073d1 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTests/kotlinProject.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTests/kotlinProject.ipr b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTests/kotlinProject.ipr new file mode 100644 index 00000000000..0c363fe68d2 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTests/kotlinProject.ipr @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTests/src/Main.kt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTests/src/Main.kt new file mode 100644 index 00000000000..e97bc7ec751 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTests/src/Main.kt @@ -0,0 +1,2 @@ +fun main() { +} \ No newline at end of file diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTests/tests/MainTests.kt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTests/tests/MainTests.kt new file mode 100644 index 00000000000..d0fbf1444f8 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTests/tests/MainTests.kt @@ -0,0 +1,3 @@ +fun testMain() { + main() +} \ No newline at end of file diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/kotlinProject.iml b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/kotlinProject.iml new file mode 100644 index 00000000000..62e30d76009 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/kotlinProject.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/kotlinProject.ipr b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/kotlinProject.ipr new file mode 100644 index 00000000000..6c1fe3fe02d --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/kotlinProject.ipr @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/src/Main.kt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/src/Main.kt new file mode 100644 index 00000000000..d922182462e --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/src/Main.kt @@ -0,0 +1,3 @@ +fun main() { + srcOnly() +} diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/srcOnly/src/SrcOnly.kt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/srcOnly/src/SrcOnly.kt new file mode 100644 index 00000000000..51563329121 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/srcOnly/src/SrcOnly.kt @@ -0,0 +1 @@ +fun srcOnly() {} diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/srcOnly/srcOnly.iml b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/srcOnly/srcOnly.iml new file mode 100644 index 00000000000..c90834f2d60 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/srcOnly/srcOnly.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/tests/MainTests.kt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/tests/MainTests.kt new file mode 100644 index 00000000000..882f75a9953 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/tests/MainTests.kt @@ -0,0 +1,5 @@ +fun testMain() { + main() + srcOnly() + testsOnly() +} diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/testsOnly/tests/TestsOnly.kt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/testsOnly/tests/TestsOnly.kt new file mode 100644 index 00000000000..b9c5f8d81ae --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/testsOnly/tests/TestsOnly.kt @@ -0,0 +1 @@ +fun testsOnly() {} \ No newline at end of file diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/testsOnly/testsOnly.iml b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/testsOnly/testsOnly.iml new file mode 100644 index 00000000000..d732721923c --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndSeparateTestAndSrcModuleDependencies/testsOnly/testsOnly.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/kotlinProject.iml b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/kotlinProject.iml new file mode 100644 index 00000000000..f3d9af241fb --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/kotlinProject.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/kotlinProject.ipr b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/kotlinProject.ipr new file mode 100644 index 00000000000..6a444a0b5a8 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/kotlinProject.ipr @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/src/Main.kt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/src/Main.kt new file mode 100644 index 00000000000..5816452a2df --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/src/Main.kt @@ -0,0 +1,3 @@ +fun main() { + srcAndTests() +} diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/srcAndTests/src/SrcAndTests.kt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/srcAndTests/src/SrcAndTests.kt new file mode 100644 index 00000000000..4770f151401 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/srcAndTests/src/SrcAndTests.kt @@ -0,0 +1 @@ +fun srcAndTests() {} diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/srcAndTests/srcAndTests.iml b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/srcAndTests/srcAndTests.iml new file mode 100644 index 00000000000..fc6e2c7a9cf --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/srcAndTests/srcAndTests.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/srcAndTests/tests/SrcAndTestsTests.kt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/srcAndTests/tests/SrcAndTestsTests.kt new file mode 100644 index 00000000000..dcdc8f6d32a --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/srcAndTests/tests/SrcAndTestsTests.kt @@ -0,0 +1,3 @@ +fun testSrcAndTests() { + srcAndTests() +} diff --git a/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/tests/MainTests.kt b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/tests/MainTests.kt new file mode 100644 index 00000000000..2035cec6386 --- /dev/null +++ b/jps-plugin/testData/general/KotlinJavaScriptProjectWithTestsAndTestAndSrcModuleDependency/tests/MainTests.kt @@ -0,0 +1,5 @@ +fun testMain() { + main() + srcAndTests() + testSrcAndTests() +} diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java b/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java index 76687e93045..719c4ed8300 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/config/JsConfig.java @@ -19,9 +19,7 @@ package org.jetbrains.kotlin.js.config; import com.google.common.collect.Lists; import com.intellij.openapi.project.Project; import com.intellij.util.SmartList; -import kotlin.Unit; import kotlin.collections.CollectionsKt; -import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.config.CommonConfigurationKeys; @@ -87,7 +85,12 @@ public abstract class JsConfig { return configuration.get(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN); } - public abstract boolean checkLibFilesAndReportErrors(@NotNull Function1 report); + public static abstract class Reporter { + public void error(@NotNull String message) { /*Do nothing*/ } + public void warning(@NotNull String message) { /*Do nothing*/ } + } + + public abstract boolean checkLibFilesAndReportErrors(@NotNull Reporter report); protected abstract void init(@NotNull List sourceFilesInLibraries, @NotNull List metadata); diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/config/LibrarySourcesConfig.java b/js/js.frontend/src/org/jetbrains/kotlin/js/config/LibrarySourcesConfig.java index 7b5fa22a057..a9adc6097b7 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/config/LibrarySourcesConfig.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/config/LibrarySourcesConfig.java @@ -25,7 +25,6 @@ import com.intellij.psi.PsiManager; import com.intellij.util.PathUtil; import com.intellij.util.io.URLUtil; import kotlin.Unit; -import kotlin.jvm.functions.Function1; import kotlin.jvm.functions.Function2; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,7 +38,9 @@ import org.jetbrains.kotlin.utils.LibraryUtils; import java.io.File; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import static org.jetbrains.kotlin.utils.LibraryUtils.isOldKotlinJavascriptLibrary; import static org.jetbrains.kotlin.utils.PathUtil.getKotlinPathsForDistDirectory; @@ -69,9 +70,9 @@ public class LibrarySourcesConfig extends JsConfig { final PsiManager psiManager = PsiManager.getInstance(getProject()); - Function1 report = new Function1() { + JsConfig.Reporter report = new JsConfig.Reporter() { @Override - public Unit invoke(String message) { + public void error(@NotNull String message) { throw new IllegalStateException(message); } }; @@ -98,11 +99,11 @@ public class LibrarySourcesConfig extends JsConfig { } @Override - public boolean checkLibFilesAndReportErrors(@NotNull Function1 report) { + public boolean checkLibFilesAndReportErrors(@NotNull JsConfig.Reporter report) { return checkLibFilesAndReportErrors(report, null); } - private boolean checkLibFilesAndReportErrors(@NotNull Function1 report, @Nullable Function2 action) { + private boolean checkLibFilesAndReportErrors(@NotNull JsConfig.Reporter report, @Nullable Function2 action) { List libraries = getLibraries(); if (libraries.isEmpty()) { return false; @@ -111,12 +112,14 @@ public class LibrarySourcesConfig extends JsConfig { VirtualFileSystem fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL); VirtualFileSystem jarFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.JAR_PROTOCOL); + Set modules = new HashSet(); + for (String path : libraries) { VirtualFile file; File filePath = new File(path); if (!filePath.exists()) { - report.invoke("Path '" + path + "' does not exist"); + report.error("Path '" + path + "' does not exist"); return true; } @@ -128,7 +131,7 @@ public class LibrarySourcesConfig extends JsConfig { } if (file == null) { - report.invoke("File '" + path + "' does not exist or could not be read"); + report.error("File '" + path + "' does not exist or could not be read"); return true; } @@ -136,21 +139,27 @@ public class LibrarySourcesConfig extends JsConfig { if (isOldKotlinJavascriptLibrary(filePath)) { moduleName = LibraryUtils.getKotlinJsModuleName(filePath); + if (!modules.add(moduleName)) { + report.warning("Module \"" + moduleName + "\" is defined in more, than one file"); + } } else { List metadataList = KotlinJavascriptMetadataUtils.loadMetadata(filePath); if (metadataList.isEmpty()) { - report.invoke("'" + path + "' is not a valid Kotlin Javascript library"); + report.error("'" + path + "' is not a valid Kotlin Javascript library"); return true; } for (KotlinJavascriptMetadata metadata : metadataList) { if (!metadata.getVersion().isCompatible()) { - report.invoke("File '" + path + "' was compiled with an incompatible version of Kotlin. " + - "The binary version of its metadata is " + metadata.getVersion() + - ", expected version is " + JsMetadataVersion.INSTANCE); + report.error("File '" + path + "' was compiled with an incompatible version of Kotlin. " + + "The binary version of its metadata is " + metadata.getVersion() + + ", expected version is " + JsMetadataVersion.INSTANCE); return true; } + if (!modules.add(metadata.getModuleName())) { + report.warning("Module \"" + metadata.getModuleName() + "\" is defined in more, than one file"); + } } moduleName = null; diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt index 1ec97d72f01..eed02593bff 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/FunctionReader.kt @@ -16,13 +16,13 @@ package org.jetbrains.kotlin.js.inline -import org.jetbrains.kotlin.js.backend.ast.metadata.inlineStrategy +import com.google.common.collect.HashMultimap import com.google.gwt.dev.js.ThrowExceptionOnErrorReporter import com.intellij.util.containers.SLRUCache -import org.jetbrains.kotlin.builtins.isExtensionFunctionType import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.js.backend.ast.* +import org.jetbrains.kotlin.js.backend.ast.metadata.inlineStrategy import org.jetbrains.kotlin.js.config.LibrarySourcesConfig import org.jetbrains.kotlin.js.inline.util.IdentitySet import org.jetbrains.kotlin.js.inline.util.isCallInvocation @@ -51,22 +51,18 @@ private val DEFINE_MODULE_FIND_PATTERN = ".defineModule(" class FunctionReader(private val context: TranslationContext) { /** - * Maps module name to .js file content, that contains this module definition. - * One file can contain more than one module definition. + * fileContent: .js file content, that contains this module definition. + * One file can contain more than one module definition. + * + * moduleVariable: the variable used to call functions inside module. + * The default variable is _, but it can be renamed by minifier. + * + * kotlinVariable: kotlin object variable. + * The default variable is Kotlin, but it can be renamed by minifier. */ - private val moduleJsDefinition = hashMapOf() + data class ModuleInfo(val fileContent: String, val moduleVariable: String, val kotlinVariable: String) - /** - * Maps module name to variable, that is used to call functions inside module. - * The default variable is _, but it can be renamed by minifier. - */ - private val moduleRootVariable = hashMapOf() - - /** - * Maps moduleName to kotlin object variable. - * The default variable is Kotlin, but it can be renamed by minifier. - */ - private val moduleKotlinVariable = hashMapOf() + private val moduleNameToInfo = HashMultimap.create() init { val config = context.config as LibrarySourcesConfig @@ -87,10 +83,7 @@ class FunctionReader(private val context: TranslationContext) { val moduleName = preciseMatcher.group(3) val moduleVariable = preciseMatcher.group(4) val kotlinVariable = preciseMatcher.group(1) - assert(moduleName !in moduleJsDefinition) { "Module \"$moduleName\" is defined in more, than one file" } - moduleJsDefinition[moduleName] = fileContent - moduleRootVariable[moduleName] = moduleVariable - moduleKotlinVariable[moduleName] = kotlinVariable + moduleNameToInfo.put(moduleName, ModuleInfo(fileContent, moduleVariable, kotlinVariable)) } } } @@ -122,7 +115,7 @@ class FunctionReader(private val context: TranslationContext) { operator fun contains(descriptor: CallableDescriptor): Boolean { val moduleName = getExternalModuleName(descriptor) val currentModuleName = context.config.moduleId - return currentModuleName != moduleName && moduleName != null && moduleName in moduleJsDefinition + return currentModuleName != moduleName && moduleName != null && moduleName in moduleNameToInfo.keys() } operator fun get(descriptor: CallableDescriptor): JsFunction = functionCache.get(descriptor) @@ -131,13 +124,17 @@ class FunctionReader(private val context: TranslationContext) { if (descriptor !in this) return null val moduleName = getExternalModuleName(descriptor) - val file = moduleJsDefinition[moduleName].sure { "Module $moduleName file have not been read" } - val function = readFunctionFromSource(descriptor, file) - function?.markInlineArguments(descriptor) - return function + + for (info in moduleNameToInfo[moduleName]) { + val function = readFunctionFromSource(descriptor, info) + if (function != null) return function + } + + return null } - private fun readFunctionFromSource(descriptor: CallableDescriptor, source: String): JsFunction? { + private fun readFunctionFromSource(descriptor: CallableDescriptor, info: ModuleInfo): JsFunction? { + val source = info.fileContent val tag = Namer.getFunctionTag(descriptor) val index = source.indexOf(tag) if (index < 0) return null @@ -149,12 +146,12 @@ class FunctionReader(private val context: TranslationContext) { } val function = parseFunction(source, offset, ThrowExceptionOnErrorReporter, JsRootScope(JsProgram())) - val moduleName = getExternalModuleName(descriptor)!! val moduleReference = context.getModuleExpressionFor(descriptor) ?: getRootPackage() - val replacements = hashMapOf(moduleRootVariable[moduleName]!! to moduleReference, - moduleKotlinVariable[moduleName]!! to Namer.kotlinObject()) + val replacements = hashMapOf(info.moduleVariable to moduleReference, + info.kotlinVariable to Namer.kotlinObject()) replaceExternalNames(function, replacements) + function.markInlineArguments(descriptor) return function }