diff --git a/compiler/cli/src/org/jetbrains/jet/cli/common/CLICompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/common/CLICompiler.java index 22e682aa262..22099afa0c5 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/common/CLICompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/common/CLICompiler.java @@ -54,7 +54,7 @@ public abstract class CLICompiler { @SuppressWarnings("UnusedDeclaration") // Used via reflection in CompilerRunnerUtil#invokeExecMethod @NotNull - public ExitCode execAndOutputHtml(@NotNull PrintStream errStream, @NotNull Services services, @NotNull String... args) { + public ExitCode execAndOutputXml(@NotNull PrintStream errStream, @NotNull Services services, @NotNull String... args) { return exec(errStream, services, MessageRenderer.XML, args); } diff --git a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerRunnerUtil.java b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerRunnerUtil.java index a648bd68cc6..f8efcecbd30 100644 --- a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerRunnerUtil.java +++ b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerRunnerUtil.java @@ -26,13 +26,11 @@ import org.jetbrains.jet.utils.KotlinPaths; import java.io.*; import java.lang.ref.SoftReference; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Collections; +import java.util.Arrays; import java.util.List; import static org.jetbrains.jet.cli.common.messages.CompilerMessageLocation.NO_LOCATION; @@ -42,100 +40,103 @@ public class CompilerRunnerUtil { private static SoftReference ourClassLoaderRef = new SoftReference(null); - public static List kompilerClasspath(KotlinPaths paths, MessageCollector messageCollector) { + @Nullable + private static File getLibPath(@NotNull KotlinPaths paths, @NotNull MessageCollector messageCollector) { File libs = paths.getLibPath(); + if (libs.exists() && !libs.isFile()) return libs; - if (!libs.exists() || libs.isFile()) { - messageCollector.report(ERROR, "Broken compiler at '" + libs.getAbsolutePath() + "'. Make sure plugin is properly installed", NO_LOCATION); - return Collections.emptyList(); - } + messageCollector.report( + ERROR, + "Broken compiler at '" + libs.getAbsolutePath() + "'. Make sure plugin is properly installed", + NO_LOCATION + ); - ArrayList answer = new ArrayList(); - answer.add(new File(libs, "kotlin-compiler.jar")); - answer.add(new File(libs, "kotlin-runtime.jar")); - return answer; + return null; } @NotNull - public static ClassLoader getOrCreatePreloader( - @NotNull KotlinPaths paths, + private static List compilerClasspath(@NotNull File libs) { + return Arrays.asList( + new File(libs, "kotlin-compiler.jar"), + new File(libs, "kotlin-runtime.jar") + ); + } + + @NotNull + private static ClassLoader createPreloader( + @NotNull File libPath, @Nullable ClassLoader parentClassLoader, - @Nullable ClassCondition classToLoadByParent, - @NotNull MessageCollector messageCollector - ) { - ClassLoader answer = ourClassLoaderRef.get(); - if (answer == null) { - try { - int estimatedClassNumber = 4096; - answer = ClassPreloadingUtils.preloadClasses(kompilerClasspath(paths, messageCollector), estimatedClassNumber, parentClassLoader, classToLoadByParent); - } - catch (IOException e) { - throw new RuntimeException(e); - } - ourClassLoaderRef = new SoftReference(answer); - } - return answer; + @Nullable ClassCondition classToLoadByParent + ) throws IOException { + return ClassPreloadingUtils.preloadClasses( + compilerClasspath(libPath), /* estimatedClassNumber = */ 4096, parentClassLoader, classToLoadByParent + ); } - public static ClassLoader getOrCreateClassLoader(KotlinPaths paths, MessageCollector messageCollector) { - ClassLoader answer = ourClassLoaderRef.get(); - if (answer == null) { - answer = createClassLoader(paths, messageCollector); - ourClassLoaderRef = new SoftReference(answer); - } - return answer; - } - - private static URLClassLoader createClassLoader(KotlinPaths paths, MessageCollector messageCollector) { - List jars = kompilerClasspath(paths, messageCollector); + @NotNull + private static URLClassLoader createClassLoader(@NotNull File libPath) throws MalformedURLException { + List jars = compilerClasspath(libPath); URL[] urls = new URL[jars.size()]; for (int i = 0; i < urls.length; i++) { - try { - urls[i] = jars.get(i).toURI().toURL(); - } - catch (MalformedURLException e) { - throw new RuntimeException(e); // Checked exceptions are great! I love them, and I love brilliant library designers too! - } + urls[i] = jars.get(i).toURI().toURL(); } return new URLClassLoader(urls, null); } - static void handleProcessTermination(int exitCode, MessageCollector messageCollector) { + private static void handleProcessTermination(int exitCode, @NotNull MessageCollector messageCollector) { if (exitCode != 0 && exitCode != 1) { messageCollector.report(ERROR, "Compiler terminated with exit code: " + exitCode, NO_LOCATION); } } - public static int getReturnCodeFromObject(Object rc) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - if ("org.jetbrains.jet.cli.common.ExitCode".equals(rc.getClass().getCanonicalName())) { - return (Integer)rc.getClass().getMethod("getCode").invoke(rc); + public static int getReturnCodeFromObject(@Nullable Object rc) throws Exception { + if (rc == null) { + return /* ExitCode.INTERNAL_ERROR */ 2; + } + else if ("org.jetbrains.jet.cli.common.ExitCode".equals(rc.getClass().getCanonicalName())) { + return (Integer) rc.getClass().getMethod("getCode").invoke(rc); } else { throw new IllegalStateException("Unexpected return: " + rc); } } + @Nullable public static Object invokeExecMethod( - String compilerClassName, String[] arguments, CompilerEnvironment environment, - MessageCollector messageCollector, PrintStream out, boolean usePreloader + @NotNull String compilerClassName, + @NotNull String[] arguments, + @NotNull CompilerEnvironment environment, + @NotNull MessageCollector messageCollector, + @NotNull PrintStream out, + boolean usePreloader ) throws Exception { - ClassLoader loader = usePreloader - ? getOrCreatePreloader(environment.getKotlinPaths(), environment.getParentClassLoader(), - environment.getClassesToLoadByParent(), messageCollector) - : getOrCreateClassLoader(environment.getKotlinPaths(), messageCollector); + File libPath = getLibPath(environment.getKotlinPaths(), messageCollector); + if (libPath == null) return null; - Class kompiler = Class.forName(compilerClassName, true, loader); + ClassLoader classLoader = ourClassLoaderRef.get(); + if (classLoader == null) { + classLoader = usePreloader + ? createPreloader(libPath, environment.getParentClassLoader(), environment.getClassesToLoadByParent()) + : createClassLoader(libPath); + ourClassLoaderRef = new SoftReference(classLoader); + } + + Class kompiler = Class.forName(compilerClassName, true, classLoader); Method exec = kompiler.getMethod( - "execAndOutputHtml", + "execAndOutputXml", PrintStream.class, - Class.forName("org.jetbrains.jet.config.Services", true, loader), String[].class); + Class.forName("org.jetbrains.jet.config.Services", true, classLoader), + String[].class + ); return exec.invoke(kompiler.newInstance(), out, environment.getServices(), arguments); } - public static void outputCompilerMessagesAndHandleExitCode(@NotNull MessageCollector messageCollector, + public static void outputCompilerMessagesAndHandleExitCode( + @NotNull MessageCollector messageCollector, @NotNull OutputItemsCollector outputItemsCollector, - @NotNull Function compilerRun) { + @NotNull Function compilerRun + ) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); PrintStream out = new PrintStream(outputStream);