diff --git a/compiler/backend-common/src/output.kt b/compiler/backend-common/src/output.kt index ecdc0dd35e6..c4f78cdb1ce 100644 --- a/compiler/backend-common/src/output.kt +++ b/compiler/backend-common/src/output.kt @@ -23,9 +23,23 @@ public trait OutputFileCollection { public fun asList(): List } +public class SimpleOutputFileCollection(private val outputFiles: List) : OutputFileCollection { + override fun get(relativePath: String): OutputFile? = outputFiles.find { it.relativePath == relativePath } + override fun asList(): List = outputFiles +} + public trait OutputFile { public val relativePath: String public val sourceFiles: List public fun asByteArray(): ByteArray public fun asText(): String +} + +class SimpleOutputFile( + public override val sourceFiles: List, + public override val relativePath: String, + private val content: String +) : OutputFile { + override fun asByteArray(): ByteArray = content.toByteArray() + override fun asText(): String = content } \ No newline at end of file diff --git a/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java index f5a42afe5e0..886c4712c42 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java @@ -16,18 +16,19 @@ package org.jetbrains.jet.cli.js; -import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Predicates; -import com.google.common.collect.Iterables; import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import jet.Function0; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.OutputFileCollection; import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.cli.common.CLICompiler; import org.jetbrains.jet.cli.common.ExitCode; @@ -37,6 +38,9 @@ import org.jetbrains.jet.cli.common.messages.AnalyzerWithCompilerReport; import org.jetbrains.jet.cli.common.messages.CompilerMessageLocation; import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity; import org.jetbrains.jet.cli.common.messages.MessageCollector; +import org.jetbrains.jet.cli.common.output.OutputDirector; +import org.jetbrains.jet.cli.common.output.SingleDirectoryDirector; +import org.jetbrains.jet.cli.common.output.outputUtils.OutputUtilsPackage; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.config.CommonConfigurationKeys; import org.jetbrains.jet.config.CompilerConfiguration; @@ -84,23 +88,25 @@ public class K2JSCompiler extends CLICompiler { JetCoreEnvironment environmentForJS = JetCoreEnvironment.createForProduction(rootDisposable, configuration); Project project = environmentForJS.getProject(); + List sourcesFiles = environmentForJS.getSourceFiles(); ClassPathLibrarySourcesLoader sourceLoader = new ClassPathLibrarySourcesLoader(project); - List sourceFiles = sourceLoader.findSourceFiles(); - environmentForJS.getSourceFiles().addAll(sourceFiles); + List additionalSourceFiles = sourceLoader.findSourceFiles(); + sourcesFiles.addAll(additionalSourceFiles); if (arguments.verbose) { - reportCompiledSourcesList(messageCollector, environmentForJS); + reportCompiledSourcesList(messageCollector, sourcesFiles); } - String outputFile = arguments.outputFile; - if (outputFile == null) { + if (arguments.outputFile == null) { messageCollector.report(CompilerMessageSeverity.ERROR, "Specify output file via -output", CompilerMessageLocation.NO_LOCATION); return ExitCode.INTERNAL_ERROR; } + File outputFile = new File(arguments.outputFile); + Config config = getConfig(arguments, project); - if (analyzeAndReportErrors(messageCollector, environmentForJS.getSourceFiles(), config)) { + if (analyzeAndReportErrors(messageCollector, sourcesFiles, config)) { return COMPILATION_ERROR; } @@ -127,15 +133,19 @@ public class K2JSCompiler extends CLICompiler { } MainCallParameters mainCallParameters = createMainCallParameters(arguments.main); - return translateAndGenerateOutputFile(mainCallParameters, environmentForJS, config, outputFile, outputPrefixFile, outputPostfixFile); + + OutputFileCollection outputFiles = translate(mainCallParameters, config, sourcesFiles, outputFile, outputPrefixFile, outputPostfixFile); + + OutputDirector outputDirector = new SingleDirectoryDirector(outputFile.getParentFile()); + OutputUtilsPackage.writeAll(outputFiles, outputDirector, messageCollector); + + return OK; } - private static void reportCompiledSourcesList(@NotNull MessageCollector messageCollector, - @NotNull JetCoreEnvironment environmentForJS) { - List files = environmentForJS.getSourceFiles(); - Iterable fileNames = Iterables.transform(files, new Function() { + private static void reportCompiledSourcesList(@NotNull MessageCollector messageCollector, @NotNull List sourceFiles) { + Iterable fileNames = ContainerUtil.map(sourceFiles, new Function() { @Override - public String apply(@Nullable JetFile file) { + public String fun(@Nullable JetFile file) { assert file != null; VirtualFile virtualFile = file.getVirtualFile(); if (virtualFile != null) { @@ -148,23 +158,20 @@ public class K2JSCompiler extends CLICompiler { CompilerMessageLocation.NO_LOCATION); } - @NotNull - private static ExitCode translateAndGenerateOutputFile( + private static OutputFileCollection translate( @NotNull MainCallParameters mainCall, - @NotNull JetCoreEnvironment environmentForJS, @NotNull Config config, - @NotNull String outputFile, + @NotNull List sourceFiles, + @NotNull File outputFile, @Nullable File outputPrefix, @Nullable File outputPostfix ) { try { - K2JSTranslator.translateWithMainCallParametersAndSaveToFile(mainCall, environmentForJS.getSourceFiles(), - outputFile, outputPrefix, outputPostfix, config); + return K2JSTranslator.translateWithMainCallParameters(mainCall, sourceFiles, outputFile, outputPrefix, outputPostfix, config); } catch (Exception e) { throw new RuntimeException(e); } - return OK; } private static boolean analyzeAndReportErrors(@NotNull MessageCollector messageCollector, diff --git a/compiler/util/src/org/jetbrains/jet/utils/fileUtils.kt b/compiler/util/src/org/jetbrains/jet/utils/fileUtils.kt new file mode 100644 index 00000000000..50d5245c3ce --- /dev/null +++ b/compiler/util/src/org/jetbrains/jet/utils/fileUtils.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2013 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.jet.utils.fileUtils + +import java.io.File + + +// TODO: move to stdlib as: +// public fun File?.readTextOrEmpty(encoding: String = Charset.defaultCharset().name()): String = this?.readText(encoding) ?: "" +public fun File?.readTextOrEmpty() : String = this?.readText() ?: "" \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompilerManager.java b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompilerManager.java index a64f4f701e1..0013db1b95c 100644 --- a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompilerManager.java +++ b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompilerManager.java @@ -18,18 +18,24 @@ package org.jetbrains.jet.plugin.compiler; import com.intellij.diagnostic.PluginException; import com.intellij.ide.plugins.PluginManager; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.*; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtilRt; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.plugin.JetFileType; import java.io.PrintStream; import java.io.PrintWriter; import java.util.Collections; +import java.util.Set; import static org.jetbrains.jet.compiler.runner.CompilerRunnerConstants.INTERNAL_ERROR_PREFIX; import static org.jetbrains.jet.compiler.runner.CompilerRunnerConstants.KOTLIN_COMPILER_NAME; @@ -39,6 +45,7 @@ public class JetCompilerManager implements ProjectComponent { // Comes from external make private static final String PREFIX_WITH_COMPILER_NAME = KOTLIN_COMPILER_NAME + ": " + INTERNAL_ERROR_PREFIX; + private static final Set FILE_EXTS_WHICH_NEEDS_REFRESH = ContainerUtil.immutableSet(".js", ".map"); public JetCompilerManager(Project project, CompilerManager manager) { manager.addTranslatingCompiler(new JetCompiler(), @@ -64,6 +71,16 @@ public class JetCompilerManager implements ProjectComponent { @Override public void fileGenerated(String outputRoot, String relativePath) { + if (ApplicationManager.getApplication().isUnitTestMode()) return; + + String ext = FileUtilRt.getExtension(relativePath).toLowerCase(); + + if (FILE_EXTS_WHICH_NEEDS_REFRESH.contains(ext)) { + String outFile = outputRoot + "/" + relativePath; + VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(outFile); + assert virtualFile != null : "Virtual file not found for generated file path: " + outFile; + virtualFile.refresh(/*async =*/ false, /*recursive =*/ false); + } } }, project); } diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java b/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java index b6f75729759..a26c2960171 100644 --- a/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java +++ b/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java @@ -16,14 +16,12 @@ package org.jetbrains.jet.plugin.compiler; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.*; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleOrderEntry; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.OrderEntry; -import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Chunk; import com.intellij.util.Function; @@ -108,12 +106,6 @@ public final class K2JSCompiler implements TranslatingCompiler { KotlinCompilerRunner.runK2JsCompiler(commonArguments, k2jsArguments, compilerSettings, messageCollector, environment, outputItemsCollector, srcFiles, libraryFiles, outFile); - if (!ApplicationManager.getApplication().isUnitTestMode()) { - VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(outDir); - assert virtualFile != null : "Virtual file not found for module output: " + outDir; - virtualFile.refresh(false, true); - } - TranslatingCompilerUtils.reportOutputs(sink, environment.getOutput(), outputItemsCollector); } diff --git a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java index cdea129cb77..49159f3cbff 100644 --- a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java +++ b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java @@ -51,7 +51,9 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.*; +import static org.jetbrains.jet.cli.common.messages.CompilerMessageLocation.NO_LOCATION; import static org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity.*; +import static org.jetbrains.jet.compiler.runner.CompilerRunnerConstants.INTERNAL_ERROR_PREFIX; import static org.jetbrains.jet.compiler.runner.KotlinCompilerRunner.runK2JsCompiler; import static org.jetbrains.jet.compiler.runner.KotlinCompilerRunner.runK2JvmCompiler; @@ -87,11 +89,11 @@ public class KotlinBuilder extends ModuleLevelBuilder { MessageCollector messageCollector = new MessageCollectorAdapter(context); // Workaround for Android Studio if (!isJavaPluginEnabled(context)) { - messageCollector.report(INFO, "Kotlin JPS plugin is disabled", CompilerMessageLocation.NO_LOCATION); + messageCollector.report(INFO, "Kotlin JPS plugin is disabled", NO_LOCATION); return ExitCode.NOTHING_DONE; } - messageCollector.report(INFO, "Kotlin JPS plugin version " + KotlinVersion.VERSION, CompilerMessageLocation.NO_LOCATION); + messageCollector.report(INFO, "Kotlin JPS plugin version " + KotlinVersion.VERSION, NO_LOCATION); ModuleBuildTarget representativeTarget = chunk.representativeTarget(); @@ -128,7 +130,7 @@ public class KotlinBuilder extends ModuleLevelBuilder { WARNING, "Circular dependencies are not supported. " + "The following JS modules depend on each other: " + StringUtil.join(chunk.getModules(), MODULE_NAME, ", ") + ". " + "Kotlin is not compiled for these modules", - CompilerMessageLocation.NO_LOCATION); + NO_LOCATION); return ExitCode.NOTHING_DONE; } @@ -152,7 +154,7 @@ public class KotlinBuilder extends ModuleLevelBuilder { WARNING, "Circular dependencies are only partially supported. " + "The following modules depend on each other: " + StringUtil.join(chunk.getModules(), MODULE_NAME, ", ") + ". " + "Kotlin will compile them, but some strange effect may happen", - CompilerMessageLocation.NO_LOCATION); + NO_LOCATION); } File moduleFile = KotlinBuilderModuleScriptGenerator.generateModuleDescription(context, chunk); @@ -178,7 +180,17 @@ public class KotlinBuilder extends ModuleLevelBuilder { } for (SimpleOutputItem outputItem : outputItemCollector.getOutputs()) { - BuildTarget target = sourceToTarget.get(outputItem.getSourceFiles().iterator().next()); + BuildTarget target = null; + Collection sourceFiles = outputItem.getSourceFiles(); + if (sourceFiles != null && !sourceFiles.isEmpty()) { + target = sourceToTarget.get(sourceFiles.iterator().next()); + } + else { + messageCollector.report(ERROR, + INTERNAL_ERROR_PREFIX + "outputItem.sourceFiles is null or empty, outputItem = " + outputItem, + NO_LOCATION); + } + outputConsumer.registerOutputFile( target != null ? target : representativeTarget, outputItem.getOutputFile(), @@ -235,7 +247,7 @@ public class KotlinBuilder extends ModuleLevelBuilder { ) { String prefix = ""; if (severity == EXCEPTION) { - prefix = CompilerRunnerConstants.INTERNAL_ERROR_PREFIX; + prefix = INTERNAL_ERROR_PREFIX; } context.processMessage(new CompilerMessage( CompilerRunnerConstants.KOTLIN_COMPILER_NAME, diff --git a/js/js.tests/js.tests.iml b/js/js.tests/js.tests.iml index 1e4130900f8..2125473ee41 100644 --- a/js/js.tests/js.tests.iml +++ b/js/js.tests/js.tests.iml @@ -16,6 +16,7 @@ + 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 b94bc6d764f..105d617d703 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java @@ -137,7 +137,7 @@ public abstract class BasicTest extends KotlinTestWithEnvironment { @NotNull EcmaVersion version, @NotNull TestConfigFactory configFactory ) throws Exception { - TranslationUtils.translateFiles(project, files, outputFile, mainCallParameters, version, configFactory); + TranslationUtils.translateFiles(project, mainCallParameters, files, outputFile, version, configFactory); } @NotNull diff --git a/js/js.tests/test/org/jetbrains/k2js/test/OutputPrefixPostfixTest.java b/js/js.tests/test/org/jetbrains/k2js/test/OutputPrefixPostfixTest.java index a60d7ef68f1..c551d0314d7 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/OutputPrefixPostfixTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/OutputPrefixPostfixTest.java @@ -26,6 +26,7 @@ import org.jetbrains.k2js.facade.K2JSTranslator; import org.jetbrains.k2js.facade.MainCallParameters; import org.jetbrains.k2js.test.config.TestConfigFactory; import org.jetbrains.k2js.test.semantics.TranslatorTestCaseBuilder; +import org.jetbrains.k2js.test.utils.TranslationUtils; import java.io.File; import java.util.List; @@ -62,9 +63,9 @@ public final class OutputPrefixPostfixTest extends SingleFileTranslationTest { @NotNull EcmaVersion version, @NotNull TestConfigFactory configFactory ) throws Exception { - K2JSTranslator.translateWithMainCallParametersAndSaveToFile(mainCallParameters, createJetFileList(project, files, null), - outputFile, outputPrefixFile, outputPostfixFile, - getConfig(project, version, configFactory)); + TranslationUtils.translateFiles(mainCallParameters, createJetFileList(project, files, null), + outputFile, outputPrefixFile, outputPostfixFile, + getConfig(project, version, configFactory)); } @Override diff --git a/js/js.tests/test/org/jetbrains/k2js/test/SourcemapTest.java b/js/js.tests/test/org/jetbrains/k2js/test/SourcemapTest.java index e18f4e12f72..79b53aaecaf 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/SourcemapTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/SourcemapTest.java @@ -20,11 +20,11 @@ import com.intellij.openapi.project.Project; import junit.framework.Test; import org.jetbrains.annotations.NotNull; import org.jetbrains.k2js.config.EcmaVersion; -import org.jetbrains.k2js.facade.K2JSTranslator; import org.jetbrains.k2js.facade.MainCallParameters; import org.jetbrains.k2js.test.config.TestConfig; import org.jetbrains.k2js.test.config.TestConfigFactory; import org.jetbrains.k2js.test.semantics.TranslatorTestCaseBuilder; +import org.jetbrains.k2js.test.utils.TranslationUtils; import java.util.List; @@ -52,9 +52,9 @@ public final class SourcemapTest extends SingleFileTranslationTest { @NotNull EcmaVersion version, @NotNull TestConfigFactory configFactory ) throws Exception { - K2JSTranslator.translateWithMainCallParametersAndSaveToFile(mainCallParameters, createJetFileList(project, files, null), - outputFile, null, null, - getConfig(project, version, configFactory)); + TranslationUtils.translateFiles(mainCallParameters, createJetFileList(project, files, null), + outputFile, null, null, + getConfig(project, version, configFactory)); } @NotNull diff --git a/js/js.tests/test/org/jetbrains/k2js/test/utils/TranslationUtils.java b/js/js.tests/test/org/jetbrains/k2js/test/utils/TranslationUtils.java index 97ec4915864..5737f786b21 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/utils/TranslationUtils.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/utils/TranslationUtils.java @@ -23,14 +23,16 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.OutputFileCollection; import org.jetbrains.jet.analyzer.AnalyzeExhaust; +import org.jetbrains.jet.cli.common.output.outputUtils.OutputUtilsPackage; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.k2js.analyze.AnalyzerFacadeForJS; import org.jetbrains.k2js.config.Config; import org.jetbrains.k2js.config.EcmaVersion; -import org.jetbrains.k2js.facade.K2JSTranslator; import org.jetbrains.k2js.facade.MainCallParameters; +import org.jetbrains.k2js.facade.exceptions.TranslationException; import org.jetbrains.k2js.test.config.TestConfigFactory; import org.jetbrains.k2js.utils.JetFileUtils; @@ -39,6 +41,8 @@ import java.io.IOException; import java.lang.ref.SoftReference; import java.util.List; +import static org.jetbrains.k2js.facade.K2JSTranslator.translateWithMainCallParameters; + //TODO: use method object public final class TranslationUtils { @@ -95,13 +99,30 @@ public final class TranslationUtils { return configFactory.create(project, version, getLibFilesWithCode(getAllLibFiles(project)), preanalyzedContext); } - public static void translateFiles(@NotNull Project project, @NotNull List inputFiles, - @NotNull String outputFile, + public static void translateFiles( + @NotNull Project project, @NotNull MainCallParameters mainCallParameters, - @NotNull EcmaVersion version, TestConfigFactory configFactory) throws Exception { + @NotNull List inputFiles, + @NotNull String outputFile, + @NotNull EcmaVersion version, + @NotNull TestConfigFactory configFactory + ) throws Exception { List jetFiles = createJetFileList(project, inputFiles, null); - K2JSTranslator translator = new K2JSTranslator(getConfig(project, version, configFactory)); - FileUtil.writeToFile(new File(outputFile), translator.generateProgramCode(jetFiles, mainCallParameters)); + Config config = getConfig(project, version, configFactory); + translateFiles(mainCallParameters, jetFiles, outputFile, null, null, config); + } + + public static void translateFiles( + @NotNull MainCallParameters mainCall, + @NotNull List files, + @NotNull String outputPath, + @Nullable File outputPrefixFile, + @Nullable File outputPostfixFile, + @NotNull Config config + ) throws TranslationException, IOException { + File outputFile = new File(outputPath); + OutputFileCollection outputFiles = translateWithMainCallParameters(mainCall, files, outputFile, outputPrefixFile, outputPostfixFile, config); + OutputUtilsPackage.writeAllTo(outputFiles, outputFile.getParentFile()); } @NotNull diff --git a/js/js.translator/js.translator.iml b/js/js.translator/js.translator.iml index 3ec26a8e82c..5929843bfe9 100644 --- a/js/js.translator/js.translator.iml +++ b/js/js.translator/js.translator.iml @@ -11,6 +11,7 @@ + diff --git a/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java b/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java index d0c7de6c3c9..6fc24c4e43a 100644 --- a/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java @@ -19,12 +19,20 @@ package org.jetbrains.k2js.facade; import com.google.dart.compiler.backend.js.ast.JsProgram; import com.google.dart.compiler.util.TextOutputImpl; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Function; +import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.OutputFileCollection; +import org.jetbrains.jet.SimpleOutputFile; +import org.jetbrains.jet.SimpleOutputFileCollection; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.utils.fileUtils.FileUtilsPackage; import org.jetbrains.js.compiler.JsSourceGenerationVisitor; import org.jetbrains.js.compiler.sourcemap.SourceMap3Builder; import org.jetbrains.js.compiler.sourcemap.SourceMapBuilder; @@ -49,44 +57,49 @@ public final class K2JSTranslator { public static final String FLUSH_SYSTEM_OUT = "Kotlin.System.flush();\n"; public static final String GET_SYSTEM_OUT = "Kotlin.System.output();\n"; - public static void translateWithMainCallParametersAndSaveToFile( + public static OutputFileCollection translateWithMainCallParameters( @NotNull MainCallParameters mainCall, @NotNull List files, - @NotNull String outputPath, + @NotNull File outputFile, @Nullable File outputPrefixFile, @Nullable File outputPostfixFile, @NotNull Config config ) throws TranslationException, IOException { K2JSTranslator translator = new K2JSTranslator(config); - File outFile = new File(outputPath); TextOutputImpl output = new TextOutputImpl(); - SourceMapBuilder sourceMapBuilder = config.isSourcemap() ? new SourceMap3Builder(outFile, output, new SourceMapBuilderConsumer()) : null; + SourceMapBuilder sourceMapBuilder = config.isSourcemap() ? new SourceMap3Builder(outputFile, output, new SourceMapBuilderConsumer()) : null; String programCode = translator.generateProgramCode(files, mainCall, output, sourceMapBuilder); - if (outputPrefixFile != null) { - String prefix = FileUtil.loadFile(outputPrefixFile); - FileUtil.writeToFile(outFile, prefix); - if (sourceMapBuilder != null) { - sourceMapBuilder.skipLinesInBegin(StringUtil.getLineBreakCount(prefix)); + String prefix = FileUtilsPackage.readTextOrEmpty(outputPrefixFile); + String postfix = FileUtilsPackage.readTextOrEmpty(outputPostfixFile); + + StringBuilder outBuilder = new StringBuilder(programCode.length() + prefix.length() + postfix.length()); + outBuilder.append(prefix).append(programCode).append(postfix); + + List sourceFiles = ContainerUtil.map(files, new Function() { + @Override + public File fun(JetFile file) { + VirtualFile virtualFile = file.getOriginalFile().getVirtualFile(); + if (virtualFile == null) return new File(file.getName()); + return VfsUtilCore.virtualToIoFile(virtualFile); } - } + }); - FileUtil.writeToFile(outFile, programCode.getBytes(), outputPrefixFile != null); - - if (outputPostfixFile != null) { - byte[] postfix = FileUtil.loadFileBytes(outputPostfixFile); - FileUtil.writeToFile(outFile, postfix, true); - } + SimpleOutputFile jsFile = new SimpleOutputFile(sourceFiles, outputFile.getName(), outBuilder.toString()); + List outputFiles = new SmartList(jsFile); if (sourceMapBuilder != null) { - FileUtil.writeToFile(sourceMapBuilder.getOutFile(), sourceMapBuilder.build()); + sourceMapBuilder.skipLinesInBegin(StringUtil.getLineBreakCount(prefix)); + SimpleOutputFile sourcemapFile = new SimpleOutputFile(sourceFiles, sourceMapBuilder.getOutFile().getName(), sourceMapBuilder.build()); + outputFiles.add(sourcemapFile); } + + return new SimpleOutputFileCollection(outputFiles); } @NotNull private final Config config; - public K2JSTranslator(@NotNull Config config) { this.config = config; }