Code that runs the compiler is migrated onto MessageCollector

CompilerEnvironment migrated to use io.Files instead of VirtualFiles

This prepares the move of this code to the separate module, to be re-used by external build
This commit is contained in:
Andrey Breslav
2012-11-08 20:47:18 +04:00
parent 2584ba5246
commit 4926dd7189
6 changed files with 210 additions and 100 deletions
+1
View File
@@ -30,6 +30,7 @@
<orderEntry type="module" module-name="js.translator" /> <orderEntry type="module" module-name="js.translator" />
<orderEntry type="module" module-name="cli" scope="TEST" /> <orderEntry type="module" module-name="cli" scope="TEST" />
<orderEntry type="module" module-name="ide-compiler-runner" /> <orderEntry type="module" module-name="ide-compiler-runner" />
<orderEntry type="module" module-name="cli-common" />
</component> </component>
</module> </module>
@@ -16,17 +16,15 @@
package org.jetbrains.jet.plugin.compiler; package org.jetbrains.jet.plugin.compiler;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.vfs.VirtualFile;
import jet.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.cli.common.messages.MessageCollector;
import org.jetbrains.jet.utils.PathUtil; import org.jetbrains.jet.utils.PathUtil;
import java.io.*; import java.io.File;
import static com.intellij.openapi.compiler.CompilerMessageCategory.ERROR; import static org.jetbrains.jet.cli.common.messages.CompilerMessageLocation.NO_LOCATION;
import static org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity.ERROR;
/** /**
* @author Pavel Talanov * @author Pavel Talanov
@@ -34,9 +32,8 @@ import static com.intellij.openapi.compiler.CompilerMessageCategory.ERROR;
public final class CompilerEnvironment { public final class CompilerEnvironment {
@NotNull @NotNull
public static CompilerEnvironment getEnvironmentFor(@NotNull CompileContext compileContext, @NotNull Module module, boolean tests) { public static CompilerEnvironment getEnvironmentFor(boolean tests, File mainOutput, File outputDirectoryForTests) {
VirtualFile mainOutput = compileContext.getModuleOutputDirectory(module); final File outputDir = tests ? outputDirectoryForTests : mainOutput;
final VirtualFile outputDir = tests ? compileContext.getModuleOutputDirectoryForTests(module) : mainOutput;
File kotlinHome = PathUtil.getDefaultCompilerPath(); File kotlinHome = PathUtil.getDefaultCompilerPath();
return new CompilerEnvironment(kotlinHome, outputDir); return new CompilerEnvironment(kotlinHome, outputDir);
} }
@@ -44,9 +41,9 @@ public final class CompilerEnvironment {
@Nullable @Nullable
private final File kotlinHome; private final File kotlinHome;
@Nullable @Nullable
private final VirtualFile output; private final File output;
public CompilerEnvironment(@Nullable File home, @Nullable VirtualFile output) { public CompilerEnvironment(@Nullable File home, @Nullable File output) {
this.kotlinHome = home; this.kotlinHome = home;
this.output = output; this.output = output;
} }
@@ -62,17 +59,17 @@ public final class CompilerEnvironment {
} }
@NotNull @NotNull
public VirtualFile getOutput() { public File getOutput() {
assert output != null; assert output != null;
return output; return output;
} }
public void reportErrorsTo(@NotNull CompileContext compileContext) { public void reportErrorsTo(@NotNull MessageCollector messageCollector) {
if (output == null) { if (output == null) {
compileContext.addMessage(ERROR, "[Internal Error] No output directory", "", -1, -1); messageCollector.report(ERROR, "[Internal Error] No output directory", NO_LOCATION);
} }
if (kotlinHome == null) { if (kotlinHome == null) {
compileContext.addMessage(ERROR, "Cannot find kotlinc home. Make sure plugin is properly installed", "", -1, -1); messageCollector.report(ERROR, "Cannot find kotlinc home. Make sure plugin is properly installed", NO_LOCATION);
} }
} }
@@ -19,15 +19,18 @@ package org.jetbrains.jet.plugin.compiler;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.intellij.compiler.impl.javaCompiler.OutputItemImpl; import com.intellij.compiler.impl.javaCompiler.OutputItemImpl;
import com.intellij.openapi.compiler.CompileContext; import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.compiler.TranslatingCompiler; import com.intellij.openapi.compiler.TranslatingCompiler;
import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import jet.Function1; import jet.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
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.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@@ -44,7 +47,8 @@ import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.*; import java.util.*;
import static com.intellij.openapi.compiler.CompilerMessageCategory.*; import static org.jetbrains.jet.cli.common.messages.CompilerMessageLocation.NO_LOCATION;
import static org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity.*;
/** /**
* @author Pavel Talanov * @author Pavel Talanov
@@ -56,12 +60,11 @@ public final class CompilerUtils {
private CompilerUtils() { private CompilerUtils() {
} }
public static List<File> kompilerClasspath(File kotlinHome, CompileContext context) { public static List<File> kompilerClasspath(File kotlinHome, MessageCollector messageCollector) {
File libs = new File(kotlinHome, "lib"); File libs = new File(kotlinHome, "lib");
if (!libs.exists() || libs.isFile()) { if (!libs.exists() || libs.isFile()) {
context.addMessage(ERROR, "Broken compiler at '" + libs.getAbsolutePath() + "'. Make sure plugin is properly installed", "", -1, messageCollector.report(ERROR, "Broken compiler at '" + libs.getAbsolutePath() + "'. Make sure plugin is properly installed", NO_LOCATION);
-1);
return Collections.emptyList(); return Collections.emptyList();
} }
@@ -70,17 +73,17 @@ public final class CompilerUtils {
return answer; return answer;
} }
public static URLClassLoader getOrCreateClassLoader(File kotlinHome, CompileContext context) { public static URLClassLoader getOrCreateClassLoader(File kotlinHome, MessageCollector messageCollector) {
URLClassLoader answer = ourClassLoaderRef.get(); URLClassLoader answer = ourClassLoaderRef.get();
if (answer == null) { if (answer == null) {
answer = createClassloader(kotlinHome, context); answer = createClassloader(kotlinHome, messageCollector);
ourClassLoaderRef = new SoftReference<URLClassLoader>(answer); ourClassLoaderRef = new SoftReference<URLClassLoader>(answer);
} }
return answer; return answer;
} }
private static URLClassLoader createClassloader(File kotlinHome, CompileContext context) { private static URLClassLoader createClassloader(File kotlinHome, MessageCollector messageCollector) {
List<File> jars = kompilerClasspath(kotlinHome, context); List<File> jars = kompilerClasspath(kotlinHome, messageCollector);
URL[] urls = new URL[jars.size()]; URL[] urls = new URL[jars.size()];
for (int i = 0; i < urls.length; i++) { for (int i = 0; i < urls.length; i++) {
try { try {
@@ -93,13 +96,13 @@ public final class CompilerUtils {
return new URLClassLoader(urls, null); return new URLClassLoader(urls, null);
} }
static void handleProcessTermination(int exitCode, CompileContext compileContext) { static void handleProcessTermination(int exitCode, MessageCollector messageCollector) {
if (exitCode != 0 && exitCode != 1) { if (exitCode != 0 && exitCode != 1) {
compileContext.addMessage(ERROR, "Compiler terminated with exit code: " + exitCode, "", -1, -1); messageCollector.report(ERROR, "Compiler terminated with exit code: " + exitCode, NO_LOCATION);
} }
} }
public static void parseCompilerMessagesFromReader(CompileContext compileContext, final Reader reader, OutputItemsCollector collector) { public static void parseCompilerMessagesFromReader(MessageCollector messageCollector, final Reader reader, OutputItemsCollector collector) {
// Sometimes the compiler can't output valid XML // Sometimes the compiler can't output valid XML
// Example: error in command line arguments passed to the compiler // Example: error in command line arguments passed to the compiler
// having no -tags key (arguments are not parsed), the compiler doesn't know // having no -tags key (arguments are not parsed), the compiler doesn't know
@@ -130,7 +133,7 @@ public final class CompilerUtils {
try { try {
SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser(); SAXParser parser = factory.newSAXParser();
parser.parse(new InputSource(wrappingReader), new CompilerOutputSAXHandler(compileContext, collector)); parser.parse(new InputSource(wrappingReader), new CompilerOutputSAXHandler(messageCollector, collector));
} }
catch (Throwable e) { catch (Throwable e) {
@@ -145,7 +148,7 @@ public final class CompilerUtils {
String message = stringBuilder.toString(); String message = stringBuilder.toString();
LOG.error(message); LOG.error(message);
LOG.error(e); LOG.error(e);
compileContext.addMessage(ERROR, message, null, -1, -1); messageCollector.report(ERROR, message, NO_LOCATION);
} }
finally { finally {
try { try {
@@ -168,24 +171,37 @@ public final class CompilerUtils {
public static Object invokeExecMethod(CompilerEnvironment environment, public static Object invokeExecMethod(CompilerEnvironment environment,
PrintStream out, PrintStream out,
CompileContext context, String[] arguments, String name) throws Exception { MessageCollector messageCollector, String[] arguments, String name) throws Exception {
URLClassLoader loader = getOrCreateClassLoader(environment.getKotlinHome(), context); URLClassLoader loader = getOrCreateClassLoader(environment.getKotlinHome(), messageCollector);
Class<?> kompiler = Class.forName(name, true, loader); Class<?> kompiler = Class.forName(name, true, loader);
Method exec = kompiler.getMethod("exec", PrintStream.class, String[].class); Method exec = kompiler.getMethod("exec", PrintStream.class, String[].class);
return exec.invoke(kompiler.newInstance(), out, arguments); return exec.invoke(kompiler.newInstance(), out, arguments);
} }
@NotNull
public static CompilerEnvironment getEnvironmentFor(@NotNull CompileContext compileContext, @NotNull Module module, boolean tests) {
VirtualFile mainOutput = compileContext.getModuleOutputDirectory(module);
VirtualFile outputDirectoryForTests = compileContext.getModuleOutputDirectoryForTests(module);
return CompilerEnvironment.getEnvironmentFor(tests, toIoFile(mainOutput), toIoFile(outputDirectoryForTests));
}
@Nullable
public static File toIoFile(@Nullable VirtualFile file) {
if (file == null) return null;
return new File(file.getPath());
}
private static class CompilerOutputSAXHandler extends DefaultHandler { private static class CompilerOutputSAXHandler extends DefaultHandler {
private static final Map<String, CompilerMessageCategory> CATEGORIES = ImmutableMap.<String, CompilerMessageCategory>builder() private static final Map<String, CompilerMessageSeverity> CATEGORIES = ImmutableMap.<String, CompilerMessageSeverity>builder()
.put("error", CompilerMessageCategory.ERROR) .put("error", ERROR)
.put("warning", CompilerMessageCategory.WARNING) .put("warning", WARNING)
.put("logging", CompilerMessageCategory.STATISTICS) .put("logging", LOGGING)
.put("exception", CompilerMessageCategory.ERROR) .put("exception", ERROR)
.put("info", CompilerMessageCategory.INFORMATION) .put("info", INFO)
.put("messages", CompilerMessageCategory.INFORMATION) // Root XML element .put("messages", INFO) // Root XML element
.build(); .build();
private final CompileContext compileContext; private final MessageCollector messageCollector;
private final OutputItemsCollector collector; private final OutputItemsCollector collector;
private final StringBuilder message = new StringBuilder(); private final StringBuilder message = new StringBuilder();
@@ -194,8 +210,8 @@ public final class CompilerUtils {
private int line; private int line;
private int column; private int column;
public CompilerOutputSAXHandler(CompileContext compileContext, OutputItemsCollector collector) { public CompilerOutputSAXHandler(MessageCollector messageCollector, OutputItemsCollector collector) {
this.compileContext = compileContext; this.messageCollector = messageCollector;
this.collector = collector; this.collector = collector;
} }
@@ -217,7 +233,7 @@ public final class CompilerUtils {
// We're directly inside the root tag: <MESSAGES> // We're directly inside the root tag: <MESSAGES>
String message = new String(ch, start, length); String message = new String(ch, start, length);
if (!message.trim().isEmpty()) { if (!message.trim().isEmpty()) {
compileContext.addMessage(ERROR, "Unhandled compiler output: " + message, null, -1, -1); messageCollector.report(ERROR, "Unhandled compiler output: " + message, NO_LOCATION);
} }
} }
else { else {
@@ -232,10 +248,10 @@ public final class CompilerUtils {
return; return;
} }
String qNameLowerCase = qName.toLowerCase(); String qNameLowerCase = qName.toLowerCase();
CompilerMessageCategory category = CATEGORIES.get(qNameLowerCase); CompilerMessageSeverity category = CATEGORIES.get(qNameLowerCase);
if (category == null) { if (category == null) {
compileContext.addMessage(ERROR, "Unknown compiler message tag: " + qName, null, -1, -1); messageCollector.report(ERROR, "Unknown compiler message tag: " + qName, NO_LOCATION);
category = INFORMATION; category = INFO;
} }
String text = message.toString(); String text = message.toString();
@@ -243,12 +259,11 @@ public final class CompilerUtils {
LOG.error(text); LOG.error(text);
} }
if (category == STATISTICS) { if (category == LOGGING) {
compileContext.getProgressIndicator().setText(text);
collector.learn(text); collector.learn(text);
} }
else { else {
compileContext.addMessage(category, text, path, line, column); messageCollector.report(category, text, CompilerMessageLocation.create(path, line, column));
} }
tags.pop(); tags.pop();
} }
@@ -305,8 +320,8 @@ public final class CompilerUtils {
} }
} }
public static void outputCompilerMessagesAndHandleExitCode(@NotNull CompileContext context, public static void outputCompilerMessagesAndHandleExitCode(@NotNull MessageCollector messageCollector,
@NotNull OutputItemsCollector collector, @NotNull OutputItemsCollector outputItemsCollector,
@NotNull Function1<PrintStream, Integer> compilerRun) { @NotNull Function1<PrintStream, Integer> compilerRun) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PrintStream out = new PrintStream(outputStream); PrintStream out = new PrintStream(outputStream);
@@ -314,8 +329,8 @@ public final class CompilerUtils {
int exitCode = compilerRun.invoke(out); int exitCode = compilerRun.invoke(out);
BufferedReader reader = new BufferedReader(new StringReader(outputStream.toString())); BufferedReader reader = new BufferedReader(new StringReader(outputStream.toString()));
parseCompilerMessagesFromReader(context, reader, collector); parseCompilerMessagesFromReader(messageCollector, reader, outputItemsCollector);
handleProcessTermination(exitCode, context); handleProcessTermination(exitCode, messageCollector);
} }
} }
@@ -40,6 +40,9 @@ import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil;
import jet.Function1; import jet.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
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.compiler.runner.KotlinModuleScriptGenerator; import org.jetbrains.jet.compiler.runner.KotlinModuleScriptGenerator;
import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.plugin.project.JsModuleDetector; import org.jetbrains.jet.plugin.project.JsModuleDetector;
@@ -50,9 +53,6 @@ import java.io.InputStreamReader;
import java.io.PrintStream; import java.io.PrintStream;
import java.util.*; import java.util.*;
import static com.intellij.openapi.compiler.CompilerMessageCategory.ERROR;
import static com.intellij.openapi.compiler.CompilerMessageCategory.INFORMATION;
/** /**
* @author yole * @author yole
*/ */
@@ -108,7 +108,8 @@ public class JetCompiler implements TranslatingCompiler {
doCompile(compileContext, moduleChunk, testFiles, module, outputSink, true); doCompile(compileContext, moduleChunk, testFiles, module, outputSink, true);
} }
private void doCompile(CompileContext compileContext, private void doCompile(
final CompileContext compileContext,
Chunk<Module> moduleChunk, Chunk<Module> moduleChunk,
List<VirtualFile> files, List<VirtualFile> files,
Module module, Module module,
@@ -116,9 +117,11 @@ public class JetCompiler implements TranslatingCompiler {
boolean tests) { boolean tests) {
if (files.isEmpty()) return; if (files.isEmpty()) return;
CompilerEnvironment environment = CompilerEnvironment.getEnvironmentFor(compileContext, module, tests); MessageCollector messageCollector = new MessageCollectorAdapter(compileContext);
CompilerEnvironment environment = CompilerUtils.getEnvironmentFor(compileContext, module, tests);
if (!environment.success()) { if (!environment.success()) {
environment.reportErrorsTo(compileContext); environment.reportErrorsTo(messageCollector);
return; return;
} }
@@ -129,19 +132,31 @@ public class JetCompiler implements TranslatingCompiler {
if (scriptFile == null) return; if (scriptFile == null) return;
CompilerUtils.OutputItemsCollectorImpl collector = new CompilerUtils.OutputItemsCollectorImpl(environment.getOutput().getPath()); CompilerUtils.OutputItemsCollectorImpl collector = new CompilerUtils.OutputItemsCollectorImpl(environment.getOutput().getPath());
runCompiler(compileContext, environment, scriptFile, collector); runCompiler(messageCollector, environment, scriptFile, collector);
outputSink.add(environment.getOutput().getPath(), collector.getOutputs(), collector.getSources().toArray(VirtualFile.EMPTY_ARRAY)); outputSink.add(environment.getOutput().getPath(), collector.getOutputs(), collector.getSources().toArray(VirtualFile.EMPTY_ARRAY));
} }
private void runCompiler(CompileContext compileContext, private static void runCompiler(
MessageCollector messageCollector,
CompilerEnvironment environment, CompilerEnvironment environment,
File scriptFile, File scriptFile,
CompilerUtils.OutputItemsCollectorImpl collector) { CompilerUtils.OutputItemsCollectorImpl collector
if (RUN_OUT_OF_PROCESS) { ) {
runOutOfProcess(compileContext, collector, environment, scriptFile); runCompiler(messageCollector, environment, scriptFile, collector, RUN_OUT_OF_PROCESS);
}
private static void runCompiler(
MessageCollector messageCollector,
CompilerEnvironment environment,
File scriptFile,
CompilerUtils.OutputItemsCollectorImpl collector,
boolean runOutOfProcess
) {
if (runOutOfProcess) {
runOutOfProcess(messageCollector, collector, environment, scriptFile);
} }
else { else {
runInProcess(compileContext, collector, environment, scriptFile); runInProcess(messageCollector, collector, environment, scriptFile);
} }
} }
@@ -150,7 +165,7 @@ public class JetCompiler implements TranslatingCompiler {
Chunk<Module> moduleChunk, Chunk<Module> moduleChunk,
List<VirtualFile> files, List<VirtualFile> files,
Module module, Module module,
boolean tests, VirtualFile mainOutput, VirtualFile outputDir boolean tests, VirtualFile mainOutput, File outputDir
) { ) {
ArrayList<String> sourceFilePaths = ContainerUtil.newArrayList(paths(files)); ArrayList<String> sourceFilePaths = ContainerUtil.newArrayList(paths(files));
ModuleChunk chunk = new ModuleChunk((CompileContextEx)compileContext, moduleChunk, Collections.<Module, List<VirtualFile>>emptyMap()); ModuleChunk chunk = new ModuleChunk((CompileContextEx)compileContext, moduleChunk, Collections.<Module, List<VirtualFile>>emptyMap());
@@ -171,7 +186,7 @@ public class JetCompiler implements TranslatingCompiler {
outputDirectoriesToFilter outputDirectoriesToFilter
); );
File scriptFile = new File(path(outputDir), "script.kts"); File scriptFile = new File(outputDir, "script.kts");
try { try {
FileUtil.writeToFile(scriptFile, script.toString()); FileUtil.writeToFile(scriptFile, script.toString());
} }
@@ -208,27 +223,29 @@ public class JetCompiler implements TranslatingCompiler {
}; };
} }
private static void runInProcess(final CompileContext compileContext, private static void runInProcess(final MessageCollector messageCollector,
OutputItemsCollector collector, OutputItemsCollector collector,
final CompilerEnvironment environment, final CompilerEnvironment environment,
final File scriptFile) { final File scriptFile) {
CompilerUtils.outputCompilerMessagesAndHandleExitCode(compileContext, collector, new Function1<PrintStream, Integer>() { CompilerUtils.outputCompilerMessagesAndHandleExitCode(messageCollector, collector, new Function1<PrintStream, Integer>() {
@Override @Override
public Integer invoke(PrintStream stream) { public Integer invoke(PrintStream stream) {
return execInProcess(environment, scriptFile, stream, compileContext); return execInProcess(environment, scriptFile, stream, messageCollector);
} }
}); });
} }
private static int execInProcess(CompilerEnvironment environment, File scriptFile, PrintStream out, CompileContext context) { private static int execInProcess(CompilerEnvironment environment, File scriptFile, PrintStream out, MessageCollector messageCollector) {
try { try {
String compilerClassName = "org.jetbrains.jet.cli.jvm.K2JVMCompiler"; String compilerClassName = "org.jetbrains.jet.cli.jvm.K2JVMCompiler";
String[] arguments = commandLineArguments(environment.getOutput(), scriptFile); String[] arguments = commandLineArguments(environment.getOutput(), scriptFile);
context.addMessage(INFORMATION, "Using kotlinHome=" + environment.getKotlinHome(), "", -1, -1); messageCollector.report(CompilerMessageSeverity.INFO,
context.addMessage(INFORMATION, "Using kotlinHome=" + environment.getKotlinHome(),
"Invoking in-process compiler " + compilerClassName + " with arguments " + Arrays.asList(arguments), "", -1, CompilerMessageLocation.NO_LOCATION);
-1); messageCollector.report(CompilerMessageSeverity.INFO,
Object rc = CompilerUtils.invokeExecMethod(environment, out, context, arguments, compilerClassName); "Invoking in-process compiler " + compilerClassName + " with arguments " + Arrays.asList(arguments),
CompilerMessageLocation.NO_LOCATION);
Object rc = CompilerUtils.invokeExecMethod(environment, out, messageCollector, arguments, compilerClassName);
// exec() returns a K2JVMCompiler.ExitCode object, that class is not accessible here, // exec() returns a K2JVMCompiler.ExitCode object, that class is not accessible here,
// so we take it's contents through reflection // so we take it's contents through reflection
return CompilerUtils.getReturnCodeFromObject(rc); return CompilerUtils.getReturnCodeFromObject(rc);
@@ -239,18 +256,20 @@ public class JetCompiler implements TranslatingCompiler {
} }
} }
private static String[] commandLineArguments(VirtualFile outputDir, File scriptFile) { private static String[] commandLineArguments(File outputDir, File scriptFile) {
return new String[]{ return new String[]{
"-module", scriptFile.getAbsolutePath(), "-module", scriptFile.getAbsolutePath(),
"-output", path(outputDir), "-output", outputDir.getPath(),
"-tags", "-verbose", "-version", "-tags", "-verbose", "-version",
"-noStdlib", "-noJdkAnnotations", "-noJdk"}; "-noStdlib", "-noJdkAnnotations", "-noJdk"};
} }
private static void runOutOfProcess(final CompileContext compileContext, private static void runOutOfProcess(
final OutputItemsCollector collector, final MessageCollector messageCollector,
final OutputItemsCollector itemCollector,
CompilerEnvironment environment, CompilerEnvironment environment,
File scriptFile) { File scriptFile
) {
final SimpleJavaParameters params = new SimpleJavaParameters(); final SimpleJavaParameters params = new SimpleJavaParameters();
params.setJdk(new SimpleJavaSdkType().createJdk("tmp", SystemProperties.getJavaHome())); params.setJdk(new SimpleJavaSdkType().createJdk("tmp", SystemProperties.getJavaHome()));
params.setMainClass("org.jetbrains.jet.cli.jvm.K2JVMCompiler"); params.setMainClass("org.jetbrains.jet.cli.jvm.K2JVMCompiler");
@@ -259,7 +278,7 @@ public class JetCompiler implements TranslatingCompiler {
params.getProgramParametersList().add(arg); params.getProgramParametersList().add(arg);
} }
for (File jar : CompilerUtils.kompilerClasspath(environment.getKotlinHome(), compileContext)) { for (File jar : CompilerUtils.kompilerClasspath(environment.getKotlinHome(), messageCollector)) {
params.getClassPath().add(jar); params.getClassPath().add(jar);
} }
@@ -271,7 +290,9 @@ public class JetCompiler implements TranslatingCompiler {
final GeneralCommandLine commandLine = JdkUtil.setupJVMCommandLine( final GeneralCommandLine commandLine = JdkUtil.setupJVMCommandLine(
((JavaSdkType)sdk.getSdkType()).getVMExecutablePath(sdk), params, false); ((JavaSdkType)sdk.getSdkType()).getVMExecutablePath(sdk), params, false);
compileContext.addMessage(INFORMATION, "Invoking out-of-process compiler with arguments: " + commandLine, "", -1, -1); messageCollector.report(CompilerMessageSeverity.INFO,
"Invoking out-of-process compiler with arguments: " + commandLine,
CompilerMessageLocation.NO_LOCATION);
try { try {
final Process process = commandLine.createProcess(); final Process process = commandLine.createProcess();
@@ -280,7 +301,7 @@ public class JetCompiler implements TranslatingCompiler {
@Override @Override
public void run() { public void run() {
CompilerUtils CompilerUtils
.parseCompilerMessagesFromReader(compileContext, new InputStreamReader(process.getInputStream()), collector); .parseCompilerMessagesFromReader(messageCollector, new InputStreamReader(process.getInputStream()), itemCollector);
} }
}); });
@@ -297,10 +318,12 @@ public class JetCompiler implements TranslatingCompiler {
}); });
int exitCode = process.waitFor(); int exitCode = process.waitFor();
CompilerUtils.handleProcessTermination(exitCode, compileContext); CompilerUtils.handleProcessTermination(exitCode, messageCollector);
} }
catch (Exception e) { catch (Exception e) {
compileContext.addMessage(ERROR, "[Internal Error] " + e.getLocalizedMessage(), "", -1, -1); messageCollector.report(CompilerMessageSeverity.ERROR,
"[Internal Error] " + e.getLocalizedMessage(),
CompilerMessageLocation.NO_LOCATION);
return; return;
} }
} }
@@ -26,6 +26,7 @@ import com.intellij.openapi.roots.ModuleOrderEntry;
import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEntry; import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil; import com.intellij.util.ArrayUtil;
import com.intellij.util.Chunk; import com.intellij.util.Chunk;
@@ -34,9 +35,13 @@ import gnu.trove.THashSet;
import jet.Function1; import jet.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
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.plugin.JetFileType; import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.plugin.project.JsModuleDetector; import org.jetbrains.jet.plugin.project.JsModuleDetector;
import java.io.File;
import java.io.PrintStream; import java.io.PrintStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -72,22 +77,24 @@ public final class K2JSCompiler implements TranslatingCompiler {
return; return;
} }
CompilerEnvironment environment = CompilerEnvironment.getEnvironmentFor(context, module, /*tests = */ false); MessageCollector messageCollector = new MessageCollectorAdapter(context);
CompilerEnvironment environment = CompilerUtils.getEnvironmentFor(context, module, /*tests = */ false);
if (!environment.success()) { if (!environment.success()) {
environment.reportErrorsTo(context); environment.reportErrorsTo(messageCollector);
return; return;
} }
doCompile(context, sink, module, environment); doCompile(messageCollector, sink, module, environment);
} }
private static void doCompile(@NotNull final CompileContext context, @NotNull OutputSink sink, @NotNull final Module module, private static void doCompile(@NotNull final MessageCollector messageCollector, @NotNull OutputSink sink, @NotNull final Module module,
@NotNull final CompilerEnvironment environment) { @NotNull final CompilerEnvironment environment) {
CompilerUtils.OutputItemsCollectorImpl collector = new CompilerUtils.OutputItemsCollectorImpl(environment.getOutput().getPath()); CompilerUtils.OutputItemsCollectorImpl collector = new CompilerUtils.OutputItemsCollectorImpl(environment.getOutput().getPath());
outputCompilerMessagesAndHandleExitCode(context, collector, new Function1<PrintStream, Integer>() { outputCompilerMessagesAndHandleExitCode(messageCollector, collector, new Function1<PrintStream, Integer>() {
@Override @Override
public Integer invoke(PrintStream stream) { public Integer invoke(PrintStream stream) {
return execInProcess(context, environment, stream, module); return execInProcess(messageCollector, environment, stream, module);
} }
}); });
sink.add(environment.getOutput().getPath(), collector.getOutputs(), collector.getSources().toArray(VirtualFile.EMPTY_ARRAY)); sink.add(environment.getOutput().getPath(), collector.getOutputs(), collector.getSources().toArray(VirtualFile.EMPTY_ARRAY));
@@ -103,27 +110,31 @@ public final class K2JSCompiler implements TranslatingCompiler {
} }
@NotNull @NotNull
private static Integer execInProcess(@NotNull CompileContext context, private static Integer execInProcess(@NotNull MessageCollector messageCollector,
@NotNull CompilerEnvironment environment, @NotNull PrintStream out, @NotNull Module module) { @NotNull CompilerEnvironment environment, @NotNull PrintStream out, @NotNull Module module) {
try { try {
return doExec(context, environment, out, module); return doExec(messageCollector, environment, out, module);
} }
catch (Throwable e) { catch (Throwable e) {
context.addMessage(CompilerMessageCategory.ERROR, "Exception while executing compiler:\n" + e.getMessage(), null, -1, -1); messageCollector.report(CompilerMessageSeverity.ERROR,
"Exception while executing compiler:\n" + e.getMessage(),
CompilerMessageLocation.NO_LOCATION);
} }
return -1; return -1;
} }
@NotNull @NotNull
private static Integer doExec(@NotNull CompileContext context, @NotNull CompilerEnvironment environment, @NotNull PrintStream out, private static Integer doExec(@NotNull MessageCollector messageCollector, @NotNull CompilerEnvironment environment, @NotNull PrintStream out,
@NotNull Module module) throws Exception { @NotNull Module module) throws Exception {
VirtualFile outDir = context.getModuleOutputDirectory(module); File outDir = environment.getOutput();
String outFile = outDir == null ? null : outDir.getPath() + "/" + module.getName() + ".js"; String outFile = outDir.getPath() + "/" + module.getName() + ".js";
String[] commandLineArgs = constructArguments(module, outFile); String[] commandLineArgs = constructArguments(module, outFile);
Object rc = invokeExecMethod(environment, out, context, commandLineArgs, "org.jetbrains.jet.cli.js.K2JSCompiler"); Object rc = invokeExecMethod(environment, out, messageCollector, commandLineArgs, "org.jetbrains.jet.cli.js.K2JSCompiler");
if (outDir != null && !ApplicationManager.getApplication().isUnitTestMode()) { if (!ApplicationManager.getApplication().isUnitTestMode()) {
outDir.refresh(false, true); VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(outDir);
assert virtualFile != null : "Virtual file not found for module output: " + outDir;
virtualFile.refresh(false, true);
} }
return CompilerUtils.getReturnCodeFromObject(rc); return CompilerUtils.getReturnCodeFromObject(rc);
} }
@@ -0,0 +1,63 @@
/*
* Copyright 2010-2012 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.plugin.compiler;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import org.jetbrains.annotations.NotNull;
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 static com.intellij.openapi.compiler.CompilerMessageCategory.*;
class MessageCollectorAdapter implements MessageCollector {
private final CompileContext compileContext;
public MessageCollectorAdapter(CompileContext compileContext) {
this.compileContext = compileContext;
}
@Override
public void report(
@NotNull CompilerMessageSeverity severity,
@NotNull String message,
@NotNull CompilerMessageLocation location
) {
CompilerMessageCategory category = category(severity);
compileContext.addMessage(category, message, location.getPath(), location.getLine(), location.getColumn());
if (category == STATISTICS) {
compileContext.getProgressIndicator().setText(message);
}
}
private static CompilerMessageCategory category(CompilerMessageSeverity severity) {
switch (severity) {
case INFO:
return INFORMATION;
case ERROR:
return ERROR;
case WARNING:
return WARNING;
case EXCEPTION:
return ERROR;
case LOGGING:
return STATISTICS;
}
throw new IllegalArgumentException("Unknown severity: " + severity);
}
}