From 4ed07cd9aed03dfbe3941861f0153f9c916acb7f Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 21 Nov 2012 18:16:09 +0400 Subject: [PATCH] Introducing KotlinPaths to impose some discipline on compiler/library location --- .../jet/buildtools/core/BytecodeCompiler.java | 18 ++- .../jetbrains/jet/cli/jvm/K2JVMCompiler.java | 18 ++- .../jvm/compiler/CompileEnvironmentUtil.java | 21 +-- .../compiler/KotlinToJVMBytecodeCompiler.java | 19 ++- .../data/antTaskJvm/hello.kt | 4 +- .../data/antTaskJvm/hello.run.expected | 2 +- .../src/org/jetbrains/kotlin/AntTaskTest.java | 5 +- .../tests/org/jetbrains/jet/JetTestUtils.java | 5 + .../org/jetbrains/jet/cli/jvm/CliTest.java | 7 +- .../AnnotationJavaDescriptorResolverTest.java | 9 +- .../org/jetbrains/jet/utils/KotlinPaths.java | 65 ++++++++ .../src/org/jetbrains/jet/utils/PathUtil.java | 150 +++++++++--------- .../compiler/runner/CompilerEnvironment.java | 35 ++-- .../compiler/runner/CompilerRunnerUtil.java | 15 +- .../compiler/runner/KotlinCompilerRunner.java | 4 +- .../OutdatedKotlinRuntimeNotification.java | 4 +- .../compiler/TranslatingCompilerUtils.java | 9 +- ...gureKotlinLibraryNotificationProvider.java | 8 +- .../jet/plugin/quickfix/JsModuleSetUp.java | 8 +- .../jet/jps/build/KotlinBuilder.java | 2 +- 20 files changed, 244 insertions(+), 164 deletions(-) create mode 100644 compiler/util/src/org/jetbrains/jet/utils/KotlinPaths.java diff --git a/build-tools/core/src/org/jetbrains/jet/buildtools/core/BytecodeCompiler.java b/build-tools/core/src/org/jetbrains/jet/buildtools/core/BytecodeCompiler.java index bdd41294c5c..a4f78a6f4ae 100644 --- a/build-tools/core/src/org/jetbrains/jet/buildtools/core/BytecodeCompiler.java +++ b/build-tools/core/src/org/jetbrains/jet/buildtools/core/BytecodeCompiler.java @@ -25,6 +25,7 @@ import org.jetbrains.jet.cli.common.messages.MessageCollectorPlainTextToStream; import org.jetbrains.jet.cli.jvm.compiler.*; import org.jetbrains.jet.config.CommonConfigurationKeys; import org.jetbrains.jet.config.CompilerConfiguration; +import org.jetbrains.jet.utils.KotlinPaths; import org.jetbrains.jet.utils.PathUtil; import java.io.File; @@ -62,14 +63,15 @@ public class BytecodeCompiler { } private CompilerConfiguration createConfiguration(String stdlib, String[] classpath, String[] sourceRoots) { + KotlinPaths paths = getKotlinPathsForAntTask(); CompilerConfiguration configuration = new CompilerConfiguration(); configuration.add(CLASSPATH_KEY, PathUtil.findRtJar()); if ((stdlib != null) && (stdlib.trim().length() > 0)) { configuration.add(CLASSPATH_KEY, new File(stdlib)); } else { - File path = PathUtil.getDefaultRuntimePath(); - if (path != null) { + File path = paths.getRuntimePath(); + if (path.exists()) { configuration.add(CLASSPATH_KEY, path); } } @@ -78,8 +80,8 @@ public class BytecodeCompiler { configuration.add(CLASSPATH_KEY, new File(path)); } } - File jdkAnnotationsPath = PathUtil.getJdkAnnotationsPath(); - if (jdkAnnotationsPath != null) { + File jdkAnnotationsPath = paths.getJdkAnnotationsPath(); + if (jdkAnnotationsPath.exists()) { configuration.add(ANNOTATIONS_PATH_KEY, jdkAnnotationsPath); } @@ -91,7 +93,6 @@ public class BytecodeCompiler { return configuration; } - /** * Retrieves compilation error message. * @@ -172,7 +173,7 @@ public class BytecodeCompiler { @Nullable String stdlib, @Nullable String[] classpath) { try { - List modules = CompileEnvironmentUtil.loadModuleScript(module, MessageCollectorPlainTextToStream.PLAIN_TEXT_TO_SYSTEM_ERR); + List modules = CompileEnvironmentUtil.loadModuleScript(getKotlinPathsForAntTask(), module, MessageCollectorPlainTextToStream.PLAIN_TEXT_TO_SYSTEM_ERR); List sourcesRoots = new ArrayList(); for (Module m : modules) { sourcesRoots.addAll(m.getSourceFiles()); @@ -196,4 +197,9 @@ public class BytecodeCompiler { public void setCompilerPlugins(List compilerPlugins) { this.compilerPlugins = compilerPlugins; } + + private static KotlinPaths getKotlinPathsForAntTask() { + return new KotlinPaths(PathUtil.getJarPathForClass(BytecodeCompiler.class).getParentFile().getParentFile()); + } + } diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/K2JVMCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/K2JVMCompiler.java index b518f915335..a39065bf6c2 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/K2JVMCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/K2JVMCompiler.java @@ -36,6 +36,7 @@ import org.jetbrains.jet.codegen.CompilationException; import org.jetbrains.jet.config.CommonConfigurationKeys; import org.jetbrains.jet.config.CompilerConfiguration; import org.jetbrains.jet.lang.resolve.AnalyzerScriptParameter; +import org.jetbrains.jet.utils.KotlinPaths; import org.jetbrains.jet.utils.PathUtil; import java.io.File; @@ -60,9 +61,10 @@ public class K2JVMCompiler extends CLICompiler { @Override @NotNull protected ExitCode doExecute(K2JVMCompilerArguments arguments, PrintingMessageCollector messageCollector, Disposable rootDisposable) { + KotlinPaths paths = PathUtil.getKotlinPathsForCompiler(); CompilerConfiguration configuration = new CompilerConfiguration(); - configuration.addAll(JVMConfigurationKeys.CLASSPATH_KEY, getClasspath(arguments)); - configuration.addAll(JVMConfigurationKeys.ANNOTATIONS_PATH_KEY, getAnnotationsPath(arguments)); + configuration.addAll(JVMConfigurationKeys.CLASSPATH_KEY, getClasspath(paths, arguments)); + configuration.addAll(JVMConfigurationKeys.ANNOTATIONS_PATH_KEY, getAnnotationsPath(paths, arguments)); final List argumentsSourceDirs = arguments.getSourceDirs(); if (!arguments.script && @@ -124,7 +126,7 @@ public class K2JVMCompiler extends CLICompiler { if (arguments.module != null) { boolean oldVerbose = messageCollector.isVerbose(); messageCollector.setVerbose(false); - List modules = CompileEnvironmentUtil.loadModuleScript(arguments.module, messageCollector); + List modules = CompileEnvironmentUtil.loadModuleScript(paths, arguments.module, messageCollector); messageCollector.setVerbose(oldVerbose); File directory = new File(arguments.module).getParentFile(); noErrors = KotlinToJVMBytecodeCompiler.compileModules(configuration, modules, @@ -134,7 +136,7 @@ public class K2JVMCompiler extends CLICompiler { else if (arguments.script) { List scriptArgs = arguments.freeArgs.subList(1, arguments.freeArgs.size()); JetCoreEnvironment environment = new JetCoreEnvironment(rootDisposable, configuration); - noErrors = KotlinToJVMBytecodeCompiler.compileAndExecuteScript(environment, scriptArgs); + noErrors = KotlinToJVMBytecodeCompiler.compileAndExecuteScript(paths, environment, scriptArgs); } else { JetCoreEnvironment environment = new JetCoreEnvironment(rootDisposable, configuration); @@ -180,13 +182,13 @@ public class K2JVMCompiler extends CLICompiler { } @NotNull - private static List getClasspath(@NotNull K2JVMCompilerArguments arguments) { + private static List getClasspath(@NotNull KotlinPaths paths, @NotNull K2JVMCompilerArguments arguments) { List classpath = Lists.newArrayList(); if (!arguments.noJdk) { classpath.add(PathUtil.findRtJar()); } if (!arguments.noStdlib) { - classpath.add(PathUtil.getDefaultRuntimePath()); + classpath.add(paths.getRuntimePath()); } if (arguments.classpath != null) { for (String element : Splitter.on(File.pathSeparatorChar).split(arguments.classpath)) { @@ -197,10 +199,10 @@ public class K2JVMCompiler extends CLICompiler { } @NotNull - private static List getAnnotationsPath(@NotNull K2JVMCompilerArguments arguments) { + private static List getAnnotationsPath(@NotNull KotlinPaths paths, @NotNull K2JVMCompilerArguments arguments) { List annotationsPath = Lists.newArrayList(); if (!arguments.noJdkAnnotations) { - annotationsPath.add(PathUtil.getJdkAnnotationsPath()); + annotationsPath.add(paths.getJdkAnnotationsPath()); } if (arguments.annotations != null) { for (String element : Splitter.on(File.pathSeparatorChar).split(arguments.annotations)) { diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CompileEnvironmentUtil.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CompileEnvironmentUtil.java index 88409aaf403..08bb5b442a7 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CompileEnvironmentUtil.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CompileEnvironmentUtil.java @@ -35,6 +35,7 @@ import org.jetbrains.jet.config.CommonConfigurationKeys; import org.jetbrains.jet.config.CompilerConfiguration; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.utils.KotlinPaths; import org.jetbrains.jet.utils.PathUtil; import java.io.File; @@ -81,7 +82,7 @@ public class CompileEnvironmentUtil { } @NotNull - public static List loadModuleScript(String moduleScriptFile, MessageCollector messageCollector) { + public static List loadModuleScript(KotlinPaths paths, String moduleScriptFile, MessageCollector messageCollector) { Disposable disposable = new Disposable() { @Override public void dispose() { @@ -89,13 +90,13 @@ public class CompileEnvironmentUtil { } }; CompilerConfiguration configuration = new CompilerConfiguration(); - File defaultRuntimePath = PathUtil.getDefaultRuntimePath(); - if (defaultRuntimePath != null) { - configuration.add(JVMConfigurationKeys.CLASSPATH_KEY, defaultRuntimePath); + File runtimePath = paths.getRuntimePath(); + if (runtimePath.exists()) { + configuration.add(JVMConfigurationKeys.CLASSPATH_KEY, runtimePath); } configuration.add(JVMConfigurationKeys.CLASSPATH_KEY, PathUtil.findRtJar()); - File jdkAnnotationsPath = PathUtil.getJdkAnnotationsPath(); - if (jdkAnnotationsPath != null) { + File jdkAnnotationsPath = paths.getJdkAnnotationsPath(); + if (jdkAnnotationsPath.exists()) { configuration.add(JVMConfigurationKeys.ANNOTATIONS_PATH_KEY, jdkAnnotationsPath); } configuration.add(CommonConfigurationKeys.SOURCE_ROOTS_KEY, moduleScriptFile); @@ -109,7 +110,7 @@ public class CompileEnvironmentUtil { loadModuleScriptText(moduleScriptFile)); } - List modules = runDefineModules(moduleScriptFile, generationState.getFactory()); + List modules = runDefineModules(paths, moduleScriptFile, generationState.getFactory()); Disposer.dispose(disposable); @@ -123,10 +124,10 @@ public class CompileEnvironmentUtil { return modules; } - private static List runDefineModules(String moduleFile, ClassFileFactory factory) { - File stdlibJar = PathUtil.getDefaultRuntimePath(); + private static List runDefineModules(KotlinPaths paths, String moduleFile, ClassFileFactory factory) { + File stdlibJar = paths.getRuntimePath(); GeneratedClassLoader loader; - if (stdlibJar != null) { + if (stdlibJar.exists()) { try { loader = new GeneratedClassLoader(factory, new URLClassLoader(new URL[]{stdlibJar.toURI().toURL()}, AllModules.class.getClassLoader())); diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java index 978edce6009..1a169419a55 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.java @@ -51,6 +51,7 @@ import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.plugin.JetMainDetector; import org.jetbrains.jet.utils.ExceptionUtils; +import org.jetbrains.jet.utils.KotlinPaths; import org.jetbrains.jet.utils.PathUtil; import java.io.File; @@ -222,9 +223,10 @@ public class KotlinToJVMBytecodeCompiler { } public static boolean compileAndExecuteScript( + @NotNull KotlinPaths paths, @NotNull JetCoreEnvironment environment, @NotNull List scriptArgs) { - Class scriptClass = compileScript(environment, null); + Class scriptClass = compileScript(paths, environment, null); if(scriptClass == null) return false; @@ -240,8 +242,8 @@ public class KotlinToJVMBytecodeCompiler { return true; } - public static Class compileScript( - @NotNull JetCoreEnvironment environment, ClassLoader parentLoader) { + private static Class compileScript( + @NotNull KotlinPaths paths, @NotNull JetCoreEnvironment environment, @Nullable ClassLoader parentLoader) { GenerationState generationState = analyzeAndGenerate(environment); if (generationState == null) { @@ -253,7 +255,7 @@ public class KotlinToJVMBytecodeCompiler { try { GeneratedClassLoader classLoader = new GeneratedClassLoader(factory, new URLClassLoader(new URL[]{ // TODO: add all classpath - PathUtil.getDefaultRuntimePath().toURI().toURL() + paths.getRuntimePath().toURI().toURL() }, parentLoader == null ? AllModules.class.getClassLoader() : parentLoader)); JetFile scriptFile = environment.getSourceFiles().get(0); @@ -364,8 +366,9 @@ public class KotlinToJVMBytecodeCompiler { } public static Class compileScript( - ClassLoader parentLoader, - String scriptPath, + @NotNull ClassLoader parentLoader, + @NotNull KotlinPaths paths, + @NotNull String scriptPath, @Nullable List scriptParameters, @Nullable List scriptDefinitions) { final MessageRenderer messageRenderer = MessageRenderer.PLAIN; @@ -377,7 +380,7 @@ public class KotlinToJVMBytecodeCompiler { compilerConfiguration.addAll(JVMConfigurationKeys.CLASSPATH_KEY, getClasspath(parentLoader)); compilerConfiguration.add(JVMConfigurationKeys.CLASSPATH_KEY, PathUtil.findRtJar()); compilerConfiguration.addAll(JVMConfigurationKeys.ANNOTATIONS_PATH_KEY, Collections.singletonList( - PathUtil.getJdkAnnotationsPath())); + paths.getJdkAnnotationsPath())); compilerConfiguration.add(CommonConfigurationKeys.SOURCE_ROOTS_KEY, scriptPath); compilerConfiguration.addAll(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY, scriptDefinitions != null ? scriptDefinitions : Collections.emptyList()); @@ -387,7 +390,7 @@ public class KotlinToJVMBytecodeCompiler { try { JetScriptDefinitionProvider.getInstance(environment.getProject()).markFileAsScript(environment.getSourceFiles().get(0)); - return compileScript(environment, parentLoader); + return compileScript(paths, environment, parentLoader); } catch (CompilationException e) { messageCollector.report(CompilerMessageSeverity.EXCEPTION, MessageRenderer.PLAIN.renderException(e), diff --git a/compiler/integration-tests/data/antTaskJvm/hello.kt b/compiler/integration-tests/data/antTaskJvm/hello.kt index 9098e3b590a..faa0df6ecf6 100644 --- a/compiler/integration-tests/data/antTaskJvm/hello.kt +++ b/compiler/integration-tests/data/antTaskJvm/hello.kt @@ -1,5 +1,7 @@ package Hello fun main(args : Array) { - System.out.println("Hello!") + for (s in arrayList("a")) + println("Hello, $s!") + } diff --git a/compiler/integration-tests/data/antTaskJvm/hello.run.expected b/compiler/integration-tests/data/antTaskJvm/hello.run.expected index fc47ec99014..a408df3552b 100644 --- a/compiler/integration-tests/data/antTaskJvm/hello.run.expected +++ b/compiler/integration-tests/data/antTaskJvm/hello.run.expected @@ -1,2 +1,2 @@ -OUT Hello! +OUT Hello, a! Return code: 0 diff --git a/compiler/integration-tests/src/org/jetbrains/kotlin/AntTaskTest.java b/compiler/integration-tests/src/org/jetbrains/kotlin/AntTaskTest.java index c0a9674a760..0ef274ca717 100644 --- a/compiler/integration-tests/src/org/jetbrains/kotlin/AntTaskTest.java +++ b/compiler/integration-tests/src/org/jetbrains/kotlin/AntTaskTest.java @@ -25,10 +25,11 @@ import static junit.framework.Assert.assertEquals; public class AntTaskTest extends KotlinIntegrationTestBase { @Test public void antTaskJvm() throws Exception { - final String jar = tmpdir.getTmpDir().getAbsolutePath() + File.separator + "hello.jar"; + String jar = tmpdir.getTmpDir().getAbsolutePath() + File.separator + "hello.jar"; + String runtime = new File("dist/kotlinc/lib/kotlin-runtime.jar").getAbsolutePath(); assertEquals("compilation failed", 0, runAnt("build.log", "build.xml")); - runJava("hello.run", "-cp", jar, "Hello.namespace"); + runJava("hello.run", "-cp", jar + ":" + runtime, "Hello.namespace"); } @Override diff --git a/compiler/tests/org/jetbrains/jet/JetTestUtils.java b/compiler/tests/org/jetbrains/jet/JetTestUtils.java index 8ef47d5366b..72e693a1aa0 100644 --- a/compiler/tests/org/jetbrains/jet/JetTestUtils.java +++ b/compiler/tests/org/jetbrains/jet/JetTestUtils.java @@ -49,6 +49,7 @@ import org.jetbrains.jet.test.TestMetadata; import org.jetbrains.jet.util.slicedmap.ReadOnlySlice; import org.jetbrains.jet.util.slicedmap.SlicedMap; import org.jetbrains.jet.util.slicedmap.WritableSlice; +import org.jetbrains.jet.utils.KotlinPaths; import org.junit.Assert; import javax.tools.*; @@ -469,4 +470,8 @@ public class JetTestUtils { private static String getSimpleName(String generatorClassFqName) { return generatorClassFqName.substring(generatorClassFqName.lastIndexOf(".") + 1); } + + public static KotlinPaths getPathsForTests() { + return new KotlinPaths(new File("dist/kotlinc")); + } } diff --git a/compiler/tests/org/jetbrains/jet/cli/jvm/CliTest.java b/compiler/tests/org/jetbrains/jet/cli/jvm/CliTest.java index 8133f351d05..d979bdc647a 100644 --- a/compiler/tests/org/jetbrains/jet/cli/jvm/CliTest.java +++ b/compiler/tests/org/jetbrains/jet/cli/jvm/CliTest.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.cli.jvm; import com.intellij.openapi.util.io.FileUtil; import junit.framework.Assert; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.cli.common.CLICompiler; import org.jetbrains.jet.cli.common.ExitCode; import org.jetbrains.jet.cli.jvm.compiler.KotlinToJVMBytecodeCompiler; @@ -170,7 +171,7 @@ public class CliTest { AnalyzerScriptParameter parameter = new AnalyzerScriptParameter(Name.identifier("num"), JetTypeName.parse("jet.Int")); scriptParameters.add(parameter); Class aClass = KotlinToJVMBytecodeCompiler - .compileScript(getClass().getClassLoader(), "compiler/testData/cli/fib.ktscript", scriptParameters, null); + .compileScript(getClass().getClassLoader(), JetTestUtils.getPathsForTests(), "compiler/testData/cli/fib.ktscript", scriptParameters, null); Assert.assertNotNull(aClass); try { @@ -187,7 +188,7 @@ public class CliTest { AnalyzerScriptParameter parameter = new AnalyzerScriptParameter(Name.identifier("num"), JetTypeName.parse("jet.Int")); scriptParameters.add(parameter); Class aClass = KotlinToJVMBytecodeCompiler - .compileScript(getClass().getClassLoader(), "compiler/testData/cli/fib.kt", scriptParameters, null); + .compileScript(getClass().getClassLoader(), JetTestUtils.getPathsForTests(), "compiler/testData/cli/fib.kt", scriptParameters, null); Assert.assertNotNull(aClass); try { @@ -205,7 +206,7 @@ public class CliTest { AnalyzerScriptParameter parameter = new AnalyzerScriptParameter(Name.identifier("num"), JetTypeName.parse("jet.Int")); scriptParameters.add(parameter); Class aClass = KotlinToJVMBytecodeCompiler - .compileScript(getClass().getClassLoader(), "compiler/testData/cli/fib.fib.kt", null, Arrays.asList(new JetScriptDefinition(".fib.kt",scriptParameters))); + .compileScript(getClass().getClassLoader(), JetTestUtils.getPathsForTests(), "compiler/testData/cli/fib.fib.kt", null, Arrays.asList(new JetScriptDefinition(".fib.kt",scriptParameters))); Assert.assertNotNull(aClass); try { diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/AnnotationJavaDescriptorResolverTest.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/AnnotationJavaDescriptorResolverTest.java index 092e517145a..44f955ae959 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/AnnotationJavaDescriptorResolverTest.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/AnnotationJavaDescriptorResolverTest.java @@ -37,7 +37,6 @@ import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.resolve.DescriptorRenderer; import org.jetbrains.jet.test.TestCaseWithTmpdir; -import org.jetbrains.jet.utils.PathUtil; import java.io.File; import java.io.IOException; @@ -64,14 +63,14 @@ public class AnnotationJavaDescriptorResolverTest extends TestCaseWithTmpdir { StringBuilder builder = new StringBuilder(tmpdir.getAbsolutePath()); builder.append(File.pathSeparator); - File runtimePath = PathUtil.getDefaultRuntimePath(); - if (runtimePath != null) { + File runtimePath = JetTestUtils.getPathsForTests().getRuntimePath(); + if (runtimePath.exists()) { builder.append(runtimePath.getAbsolutePath()); builder.append(File.pathSeparator); } - File annotationsPath = PathUtil.getJdkAnnotationsPath(); - if (annotationsPath != null) { + File annotationsPath = JetTestUtils.getPathsForTests().getJdkAnnotationsPath(); + if (annotationsPath.exists()) { builder.append(annotationsPath.getAbsolutePath()); } diff --git a/compiler/util/src/org/jetbrains/jet/utils/KotlinPaths.java b/compiler/util/src/org/jetbrains/jet/utils/KotlinPaths.java new file mode 100644 index 00000000000..67ba3b1386f --- /dev/null +++ b/compiler/util/src/org/jetbrains/jet/utils/KotlinPaths.java @@ -0,0 +1,65 @@ +/* + * 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.utils; + +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +public class KotlinPaths { + // kotlinc directory + private final File homePath; + + public KotlinPaths(@NotNull File homePath) { + this.homePath = homePath; + } + + @NotNull + public File getHomePath() { + return homePath; + } + + @NotNull + public File getLibPath() { + return new File(homePath, "lib"); + } + + @NotNull + public File getRuntimePath() { + return getLibraryFile("kotlin-runtime.jar"); + } + + @NotNull + public File getJdkAnnotationsPath() { + return getLibraryFile(PathUtil.JDK_ANNOTATIONS_JAR); + } + + @NotNull + public File getJsLibJsPath() { + return getLibraryFile(PathUtil.JS_LIB_JS_NAME); + } + + @NotNull + public File getJsLibJarPath() { + return getLibraryFile(PathUtil.JS_LIB_JAR_NAME); + } + + @NotNull + private File getLibraryFile(@NotNull String fileName) { + return new File(getLibPath(), fileName); + } +} diff --git a/compiler/util/src/org/jetbrains/jet/utils/PathUtil.java b/compiler/util/src/org/jetbrains/jet/utils/PathUtil.java index 107e9fa6fdd..3204b52a2e5 100644 --- a/compiler/util/src/org/jetbrains/jet/utils/PathUtil.java +++ b/compiler/util/src/org/jetbrains/jet/utils/PathUtil.java @@ -24,7 +24,6 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.io.File; @@ -34,87 +33,86 @@ public class PathUtil { public static final String JS_LIB_JS_NAME = "kotlinEcma3.js"; public static final String JDK_ANNOTATIONS_JAR = "kotlin-jdk-annotations.jar"; + private static final File NO_PATH = new File(""); + private PathUtil() {} - public static File getDefaultCompilerPath() { - File plugin_jar_path = new File(getJarPathForClass(PathUtil.class)); - - if (!plugin_jar_path.exists()) return null; - - if (plugin_jar_path.getName().equals("kotlin-plugin.jar")) { - File lib = plugin_jar_path.getParentFile(); - File pluginHome = lib.getParentFile(); - - File answer = new File(pluginHome, "kotlinc"); - - return answer.exists() ? answer : null; - } - - if (plugin_jar_path.getName().equals("kotlin-compiler.jar")) { - File lib = plugin_jar_path.getParentFile(); - File answer = lib.getParentFile(); - return answer.exists() ? answer : null; - } - - File current = new File("").getAbsoluteFile(); // CWD - - do { - File atDevHome = new File(current, "dist/kotlinc"); - if (atDevHome.exists()) return atDevHome; - current = current.getParentFile(); - } while (current != null); - - return null; - } - - public static File getCompilerPathForJpsPlugin() { - File plugin_jar_path = new File(getJarPathForClass(PathUtil.class)); - - if (!plugin_jar_path.exists()) return null; - - if (plugin_jar_path.getName().equals("kotlin-jps-plugin.jar")) { - File pluginHome = plugin_jar_path.getParentFile().getParentFile().getParentFile(); - File answer = new File(pluginHome, "kotlinc"); - return answer.exists() ? answer : null; - } - - return null; - } - - @Nullable - public static File getDefaultRuntimePath() { - return getFilePackedIntoLib("kotlin-runtime.jar"); - } - - @Nullable - public static File getDefaultJsLibJsPath() { - return getFilePackedIntoLib(JS_LIB_JS_NAME); - } - - @Nullable - public static File getDefaultJsLibJarPath() { - return getFilePackedIntoLib(JS_LIB_JAR_NAME); - } - - @Nullable - private static File getFilePackedIntoLib(@NotNull String filePathFromLib) { - File compilerPath = getDefaultCompilerPath(); - if (compilerPath == null) return null; - - File answer = new File(compilerPath, "lib/" + filePathFromLib); - - return answer.exists() ? answer : null; - } - - @Nullable - public static File getJdkAnnotationsPath() { - return getFilePackedIntoLib(JDK_ANNOTATIONS_JAR); + @NotNull + public static KotlinPaths getKotlinPathsForIdeaPlugin() { + return new KotlinPaths(getCompilerPathForIdeaPlugin()); } @NotNull - public static String getJarPathForClass(@NotNull Class aClass) { + public static KotlinPaths getKotlinPathsForJpsPlugin() { + return new KotlinPaths(getCompilerPathForJpsPlugin()); + } + + @NotNull + public static KotlinPaths getKotlinPathsForCompiler() { + if (!getPathUtilJar().isFile()) { + // Not running from a jar, i.e. it is it must be a unit test + return getKotlinPathsForDistDirectory(); + } + return new KotlinPaths(getCompilerPathForCompilerJar()); + } + + @NotNull + public static KotlinPaths getKotlinPathsForDistDirectory() { + return new KotlinPaths(new File("dist/kotlinc")); + } + + @NotNull + private static File getCompilerPathForCompilerJar() { + File jar = getPathUtilJar(); + + if (!jar.exists()) return NO_PATH; + + if (jar.getName().equals("kotlin-compiler.jar")) { + File lib = jar.getParentFile(); + return lib.getParentFile(); + } + + return NO_PATH; + } + + @NotNull + private static File getCompilerPathForJpsPlugin() { + File jar = getPathUtilJar(); + + if (!jar.exists()) return NO_PATH; + + if (jar.getName().equals("kotlin-jps-plugin.jar")) { + File pluginHome = jar.getParentFile().getParentFile().getParentFile(); + return new File(pluginHome, "kotlinc"); + } + + return NO_PATH; + } + + @NotNull + private static File getCompilerPathForIdeaPlugin() { + File jar = getPathUtilJar(); + + if (!jar.exists()) return NO_PATH; + + if (jar.getName().equals("kotlin-plugin.jar")) { + File lib = jar.getParentFile(); + File pluginHome = lib.getParentFile(); + + return new File(pluginHome, "kotlinc"); + } + + return NO_PATH; + } + + private static File getPathUtilJar() { + return getJarPathForClass(PathUtil.class); + } + + @NotNull + public static File getJarPathForClass(@NotNull Class aClass) { String resourceRoot = PathManager.getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class"); - return new File(resourceRoot).getAbsoluteFile().getAbsolutePath(); + return new File(resourceRoot).getAbsoluteFile(); } @NotNull diff --git a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerEnvironment.java b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerEnvironment.java index dcd947e95da..f1cedf2c1fc 100644 --- a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerEnvironment.java +++ b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/CompilerEnvironment.java @@ -19,7 +19,7 @@ package org.jetbrains.jet.compiler.runner; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.cli.common.messages.MessageCollector; -import org.jetbrains.jet.utils.PathUtil; +import org.jetbrains.jet.utils.KotlinPaths; import java.io.File; @@ -31,39 +31,26 @@ import static org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity.ERRO */ public final class CompilerEnvironment { - @NotNull - public static CompilerEnvironment getEnvironmentFor(boolean tests, @Nullable File mainOutput, @Nullable File outputDirectoryForTests) { - final File outputDir = tests ? outputDirectoryForTests : mainOutput; - return getEnvironmentFor(outputDir); + public static CompilerEnvironment getEnvironmentFor(@NotNull KotlinPaths kotlinPaths, @Nullable File outputDir) { + return new CompilerEnvironment(kotlinPaths, outputDir); } - public static CompilerEnvironment getEnvironmentFor(@Nullable File outputDir) { - File kotlinHome = PathUtil.getDefaultCompilerPath(); - return getEnvironmentFor(kotlinHome, outputDir); - } - - public static CompilerEnvironment getEnvironmentFor(@Nullable File kotlinHome, @Nullable File outputDir) { - return new CompilerEnvironment(kotlinHome, outputDir); - } - - @Nullable - private final File kotlinHome; + private final KotlinPaths kotlinPaths; @Nullable private final File output; - public CompilerEnvironment(@Nullable File home, @Nullable File output) { - this.kotlinHome = home; + private CompilerEnvironment(@NotNull KotlinPaths kotlinPaths, @Nullable File output) { + this.kotlinPaths = kotlinPaths; this.output = output; } public boolean success() { - return kotlinHome != null && output != null; + return kotlinPaths.getHomePath().exists() && output != null; } @NotNull - public File getKotlinHome() { - assert kotlinHome != null; - return kotlinHome; + public KotlinPaths getKotlinPaths() { + return kotlinPaths; } @NotNull @@ -76,8 +63,8 @@ public final class CompilerEnvironment { if (output == null) { messageCollector.report(ERROR, "[Internal Error] No output directory", NO_LOCATION); } - if (kotlinHome == null) { - messageCollector.report(ERROR, "Cannot find kotlinc home. Make sure plugin is properly installed", NO_LOCATION); + if (!kotlinPaths.getHomePath().exists()) { + messageCollector.report(ERROR, "Cannot find kotlinc home: " + kotlinPaths.getHomePath() + ". Make sure plugin is properly installed", NO_LOCATION); } } 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 f457754fbf2..731060e9605 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 @@ -19,6 +19,7 @@ package org.jetbrains.jet.compiler.runner; import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.cli.common.messages.*; +import org.jetbrains.jet.utils.KotlinPaths; import java.io.*; import java.lang.ref.SoftReference; @@ -36,8 +37,8 @@ public class CompilerRunnerUtil { private static SoftReference ourClassLoaderRef = new SoftReference(null); - public static List kompilerClasspath(File kotlinHome, MessageCollector messageCollector) { - File libs = new File(kotlinHome, "lib"); + public static List kompilerClasspath(KotlinPaths paths, MessageCollector messageCollector) { + File libs = paths.getLibPath(); if (!libs.exists() || libs.isFile()) { messageCollector.report(ERROR, "Broken compiler at '" + libs.getAbsolutePath() + "'. Make sure plugin is properly installed", NO_LOCATION); @@ -49,17 +50,17 @@ public class CompilerRunnerUtil { return answer; } - public static URLClassLoader getOrCreateClassLoader(File kotlinHome, MessageCollector messageCollector) { + public static URLClassLoader getOrCreateClassLoader(KotlinPaths paths, MessageCollector messageCollector) { URLClassLoader answer = ourClassLoaderRef.get(); if (answer == null) { - answer = createClassloader(kotlinHome, messageCollector); + answer = createClassloader(paths, messageCollector); ourClassLoaderRef = new SoftReference(answer); } return answer; } - private static URLClassLoader createClassloader(File kotlinHome, MessageCollector messageCollector) { - List jars = kompilerClasspath(kotlinHome, messageCollector); + private static URLClassLoader createClassloader(KotlinPaths paths, MessageCollector messageCollector) { + List jars = kompilerClasspath(paths, messageCollector); URL[] urls = new URL[jars.size()]; for (int i = 0; i < urls.length; i++) { try { @@ -90,7 +91,7 @@ public class CompilerRunnerUtil { public static Object invokeExecMethod(CompilerEnvironment environment, PrintStream out, MessageCollector messageCollector, String[] arguments, String name) throws Exception { - URLClassLoader loader = getOrCreateClassLoader(environment.getKotlinHome(), messageCollector); + URLClassLoader loader = getOrCreateClassLoader(environment.getKotlinPaths(), messageCollector); Class kompiler = Class.forName(name, true, loader); Method exec = kompiler.getMethod("exec", PrintStream.class, String[].class); return exec.invoke(kompiler.newInstance(), out, arguments); diff --git a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinCompilerRunner.java b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinCompilerRunner.java index 4bdf4dcc3da..9a9da4821dd 100644 --- a/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinCompilerRunner.java +++ b/ide-compiler-runner/src/org/jetbrains/jet/compiler/runner/KotlinCompilerRunner.java @@ -69,7 +69,7 @@ public class KotlinCompilerRunner { String compilerClassName = "org.jetbrains.jet.cli.jvm.K2JVMCompiler"; String[] arguments = commandLineArguments(environment.getOutput(), scriptFile); messageCollector.report(CompilerMessageSeverity.INFO, - "Using kotlinHome=" + environment.getKotlinHome(), + "Using kotlinHome=" + environment.getKotlinPaths(), CompilerMessageLocation.NO_LOCATION); messageCollector.report(CompilerMessageSeverity.INFO, "Invoking in-process compiler " + compilerClassName + " with arguments " + Arrays.asList(arguments), @@ -107,7 +107,7 @@ public class KotlinCompilerRunner { params.getProgramParametersList().add(arg); } - for (File jar : CompilerRunnerUtil.kompilerClasspath(environment.getKotlinHome(), messageCollector)) { + for (File jar : CompilerRunnerUtil.kompilerClasspath(environment.getKotlinPaths(), messageCollector)) { params.getClassPath().add(jar); } diff --git a/idea/src/org/jetbrains/jet/plugin/OutdatedKotlinRuntimeNotification.java b/idea/src/org/jetbrains/jet/plugin/OutdatedKotlinRuntimeNotification.java index d6fedabdefc..295c706a6eb 100644 --- a/idea/src/org/jetbrains/jet/plugin/OutdatedKotlinRuntimeNotification.java +++ b/idea/src/org/jetbrains/jet/plugin/OutdatedKotlinRuntimeNotification.java @@ -105,8 +105,8 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { - File runtimePath = PathUtil.getDefaultRuntimePath(); - if (runtimePath == null) { + File runtimePath = PathUtil.getKotlinPathsForIdeaPlugin().getRuntimePath(); + if (!runtimePath.exists()) { Messages.showErrorDialog(myProject, "kotlin-runtime.jar is not found. Make sure plugin is properly installed.", "No Runtime Found"); return; diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/TranslatingCompilerUtils.java b/idea/src/org/jetbrains/jet/plugin/compiler/TranslatingCompilerUtils.java index 0736101050a..362ff3bb7e6 100644 --- a/idea/src/org/jetbrains/jet/plugin/compiler/TranslatingCompilerUtils.java +++ b/idea/src/org/jetbrains/jet/plugin/compiler/TranslatingCompilerUtils.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.plugin.compiler; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.intellij.compiler.impl.javaCompiler.OutputItemImpl; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.CompileContext; import com.intellij.openapi.compiler.TranslatingCompiler; import com.intellij.openapi.module.Module; @@ -29,6 +30,8 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.compiler.runner.CompilerEnvironment; import org.jetbrains.jet.compiler.runner.OutputItemsCollectorImpl; import org.jetbrains.jet.compiler.runner.SimpleOutputItem; +import org.jetbrains.jet.utils.KotlinPaths; +import org.jetbrains.jet.utils.PathUtil; import java.io.File; import java.util.List; @@ -42,7 +45,11 @@ public final class TranslatingCompilerUtils { 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, toNullableIoFile(mainOutput), toNullableIoFile(outputDirectoryForTests)); + File outputDir = tests ? toNullableIoFile(outputDirectoryForTests) : toNullableIoFile(mainOutput); + KotlinPaths kotlinPaths = ApplicationManager.getApplication().isUnitTestMode() + ? PathUtil.getKotlinPathsForDistDirectory() + : PathUtil.getKotlinPathsForIdeaPlugin(); + return CompilerEnvironment.getEnvironmentFor(kotlinPaths, outputDir); } @Nullable diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ConfigureKotlinLibraryNotificationProvider.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ConfigureKotlinLibraryNotificationProvider.java index 85848e0c4f9..79cb2088622 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ConfigureKotlinLibraryNotificationProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ConfigureKotlinLibraryNotificationProvider.java @@ -118,8 +118,8 @@ public class ConfigureKotlinLibraryNotificationProvider extends EditorNotificati } } - File runtimePath = PathUtil.getDefaultRuntimePath(); - if (runtimePath == null) { + File runtimePath = PathUtil.getKotlinPathsForIdeaPlugin().getRuntimePath(); + if (!runtimePath.exists()) { Messages.showErrorDialog(myProject, "kotlin-runtime.jar is not found. Make sure plugin is properly installed.", "No Runtime Found"); return null; @@ -215,8 +215,8 @@ public class ConfigureKotlinLibraryNotificationProvider extends EditorNotificati /* package */ static void addJdkAnnotations(Module module) { Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); assert sdk != null; - File annotationsIoFile = PathUtil.getJdkAnnotationsPath(); - if (annotationsIoFile != null) { + File annotationsIoFile = PathUtil.getKotlinPathsForIdeaPlugin().getJdkAnnotationsPath(); + if (annotationsIoFile.exists()) { VirtualFile jdkAnnotationsJar = LocalFileSystem.getInstance().findFileByIoFile(annotationsIoFile); if (jdkAnnotationsJar != null) { SdkModificator modificator = sdk.getSdkModificator(); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/JsModuleSetUp.java b/idea/src/org/jetbrains/jet/plugin/quickfix/JsModuleSetUp.java index e033c33cd95..2d57430cf52 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/JsModuleSetUp.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/JsModuleSetUp.java @@ -36,6 +36,7 @@ import com.intellij.psi.impl.PsiModificationTrackerImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.plugin.project.K2JSModuleComponent; +import org.jetbrains.jet.utils.KotlinPaths; import org.jetbrains.jet.utils.PathUtil; import java.io.File; @@ -109,9 +110,10 @@ public final class JsModuleSetUp { } private static boolean copyJsLibFiles(@NotNull File rootDir) { - File jsLibJarPath = PathUtil.getDefaultJsLibJarPath(); - File jsLibJsPath = PathUtil.getDefaultJsLibJsPath(); - if ((jsLibJarPath == null) || (jsLibJsPath == null)) { + KotlinPaths paths = PathUtil.getKotlinPathsForIdeaPlugin(); + File jsLibJarPath = paths.getJsLibJarPath(); + File jsLibJsPath = paths.getJsLibJsPath(); + if (!jsLibJarPath.exists() || !jsLibJsPath.exists()) { notifyFailure("JavaScript library not found. Make sure plugin is installed properly."); return false; } 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 9573d07f877..7bff4b9b7d0 100644 --- a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java +++ b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilder.java @@ -84,7 +84,7 @@ public class KotlinBuilder extends ModuleLevelBuilder { File outputDir = representativeTarget.getOutputDir(); - CompilerEnvironment environment = CompilerEnvironment.getEnvironmentFor(PathUtil.getCompilerPathForJpsPlugin(), outputDir); + CompilerEnvironment environment = CompilerEnvironment.getEnvironmentFor(PathUtil.getKotlinPathsForJpsPlugin(), outputDir); if (!environment.success()) { environment.reportErrorsTo(messageCollector); return ExitCode.ABORT;