diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index 33bb005af93..b536dae92bf 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -170,4 +170,8 @@ public class GenerationState { return answer.toString(); } + + public void destroy() { + injector.destroy(); + } } diff --git a/compiler/backend/src/org/jetbrains/jet/di/InjectorForJetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/di/InjectorForJetTypeMapper.java index 91b6fb30cd6..0d0ec20975d 100644 --- a/compiler/backend/src/org/jetbrains/jet/di/InjectorForJetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/di/InjectorForJetTypeMapper.java @@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import java.util.List; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.annotations.NotNull; +import javax.annotation.PreDestroy; /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ public class InjectorForJetTypeMapper { @@ -70,6 +71,10 @@ public class InjectorForJetTypeMapper { } + @PreDestroy + public void destroy() { + } + public JetTypeMapper getJetTypeMapper() { return this.jetTypeMapper; } diff --git a/compiler/backend/src/org/jetbrains/jet/di/InjectorForJvmCodegen.java b/compiler/backend/src/org/jetbrains/jet/di/InjectorForJvmCodegen.java index 66f37743666..b5987e16532 100644 --- a/compiler/backend/src/org/jetbrains/jet/di/InjectorForJvmCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/di/InjectorForJvmCodegen.java @@ -40,6 +40,7 @@ import org.jetbrains.jet.codegen.ClassBuilderMode; import org.jetbrains.jet.codegen.GenerationState; import org.jetbrains.jet.codegen.ClassBuilderFactory; import org.jetbrains.annotations.NotNull; +import javax.annotation.PreDestroy; /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ public class InjectorForJvmCodegen { @@ -103,6 +104,10 @@ public class InjectorForJvmCodegen { } + @PreDestroy + public void destroy() { + } + public JetStandardLibrary getJetStandardLibrary() { return this.jetStandardLibrary; } diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java b/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java index 7e6af64de21..6eb3fd6ef21 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java @@ -165,21 +165,26 @@ public class KotlinToJVMBytecodeCompiler { 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); + try { + 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; } - else if (outputDir != null) { - CompileEnvironmentUtil.writeToOutputDirectory(factory, outputDir); + finally { + generationState.destroy(); } - 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( diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaSemanticServices.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaSemanticServices.java index 75416a327df..a3fe4e74de8 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaSemanticServices.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaSemanticServices.java @@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.resolve.NamespaceFactoryImpl; import org.jetbrains.jet.lang.resolve.java.CompilerDependencies; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; +import javax.annotation.PreDestroy; /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ public class InjectorForJavaSemanticServices { @@ -94,6 +95,10 @@ public class InjectorForJavaSemanticServices { } + @PreDestroy + public void destroy() { + } + public JavaSemanticServices getJavaSemanticServices() { return this.javaSemanticServices; } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java index 905f3536f98..69366baf299 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -55,6 +55,7 @@ import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.resolve.java.CompilerDependencies; import org.jetbrains.annotations.NotNull; +import javax.annotation.PreDestroy; /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ public class InjectorForTopDownAnalyzerForJvm { @@ -241,6 +242,10 @@ public class InjectorForTopDownAnalyzerForJvm { } + @PreDestroy + public void destroy() { + } + public TopDownAnalyzer getTopDownAnalyzer() { return this.topDownAnalyzer; } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java index 05fef231d78..97875e8ee8a 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java @@ -95,9 +95,13 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade { compilerDependencies); - injector.getTopDownAnalyzer().analyzeFiles(files); + try { + injector.getTopDownAnalyzer().analyzeFiles(files); - return AnalyzeExhaust.success(bindingTraceContext.getBindingContext(), JetStandardLibrary.getInstance()); + return AnalyzeExhaust.success(bindingTraceContext.getBindingContext(), JetStandardLibrary.getInstance()); + } finally { + injector.destroy(); + } } public static AnalyzeExhaust shallowAnalyzeFiles(Collection files, diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java index 2b9af7f3106..23020ab2793 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java @@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; +import javax.annotation.PreDestroy; /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ public class InjectorForMacros { @@ -75,6 +76,10 @@ public class InjectorForMacros { } + @PreDestroy + public void destroy() { + } + public ExpressionTypingServices getExpressionTypingServices() { return this.expressionTypingServices; } diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java index 68ebbd9692b..569ef4f592c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java @@ -49,6 +49,7 @@ import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.annotations.NotNull; +import javax.annotation.PreDestroy; /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ public class InjectorForTopDownAnalyzerBasic { @@ -198,6 +199,10 @@ public class InjectorForTopDownAnalyzerBasic { } + @PreDestroy + public void destroy() { + } + public TopDownAnalyzer getTopDownAnalyzer() { return this.topDownAnalyzer; } diff --git a/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java b/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java index a8286a6658f..165332e7d03 100644 --- a/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java +++ b/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java @@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; +import javax.annotation.PreDestroy; /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ public class InjectorForTests { @@ -78,6 +79,10 @@ public class InjectorForTests { } + @PreDestroy + public void destroy() { + } + public DescriptorResolver getDescriptorResolver() { return this.descriptorResolver; } diff --git a/injector-generator/src/org/jetbrains/jet/di/DependencyInjectorGenerator.java b/injector-generator/src/org/jetbrains/jet/di/DependencyInjectorGenerator.java index f5c8412a1fa..0faab5c25f8 100644 --- a/injector-generator/src/org/jetbrains/jet/di/DependencyInjectorGenerator.java +++ b/injector-generator/src/org/jetbrains/jet/di/DependencyInjectorGenerator.java @@ -27,10 +27,12 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; +import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -106,6 +108,8 @@ public class DependencyInjectorGenerator { out.println(); generateConstructor(injectorClassName, out); out.println(); + generateDestroy(injectorClassName, out); + out.println(); generateGetters(out); // Needed to fix double-checked locking // out.println(); @@ -212,6 +216,7 @@ public class DependencyInjectorGenerator { break; } } + generateImportDirective(out, PreDestroy.class, injectorPackageName); } private void generateImportDirectives(PrintStream out, DiType type, String injectorPackageName) { @@ -305,9 +310,17 @@ public class DependencyInjectorGenerator { } private static List getPostConstructMethods(Class clazz) { + return getInjectSpecialMethods(clazz, PostConstruct.class); + } + + private static List getPreDestroyMethods(Class clazz) { + return getInjectSpecialMethods(clazz, PreDestroy.class); + } + + private static List getInjectSpecialMethods(Class clazz, Class annotationClass) { List r = Lists.newArrayList(); for (Method method : clazz.getMethods()) { - if (method.getAnnotation(PostConstruct.class) != null) { + if (method.getAnnotation(annotationClass) != null) { if (method.getParameterTypes().length != 0) { throw new IllegalStateException("@PostConstruct method must have no arguments: " + method); } @@ -317,6 +330,22 @@ public class DependencyInjectorGenerator { return r; } + private void generateDestroy(@NotNull String injectorClassName, @NotNull PrintStream out) { + out.println(" @PreDestroy"); + out.println(" public void destroy() {"); + for (Field field : fields) { + // TODO: type of field may be different from type of object + List preDestroyMethods = getPreDestroyMethods(field.getType().getClazz()); + for (Method preDestroy : preDestroyMethods) { + out.println(" " + field.getName() + "." + preDestroy.getName() + "();"); + } + if (preDestroyMethods.size() > 0) { + out.println(); + } + } + out.println(" }"); + } + private void generateGetters(PrintStream out) { String indent0 = " "; String indent1 = indent0 + INDENT_STEP; diff --git a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java index 6fc0c64c61c..2eae6436681 100644 --- a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java +++ b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java @@ -49,6 +49,7 @@ import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.annotations.NotNull; +import javax.annotation.PreDestroy; /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ public class InjectorForTopDownAnalyzerForJs { @@ -198,6 +199,10 @@ public class InjectorForTopDownAnalyzerForJs { } + @PreDestroy + public void destroy() { + } + public TopDownAnalyzer getTopDownAnalyzer() { return this.topDownAnalyzer; }