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 c1395d86f5f..f7d78f49cf0 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 @@ -18,9 +18,7 @@ package org.jetbrains.jet.buildtools.core; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.compiler.CompileEnvironment; -import org.jetbrains.jet.compiler.CompileEnvironmentException; -import org.jetbrains.jet.compiler.CompilerPlugin; +import org.jetbrains.jet.compiler.*; import org.jetbrains.jet.compiler.messages.MessageCollector; import org.jetbrains.jet.lang.resolve.java.CompilerDependencies; import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode; @@ -42,22 +40,25 @@ public class BytecodeCompiler { /** - * Creates new instance of {@link CompileEnvironment} instance using the arguments specified. + * Creates new instance of {@link org.jetbrains.jet.compiler.CompileEnvironmentConfiguration} instance using the arguments specified. * * @param stdlib path to "kotlin-runtime.jar", only used if not null and not empty * @param classpath compilation classpath, only used if not null and not empty * * @return compile environment instance */ - private CompileEnvironment env( String stdlib, String[] classpath ) { - CompileEnvironment env = new CompileEnvironment(MessageCollector.PLAIN_TEXT_TO_SYSTEM_ERR, CompilerDependencies.compilerDependenciesForProduction(CompilerSpecialMode.REGULAR)); + private CompileEnvironmentConfiguration env( String stdlib, String[] classpath ) { + CompilerDependencies dependencies = CompilerDependencies.compilerDependenciesForProduction(CompilerSpecialMode.REGULAR); + JetCoreEnvironment environment = new JetCoreEnvironment(CompileEnvironmentUtil.createMockDisposable(), dependencies); + CompileEnvironmentConfiguration env = new CompileEnvironmentConfiguration(environment, dependencies, MessageCollector.PLAIN_TEXT_TO_SYSTEM_ERR); if (( stdlib != null ) && ( stdlib.trim().length() > 0 )) { - env.setStdlib( stdlib ); + File file = new File(stdlib); + CompileEnvironmentUtil.addToClasspath(env.getEnvironment(), file); } if (( classpath != null ) && ( classpath.length > 0 )) { - env.addToClasspath( classpath ); + CompileEnvironmentUtil.addToClasspath(env.getEnvironment(), classpath); } // lets register any compiler plugins @@ -92,7 +93,8 @@ public class BytecodeCompiler { */ public void sourcesToDir ( @NotNull String src, @NotNull String output, @Nullable String stdlib, @Nullable String[] classpath ) { try { - boolean success = env( stdlib, classpath ).compileBunchOfSources( src, null, output, true /* Last arg is ignored anyway */ ); + boolean success = KotlinToJVMBytecodeCompiler.compileBunchOfSources(env(stdlib, classpath), src, null, output, true + /* Last arg is ignored anyway */); if ( ! success ) { throw new CompileEnvironmentException( errorMessage( src, false )); } @@ -114,7 +116,7 @@ public class BytecodeCompiler { */ public void sourcesToJar ( @NotNull String src, @NotNull String jar, boolean includeRuntime, @Nullable String stdlib, @Nullable String[] classpath ) { try { - boolean success = env( stdlib, classpath ).compileBunchOfSources( src, jar, null, includeRuntime ); + boolean success = KotlinToJVMBytecodeCompiler.compileBunchOfSources(env(stdlib, classpath), src, jar, null, includeRuntime); if ( ! success ) { throw new CompileEnvironmentException( errorMessage( src, false )); } @@ -136,7 +138,8 @@ public class BytecodeCompiler { */ public void moduleToJar ( @NotNull String module, @NotNull String jar, boolean includeRuntime, @Nullable String stdlib, @Nullable String[] classpath ) { try { - boolean success = env( stdlib, classpath ).compileModuleScript( module, jar, null, includeRuntime); + CompileEnvironmentConfiguration env = env(stdlib, classpath); + boolean success = KotlinToJVMBytecodeCompiler.compileModuleScript(env, module, jar, null, includeRuntime); if ( ! success ) { throw new CompileEnvironmentException( errorMessage( module, false )); } diff --git a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java index 8be718f846a..1b058ad0151 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/KotlinCompiler.java @@ -20,11 +20,11 @@ import com.google.common.base.Splitter; import com.google.common.collect.Iterables; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; import com.sampullara.cli.Args; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.compiler.CompileEnvironment; -import org.jetbrains.jet.compiler.CompileEnvironmentException; -import org.jetbrains.jet.compiler.CompilerPlugin; +import org.jetbrains.jet.compiler.*; import org.jetbrains.jet.compiler.messages.CompilerMessageLocation; import org.jetbrains.jet.compiler.messages.CompilerMessageSeverity; import org.jetbrains.jet.compiler.messages.MessageCollector; @@ -135,23 +135,30 @@ public class KotlinCompiler { runtimeJar = null; } - CompilerDependencies dependencies = new CompilerDependencies(mode, jdkHeadersJar,runtimeJar); + CompilerDependencies dependencies = new CompilerDependencies(mode, jdkHeadersJar, runtimeJar); PrintingMessageCollector messageCollector = new PrintingMessageCollector(errStream, messageRenderer, arguments.verbose); - CompileEnvironment environment = new CompileEnvironment(messageCollector, dependencies); + Disposable rootDisposable = CompileEnvironmentUtil.createMockDisposable(); + + JetCoreEnvironment environment = new JetCoreEnvironment(rootDisposable, dependencies); + CompileEnvironmentConfiguration configuration = new CompileEnvironmentConfiguration(environment, dependencies, messageCollector); try { - configureEnvironment(environment, arguments); + configureEnvironment(configuration, arguments); boolean noErrors; if (arguments.module != null) { - noErrors = environment.compileModuleScript(arguments.module, arguments.jar, arguments.outputDir, arguments.includeRuntime); + noErrors = KotlinToJVMBytecodeCompiler.compileModuleScript(configuration, + arguments.module, arguments.jar, arguments.outputDir, + arguments.includeRuntime); } else { // TODO ideally we'd unify to just having a single field that supports multiple files/dirs if (arguments.getSourceDirs() != null) { - noErrors = environment.compileBunchOfSourceDirectories(arguments.getSourceDirs(), arguments.jar, arguments.outputDir, arguments.includeRuntime); + noErrors = KotlinToJVMBytecodeCompiler.compileBunchOfSourceDirectories(configuration, + arguments.getSourceDirs(), arguments.jar, arguments.outputDir, arguments.includeRuntime); } else { - noErrors = environment.compileBunchOfSources(arguments.src, arguments.jar, arguments.outputDir, arguments.includeRuntime); + noErrors = KotlinToJVMBytecodeCompiler.compileBunchOfSources(configuration, + arguments.src, arguments.jar, arguments.outputDir, arguments.includeRuntime); } } return noErrors ? OK : COMPILATION_ERROR; @@ -161,7 +168,7 @@ public class KotlinCompiler { return INTERNAL_ERROR; } finally { - environment.dispose(); + Disposer.dispose(rootDisposable); messageCollector.printToErrStream(); } } @@ -228,20 +235,20 @@ public class KotlinCompiler { * Strategy method to configure the environment, allowing compiler * based tools to customise their own plugins */ - protected void configureEnvironment(CompileEnvironment environment, CompilerArguments arguments) { + protected void configureEnvironment(CompileEnvironmentConfiguration configuration, CompilerArguments arguments) { // install any compiler plugins List plugins = arguments.getCompilerPlugins(); if (plugins != null) { - environment.getEnvironment().getCompilerPlugins().addAll(plugins); + configuration.getEnvironment().getCompilerPlugins().addAll(plugins); } - if (environment.getCompilerDependencies().getRuntimeJar() != null) { - environment.addToClasspath(environment.getCompilerDependencies().getRuntimeJar()); + if (configuration.getCompilerDependencies().getRuntimeJar() != null) { + CompileEnvironmentUtil.addToClasspath(configuration.getEnvironment(), configuration.getCompilerDependencies().getRuntimeJar()); } if (arguments.classpath != null) { final Iterable classpath = Splitter.on(File.pathSeparatorChar).split(arguments.classpath); - environment.addToClasspath(Iterables.toArray(classpath, String.class)); + CompileEnvironmentUtil.addToClasspath(configuration.getEnvironment(), Iterables.toArray(classpath, String.class)); } } diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java deleted file mode 100644 index ac22091f949..00000000000 --- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironment.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * 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.compiler; - -import com.intellij.openapi.Disposable; -import com.intellij.openapi.util.Disposer; -import com.intellij.testFramework.LightVirtualFile; -import com.intellij.util.LocalTimeCounter; -import jet.modules.Module; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.codegen.ClassFileFactory; -import org.jetbrains.jet.codegen.GeneratedClassLoader; -import org.jetbrains.jet.codegen.GenerationState; -import org.jetbrains.jet.compiler.messages.MessageCollector; -import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.psi.JetPsiUtil; -import org.jetbrains.jet.lang.resolve.FqName; -import org.jetbrains.jet.lang.resolve.java.CompilerDependencies; -import org.jetbrains.jet.lang.resolve.java.JvmAbi; -import org.jetbrains.jet.plugin.JetLanguage; -import org.jetbrains.jet.plugin.JetMainDetector; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.util.List; - -/** - * The environment for compiling a bunch of source files or - * - * @author yole - */ -public class CompileEnvironment { - private final Disposable rootDisposable; - private JetCoreEnvironment environment; - - private final MessageCollector messageCollector; - - @NotNull - private final CompilerDependencies compilerDependencies; - - /** - * NOTE: It's very important to call dispose for every object of this class or there will be memory leaks. - * @see Disposer - */ - public CompileEnvironment(@NotNull MessageCollector messageCollector, @NotNull CompilerDependencies compilerDependencies) { - this.messageCollector = messageCollector; - this.compilerDependencies = compilerDependencies; - this.rootDisposable = new Disposable() { - @Override - public void dispose() { - } - }; - this.environment = new JetCoreEnvironment(rootDisposable, compilerDependencies); - } - - - public void dispose() { - Disposer.dispose(rootDisposable); - } - - public boolean compileModuleScript(String moduleScriptFile, @Nullable String jarPath, @Nullable String outputDir, boolean jarRuntime) { - List modules = CompileEnvironmentUtil.loadModuleScript(moduleScriptFile, messageCollector); - - if (modules == null) { - throw new CompileEnvironmentException("Module script " + moduleScriptFile + " compilation failed"); - } - - if (modules.isEmpty()) { - throw new CompileEnvironmentException("No modules where defined by " + moduleScriptFile); - } - - final String directory = new File(moduleScriptFile).getParent(); - for (Module moduleBuilder : modules) { - if (compilerDependencies.getRuntimeJar() != null) { - addToClasspath(compilerDependencies.getRuntimeJar()); - } - ClassFileFactory moduleFactory = compileModule(moduleBuilder, directory); - if (moduleFactory == null) { - return false; - } - if (outputDir != null) { - CompileEnvironmentUtil.writeToOutputDirectory(moduleFactory, outputDir); - } - else { - String path = jarPath != null ? jarPath : new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(); - try { - CompileEnvironmentUtil.writeToJar(moduleFactory, new FileOutputStream(path), null, jarRuntime); - } - catch (FileNotFoundException e) { - throw new CompileEnvironmentException("Invalid jar path " + path, e); - } - } - } - return true; - } - - public ClassFileFactory compileModule(Module moduleBuilder, String directory) { - if (moduleBuilder.getSourceFiles().isEmpty()) { - throw new CompileEnvironmentException("No source files where defined"); - } - - for (String sourceFile : moduleBuilder.getSourceFiles()) { - File source = new File(sourceFile); - if (!source.isAbsolute()) { - source = new File(directory, sourceFile); - } - - if (!source.exists()) { - throw new CompileEnvironmentException("'" + source + "' does not exist"); - } - - environment.addSources(source.getPath()); - } - for (String classpathRoot : moduleBuilder.getClasspathRoots()) { - environment.addToClasspath(new File(classpathRoot)); - } - - CompileEnvironmentUtil.ensureRuntime(environment, compilerDependencies); - - return analyze(); - } - - public ClassLoader compileText(String code) { - environment.addSources(new LightVirtualFile("script" + LocalTimeCounter.currentTime() + ".kt", JetLanguage.INSTANCE, code)); - - ClassFileFactory factory = analyze(); - if (factory == null) { - return null; - } - return new GeneratedClassLoader(factory); - } - - public boolean compileBunchOfSources(String sourceFileOrDir, String jar, String outputDir, boolean includeRuntime) { - environment.addSources(sourceFileOrDir); - - return compileBunchOfSources(jar, outputDir, includeRuntime); - } - - public boolean compileBunchOfSourceDirectories(List sources, String jar, String outputDir, boolean includeRuntime) { - for (String source : sources) { - environment.addSources(source); - } - - return compileBunchOfSources(jar, outputDir, includeRuntime); - } - - private boolean compileBunchOfSources(String jar, String outputDir, boolean includeRuntime) { - FqName mainClass = null; - for (JetFile file : environment.getSourceFiles()) { - if (JetMainDetector.hasMain(file.getDeclarations())) { - FqName fqName = JetPsiUtil.getFQName(file); - mainClass = fqName.child(JvmAbi.PACKAGE_CLASS); - break; - } - } - - CompileEnvironmentUtil.ensureRuntime(environment, compilerDependencies); - - ClassFileFactory factory = analyze(); - if (factory == null) { - return false; - } - - if (jar != null) { - try { - CompileEnvironmentUtil.writeToJar(factory, new FileOutputStream(jar), mainClass, includeRuntime); - } catch (FileNotFoundException e) { - throw new CompileEnvironmentException("Invalid jar path " + jar, e); - } - } - else if (outputDir != null) { - CompileEnvironmentUtil.writeToOutputDirectory(factory, outputDir); - } - else { - throw new CompileEnvironmentException("Output directory or jar file is not specified - no files will be saved to the disk"); - } - return true; - } - - private ClassFileFactory analyze() { - boolean stubs = compilerDependencies.getCompilerSpecialMode().isStubs(); - GenerationState generationState = - KotlinToJVMBytecodeCompiler - .analyzeAndGenerate(environment, compilerDependencies, messageCollector, stubs); - if (generationState == null) { - return null; - } - return generationState.getFactory(); - } - - /** - * Add path specified to the compilation environment. - * @param paths paths to add - */ - public void addToClasspath(File ... paths) { - for (File path : paths) { - if (!path.exists()) { - throw new CompileEnvironmentException("'" + path + "' does not exist"); - } - environment.addToClasspath(path); - } - } - - /** - * Add path specified to the compilation environment. - * @param paths paths to add - */ - public void addToClasspath(String ... paths) { - for (String path : paths) { - addToClasspath( new File(path)); - } - } - - public void setStdlib(String stdlib) { - File file = new File(stdlib); - addToClasspath(file); - } - - public JetCoreEnvironment getEnvironment() { - return environment; - } - - @NotNull - public CompilerDependencies getCompilerDependencies() { - return compilerDependencies; - } -} diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentConfiguration.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentConfiguration.java new file mode 100644 index 00000000000..2b73bd0e964 --- /dev/null +++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentConfiguration.java @@ -0,0 +1,56 @@ +/* + * 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.compiler; + +import com.intellij.openapi.util.Disposer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.compiler.messages.MessageCollector; +import org.jetbrains.jet.lang.resolve.java.CompilerDependencies; + +/** + * @author abreslav + */ +public class CompileEnvironmentConfiguration { + private final JetCoreEnvironment environment; + private final CompilerDependencies compilerDependencies; + private final MessageCollector messageCollector; + + /** + * NOTE: It's very important to call dispose for every object of this class or there will be memory leaks. + * @see Disposer + */ + public CompileEnvironmentConfiguration(@NotNull JetCoreEnvironment environment, + @NotNull CompilerDependencies compilerDependencies, @NotNull MessageCollector messageCollector) { + this.messageCollector = messageCollector; + this.compilerDependencies = compilerDependencies; + this.environment = environment; + } + + public JetCoreEnvironment getEnvironment() { + return environment; + } + + @NotNull + public CompilerDependencies getCompilerDependencies() { + return compilerDependencies; + } + + @NotNull + public MessageCollector getMessageCollector() { + return messageCollector; + } +} diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentUtil.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentUtil.java index eaf0af30966..97f882b486f 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentUtil.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileEnvironmentUtil.java @@ -51,9 +51,17 @@ import java.util.jar.*; * @author abreslav */ public class CompileEnvironmentUtil { + public static Disposable createMockDisposable() { + return new Disposable() { + @Override + public void dispose() { + } + }; + } + @Nullable public static File getUnpackedRuntimePath() { - URL url = CompileEnvironment.class.getClassLoader().getResource("jet/JetObject.class"); + URL url = CompileEnvironmentConfiguration.class.getClassLoader().getResource("jet/JetObject.class"); if (url != null && url.getProtocol().equals("file")) { return new File(url.getPath()).getParentFile().getParentFile(); } @@ -62,7 +70,7 @@ public class CompileEnvironmentUtil { @Nullable public static File getRuntimeJarPath() { - URL url = CompileEnvironment.class.getClassLoader().getResource("jet/JetObject.class"); + URL url = CompileEnvironmentConfiguration.class.getClassLoader().getResource("jet/JetObject.class"); if (url != null && url.getProtocol().equals("jar")) { String path = url.getPath(); return new File(path.substring(path.indexOf(":") + 1, path.indexOf("!/"))); @@ -187,7 +195,7 @@ public class CompileEnvironmentUtil { } } else { - loader = new GeneratedClassLoader(factory, CompileEnvironment.class.getClassLoader()); + loader = new GeneratedClassLoader(factory, CompileEnvironmentConfiguration.class.getClassLoader()); } try { Class namespaceClass = loader.loadClass(JvmAbi.PACKAGE_CLASS); @@ -301,4 +309,29 @@ public class CompileEnvironmentUtil { } } } + + /** + * Add path specified to the compilation environment. + * @param environment compilation environment to add to + * @param paths paths to add + */ + public static void addToClasspath(JetCoreEnvironment environment, File ... paths) { + for (File path : paths) { + if (!path.exists()) { + throw new CompileEnvironmentException("'" + path + "' does not exist"); + } + environment.addToClasspath(path); + } + } + + /** + * Add path specified to the compilation environment. + * @param environment compilation environment to add to + * @param paths paths to add + */ + public static void addToClasspath(JetCoreEnvironment environment, String ... paths) { + for (String path : paths) { + addToClasspath(environment, new File(path)); + } + } } diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java b/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java index ecc239820ad..a6055710614 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java @@ -25,12 +25,13 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiRecursiveElementWalkingVisitor; +import com.intellij.testFramework.LightVirtualFile; +import com.intellij.util.LocalTimeCounter; +import jet.modules.Module; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.analyzer.AnalyzeExhaust; -import org.jetbrains.jet.codegen.ClassBuilderFactories; -import org.jetbrains.jet.codegen.CompilationErrorHandler; -import org.jetbrains.jet.codegen.GenerationState; +import org.jetbrains.jet.codegen.*; import org.jetbrains.jet.compiler.messages.CompilerMessageLocation; import org.jetbrains.jet.compiler.messages.CompilerMessageSeverity; import org.jetbrains.jet.compiler.messages.MessageCollector; @@ -41,12 +42,20 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.diagnostics.Severity; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.FqName; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM; import org.jetbrains.jet.lang.resolve.java.CompilerDependencies; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; +import org.jetbrains.jet.plugin.JetLanguage; +import org.jetbrains.jet.plugin.JetMainDetector; import org.jetbrains.jet.utils.Progress; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.util.Collection; import java.util.List; @@ -56,6 +65,163 @@ import java.util.List; */ public class KotlinToJVMBytecodeCompiler { + @Nullable + public static ClassFileFactory compileModule( + CompileEnvironmentConfiguration configuration, + Module moduleBuilder, + String directory + ) { + if (moduleBuilder.getSourceFiles().isEmpty()) { + throw new CompileEnvironmentException("No source files where defined"); + } + + for (String sourceFile : moduleBuilder.getSourceFiles()) { + File source = new File(sourceFile); + if (!source.isAbsolute()) { + source = new File(directory, sourceFile); + } + + if (!source.exists()) { + throw new CompileEnvironmentException("'" + source + "' does not exist"); + } + + configuration.getEnvironment().addSources(source.getPath()); + } + for (String classpathRoot : moduleBuilder.getClasspathRoots()) { + configuration.getEnvironment().addToClasspath(new File(classpathRoot)); + } + + CompileEnvironmentUtil.ensureRuntime(configuration.getEnvironment(), configuration.getCompilerDependencies()); + + GenerationState generationState = analyzeAndGenerate(configuration); + if (generationState == null) { + return null; + } + return generationState.getFactory(); + } + + public static boolean compileModuleScript( + CompileEnvironmentConfiguration configuration, + + @NotNull String moduleScriptFile, + @Nullable String jarPath, + @Nullable String outputDir, + boolean jarRuntime) { + List modules = CompileEnvironmentUtil.loadModuleScript(moduleScriptFile, configuration.getMessageCollector()); + + if (modules == null) { + throw new CompileEnvironmentException("Module script " + moduleScriptFile + " compilation failed"); + } + + if (modules.isEmpty()) { + throw new CompileEnvironmentException("No modules where defined by " + moduleScriptFile); + } + + final String directory = new File(moduleScriptFile).getParent(); + for (Module moduleBuilder : modules) { + // TODO: this should be done only once for the environment + if (configuration.getCompilerDependencies().getRuntimeJar() != null) { + CompileEnvironmentUtil.addToClasspath(configuration.getEnvironment(), configuration.getCompilerDependencies().getRuntimeJar()); + } + ClassFileFactory moduleFactory = KotlinToJVMBytecodeCompiler.compileModule(configuration, moduleBuilder, directory); + if (moduleFactory == null) { + return false; + } + if (outputDir != null) { + CompileEnvironmentUtil.writeToOutputDirectory(moduleFactory, outputDir); + } + else { + String path = jarPath != null ? jarPath : new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(); + try { + CompileEnvironmentUtil.writeToJar(moduleFactory, new FileOutputStream(path), null, jarRuntime); + } + catch (FileNotFoundException e) { + throw new CompileEnvironmentException("Invalid jar path " + path, e); + } + } + } + return true; + } + + private static boolean compileBunchOfSources( + CompileEnvironmentConfiguration configuration, + + String jar, + String outputDir, + boolean includeRuntime + ) { + FqName mainClass = null; + for (JetFile file : configuration.getEnvironment().getSourceFiles()) { + if (JetMainDetector.hasMain(file.getDeclarations())) { + FqName fqName = JetPsiUtil.getFQName(file); + mainClass = fqName.child(JvmAbi.PACKAGE_CLASS); + break; + } + } + + CompileEnvironmentUtil.ensureRuntime(configuration.getEnvironment(), configuration.getCompilerDependencies()); + + GenerationState generationState = analyzeAndGenerate(configuration); + if (generationState == null) { + return false; + } + + ClassFileFactory factory = generationState.getFactory(); + if (jar != null) { + try { + CompileEnvironmentUtil.writeToJar(factory, new FileOutputStream(jar), mainClass, includeRuntime); + } catch (FileNotFoundException e) { + throw new CompileEnvironmentException("Invalid jar path " + jar, e); + } + } + else if (outputDir != null) { + CompileEnvironmentUtil.writeToOutputDirectory(factory, outputDir); + } + else { + throw new CompileEnvironmentException("Output directory or jar file is not specified - no files will be saved to the disk"); + } + return true; + } + + public static boolean compileBunchOfSources( + CompileEnvironmentConfiguration configuration, + + String sourceFileOrDir, String jar, String outputDir, boolean includeRuntime) { + configuration.getEnvironment().addSources(sourceFileOrDir); + + return compileBunchOfSources(configuration, jar, outputDir, includeRuntime); + } + + public static boolean compileBunchOfSourceDirectories( + CompileEnvironmentConfiguration configuration, + + List sources, String jar, String outputDir, boolean includeRuntime) { + for (String source : sources) { + configuration.getEnvironment().addSources(source); + } + + return compileBunchOfSources(configuration, jar, outputDir, includeRuntime); + } + + @Nullable + public static ClassLoader compileText( + CompileEnvironmentConfiguration configuration, + + String code) { + configuration.getEnvironment().addSources(new LightVirtualFile("script" + LocalTimeCounter.currentTime() + ".kt", JetLanguage.INSTANCE, code)); + + GenerationState generationState = analyzeAndGenerate(configuration); + if (generationState == null) { + return null; + } + return new GeneratedClassLoader(generationState.getFactory()); + } + + @Nullable + public static GenerationState analyzeAndGenerate(CompileEnvironmentConfiguration configuration) { + return analyzeAndGenerate(configuration.getEnvironment(), configuration.getCompilerDependencies(), configuration.getMessageCollector(), configuration.getCompilerDependencies().getCompilerSpecialMode().isStubs()); + } + @Nullable public static GenerationState analyzeAndGenerate( JetCoreEnvironment environment, diff --git a/compiler/tests/org/jetbrains/jet/codegen/CompileTextTest.java b/compiler/tests/org/jetbrains/jet/codegen/CompileTextTest.java index 84d8b82c38c..aacc2ca0d65 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/CompileTextTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/CompileTextTest.java @@ -17,8 +17,12 @@ package org.jetbrains.jet.codegen; import org.jetbrains.jet.CompileCompilerDependenciesTest; -import org.jetbrains.jet.compiler.CompileEnvironment; +import org.jetbrains.jet.compiler.CompileEnvironmentConfiguration; +import org.jetbrains.jet.compiler.CompileEnvironmentUtil; +import org.jetbrains.jet.compiler.JetCoreEnvironment; +import org.jetbrains.jet.compiler.KotlinToJVMBytecodeCompiler; import org.jetbrains.jet.compiler.messages.MessageCollector; +import org.jetbrains.jet.lang.resolve.java.CompilerDependencies; import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode; import java.lang.reflect.InvocationTargetException; @@ -27,9 +31,11 @@ import java.lang.reflect.Method; public class CompileTextTest extends CodegenTestCase { public void testMe() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { String text = "import org.jetbrains.jet.codegen.CompileTextTest; fun x() = CompileTextTest()"; - CompileEnvironment compileEnvironment = new CompileEnvironment(MessageCollector.PLAIN_TEXT_TO_SYSTEM_ERR, CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR)); - compileEnvironment.getEnvironment().addToClasspathFromClassLoader(getClass().getClassLoader()); - ClassLoader classLoader = compileEnvironment.compileText(text); + CompilerDependencies dependencies = CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR); + JetCoreEnvironment environment = new JetCoreEnvironment(CompileEnvironmentUtil.createMockDisposable(), dependencies); + CompileEnvironmentConfiguration configuration = new CompileEnvironmentConfiguration(environment, dependencies, MessageCollector.PLAIN_TEXT_TO_SYSTEM_ERR); + configuration.getEnvironment().addToClasspathFromClassLoader(getClass().getClassLoader()); + ClassLoader classLoader = KotlinToJVMBytecodeCompiler.compileText(configuration, text); Class namespace = classLoader.loadClass("namespace"); Method x = namespace.getDeclaredMethod("x"); Object invoke = x.invoke(null); diff --git a/compiler/tests/org/jetbrains/jet/codegen/StdlibTest.java b/compiler/tests/org/jetbrains/jet/codegen/StdlibTest.java index 20f6a1892d4..6e18a9aa08c 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/StdlibTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/StdlibTest.java @@ -17,8 +17,8 @@ package org.jetbrains.jet.codegen; import org.jetbrains.jet.codegen.forTestCompile.ForTestCompileRuntime; -import org.jetbrains.jet.compiler.CompileEnvironment; import org.jetbrains.jet.lang.psi.JetPsiUtil; +import org.junit.Test; import java.io.File; import java.lang.annotation.*; @@ -28,8 +28,6 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; -import org.junit.Test; - /** * @author alex.tkachman */