From 651cc26e5e9956af7c003fddeac1c8e7eb89f2c7 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 23 Sep 2013 14:33:21 -0700 Subject: [PATCH] Test that injectors are properly generated --- .../injectors/GenerateInjectors.java | 76 ++++++++++++------- .../injectors/GenerateInjectorsTest.java | 38 ++++++++++ .../jet/di/DependencyInjectorGenerator.java | 38 ++++++++-- 3 files changed, 117 insertions(+), 35 deletions(-) create mode 100644 generators/tests/org/jetbrains/jet/generators/injectors/GenerateInjectorsTest.java diff --git a/generators/src/org/jetbrains/jet/generators/injectors/GenerateInjectors.java b/generators/src/org/jetbrains/jet/generators/injectors/GenerateInjectors.java index 6ab9fb0bce3..4f8fc478e0c 100644 --- a/generators/src/org/jetbrains/jet/generators/injectors/GenerateInjectors.java +++ b/generators/src/org/jetbrains/jet/generators/injectors/GenerateInjectors.java @@ -48,6 +48,8 @@ import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import java.io.IOException; +import java.util.Arrays; +import java.util.List; // NOTE: After making changes, you need to re-generate the injectors. // To do that, you can run either this class, or /build.xml/generateInjectors task @@ -57,18 +59,26 @@ public class GenerateInjectors { } public static void main(String[] args) throws IOException { - generateInjectorForTopDownAnalyzerBasic(); - generateInjectorForTopDownAnalyzerForJvm(); - generateInjectorForJavaDescriptorResolver(); - generateInjectorForTopDownAnalyzerForJs(); - generateMacroInjector(); - generateTestInjector(); - generateInjectorForJvmCodegen(); - generateInjectorForLazyResolve(); - generateInjectorForBodyResolve(); + for (DependencyInjectorGenerator generator : createGenerators()) { + generator.generate(); + } } - private static void generateInjectorForLazyResolve() throws IOException { + public static List createGenerators() throws IOException { + return Arrays.asList( + generateInjectorForTopDownAnalyzerBasic(), + generateInjectorForTopDownAnalyzerForJvm(), + generateInjectorForJavaDescriptorResolver(), + generateInjectorForTopDownAnalyzerForJs(), + generateMacroInjector(), + generateTestInjector(), + generateInjectorForJvmCodegen(), + generateInjectorForLazyResolve(), + generateInjectorForBodyResolve() + ); + } + + private static DependencyInjectorGenerator generateInjectorForLazyResolve() throws IOException { DependencyInjectorGenerator generator = new DependencyInjectorGenerator(); generator.addParameter(Project.class); generator.addParameter(ResolveSession.class); @@ -82,28 +92,31 @@ public class GenerateInjectors { generator.addPublicField(JetImportsFactory.class); generator.addField(NeedSyntheticCallResolverExtension.class); generator.addField(false, PlatformToKotlinClassMap.class, null, new GivenExpression("moduleDescriptor.getPlatformToKotlinClassMap()")); - generator.generate("compiler/frontend/src", "org.jetbrains.jet.di", "InjectorForLazyResolve", GenerateInjectors.class); + generator.configure("compiler/frontend/src", "org.jetbrains.jet.di", "InjectorForLazyResolve", GenerateInjectors.class); + return generator; } - private static void generateInjectorForTopDownAnalyzerBasic() throws IOException { + private static DependencyInjectorGenerator generateInjectorForTopDownAnalyzerBasic() throws IOException { DependencyInjectorGenerator generator = new DependencyInjectorGenerator(); generateInjectorForTopDownAnalyzerCommon(generator); generator.addField(DependencyClassByQualifiedNameResolverDummyImpl.class); generator.addField(NamespaceFactoryImpl.class); generator.addParameter(PlatformToKotlinClassMap.class); - generator.generate("compiler/frontend/src", "org.jetbrains.jet.di", "InjectorForTopDownAnalyzerBasic", GenerateInjectors.class); + generator.configure("compiler/frontend/src", "org.jetbrains.jet.di", "InjectorForTopDownAnalyzerBasic", GenerateInjectors.class); + return generator; } - private static void generateInjectorForTopDownAnalyzerForJs() throws IOException { + private static DependencyInjectorGenerator generateInjectorForTopDownAnalyzerForJs() throws IOException { DependencyInjectorGenerator generator = new DependencyInjectorGenerator(); generateInjectorForTopDownAnalyzerCommon(generator); generator.addField(DependencyClassByQualifiedNameResolverDummyImpl.class); generator.addField(NamespaceFactoryImpl.class); generator.addField(false, PlatformToKotlinClassMap.class, null, new GivenExpression("org.jetbrains.jet.lang.PlatformToKotlinClassMap.EMPTY")); - generator.generate("js/js.translator/src", "org.jetbrains.jet.di", "InjectorForTopDownAnalyzerForJs", GenerateInjectors.class); + generator.configure("js/js.translator/src", "org.jetbrains.jet.di", "InjectorForTopDownAnalyzerForJs", GenerateInjectors.class); + return generator; } - private static void generateInjectorForTopDownAnalyzerForJvm() throws IOException { + private static DependencyInjectorGenerator generateInjectorForTopDownAnalyzerForJvm() throws IOException { DependencyInjectorGenerator generator = new DependencyInjectorGenerator(); generator.implementInterface(InjectorForTopDownAnalyzer.class); generateInjectorForTopDownAnalyzerCommon(generator); @@ -121,11 +134,12 @@ public class GenerateInjectors { generator.addField(false, VirtualFileFinder.class, "virtualFileFinder", new GivenExpression( "com.intellij.openapi.components.ServiceManager.getService(project, VirtualFileFinder.class)")); - generator.generate("compiler/frontend.java/src", "org.jetbrains.jet.di", "InjectorForTopDownAnalyzerForJvm", + generator.configure("compiler/frontend.java/src", "org.jetbrains.jet.di", "InjectorForTopDownAnalyzerForJvm", GenerateInjectors.class); + return generator; } - private static void generateInjectorForJavaDescriptorResolver() throws IOException { + private static DependencyInjectorGenerator generateInjectorForJavaDescriptorResolver() throws IOException { DependencyInjectorGenerator generator = new DependencyInjectorGenerator(); // Parameters @@ -144,11 +158,12 @@ public class GenerateInjectors { generator.addField(false, VirtualFileFinder.class, "virtualFileFinder", new GivenExpression("com.intellij.openapi.components.ServiceManager.getService(project, VirtualFileFinder.class)")); - generator.generate("compiler/frontend.java/src", "org.jetbrains.jet.di", "InjectorForJavaDescriptorResolver", + generator.configure("compiler/frontend.java/src", "org.jetbrains.jet.di", "InjectorForJavaDescriptorResolver", GenerateInjectors.class); + return generator; } - private static void generateInjectorForTopDownAnalyzerCommon(DependencyInjectorGenerator generator) { + private static DependencyInjectorGenerator generateInjectorForTopDownAnalyzerCommon(DependencyInjectorGenerator generator) { // Fields generator.addPublicField(TopDownAnalyzer.class); generator.addPublicField(TopDownAnalysisContext.class); @@ -163,9 +178,10 @@ public class GenerateInjectors { generator.addPublicParameter(TopDownAnalysisParameters.class); generator.addPublicParameter(BindingTrace.class); generator.addPublicParameter(ModuleDescriptorImpl.class); + return generator; } - private static void generateMacroInjector() throws IOException { + private static DependencyInjectorGenerator generateMacroInjector() throws IOException { DependencyInjectorGenerator generator = new DependencyInjectorGenerator(); // Fields @@ -177,10 +193,11 @@ public class GenerateInjectors { generator.addPublicParameter(Project.class); generator.addParameter(ModuleDescriptor.class); - generator.generate("compiler/frontend/src", "org.jetbrains.jet.di", "InjectorForMacros", GenerateInjectors.class); + generator.configure("compiler/frontend/src", "org.jetbrains.jet.di", "InjectorForMacros", GenerateInjectors.class); + return generator; } - private static void generateTestInjector() throws IOException { + private static DependencyInjectorGenerator generateTestInjector() throws IOException { DependencyInjectorGenerator generator = new DependencyInjectorGenerator(); // Fields @@ -196,10 +213,11 @@ public class GenerateInjectors { generator.addPublicParameter(Project.class); generator.addParameter(ModuleDescriptor.class); - generator.generate("compiler/tests", "org.jetbrains.jet.di", "InjectorForTests", GenerateInjectors.class); + generator.configure("compiler/tests", "org.jetbrains.jet.di", "InjectorForTests", GenerateInjectors.class); + return generator; } - private static void generateInjectorForJvmCodegen() throws IOException { + private static DependencyInjectorGenerator generateInjectorForJvmCodegen() throws IOException { DependencyInjectorGenerator generator = new DependencyInjectorGenerator(); // Parameters @@ -219,10 +237,11 @@ public class GenerateInjectors { generator.addField(true, IntrinsicMethods.class, "intrinsics", null); generator.addPublicField(ClassFileFactory.class); - generator.generate("compiler/backend/src", "org.jetbrains.jet.di", "InjectorForJvmCodegen", GenerateInjectors.class); + generator.configure("compiler/backend/src", "org.jetbrains.jet.di", "InjectorForJvmCodegen", GenerateInjectors.class); + return generator; } - private static void generateInjectorForBodyResolve() throws IOException { + private static DependencyInjectorGenerator generateInjectorForBodyResolve() throws IOException { DependencyInjectorGenerator generator = new DependencyInjectorGenerator(); // Fields generator.addPublicField(BodyResolver.class); @@ -235,6 +254,7 @@ public class GenerateInjectors { generator.addPublicParameter(BindingTrace.class); generator.addPublicParameter(BodiesResolveContext.class); generator.addParameter(ModuleDescriptor.class); - generator.generate("compiler/frontend/src", "org.jetbrains.jet.di", "InjectorForBodyResolve", GenerateInjectors.class); + generator.configure("compiler/frontend/src", "org.jetbrains.jet.di", "InjectorForBodyResolve", GenerateInjectors.class); + return generator; } } diff --git a/generators/tests/org/jetbrains/jet/generators/injectors/GenerateInjectorsTest.java b/generators/tests/org/jetbrains/jet/generators/injectors/GenerateInjectorsTest.java new file mode 100644 index 00000000000..9981850f251 --- /dev/null +++ b/generators/tests/org/jetbrains/jet/generators/injectors/GenerateInjectorsTest.java @@ -0,0 +1,38 @@ +package org.jetbrains.jet.generators.injectors; + +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import junit.framework.Assert; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import org.jetbrains.jet.di.DependencyInjectorGenerator; + +import java.io.IOException; + +@SuppressWarnings({"JUnitTestCaseWithNoTests", "JUnitTestCaseWithNonTrivialConstructors"}) +public class GenerateInjectorsTest extends TestCase { + + private final DependencyInjectorGenerator generator; + + public GenerateInjectorsTest(DependencyInjectorGenerator generator) { + super(generator.getInjectorClassName()); + this.generator = generator; + } + + @Override + protected void runTest() throws Throwable { + CharSequence text = generator.generateText(); + String expected = FileUtil.loadFile(generator.getOutputFile(), true); + String expectedText = StringUtil.convertLineSeparators(expected.trim()); + String actualText = StringUtil.convertLineSeparators(text.toString().trim()); + Assert.assertEquals("To fix this problem you need to run GenerateInjectors", expectedText, actualText); + } + + public static TestSuite suite() throws IOException { + TestSuite suite = new TestSuite(); + for (DependencyInjectorGenerator generator : GenerateInjectors.createGenerators()) { + suite.addTest(new GenerateInjectorsTest(generator)); + } + return suite; + } +} diff --git a/injector-generator/src/org/jetbrains/jet/di/DependencyInjectorGenerator.java b/injector-generator/src/org/jetbrains/jet/di/DependencyInjectorGenerator.java index 7dfe8f13452..4051036af1b 100644 --- a/injector-generator/src/org/jetbrains/jet/di/DependencyInjectorGenerator.java +++ b/injector-generator/src/org/jetbrains/jet/di/DependencyInjectorGenerator.java @@ -43,14 +43,39 @@ public class DependencyInjectorGenerator { private final ImportManager importManager = new ImportManager(); + private String targetSourceRoot; + private String injectorPackageName; + private String injectorClassName; + private Class generatorClass; + public DependencyInjectorGenerator() { } - public void generate(String targetSourceRoot, String injectorPackageName, String injectorClassName, Class generatorClass) - throws IOException { - String outputFileName = targetSourceRoot + "/" + injectorPackageName.replace(".", "/") + "/" + injectorClassName + ".java"; + public String getInjectorClassName() { + return injectorClassName; + } - File file = new File(outputFileName); + public DependencyInjectorGenerator configure(String targetSourceRoot, String injectorPackageName, String injectorClassName, Class generatorClass) { + this.targetSourceRoot = targetSourceRoot; + this.injectorPackageName = injectorPackageName; + this.injectorClassName = injectorClassName; + this.generatorClass = generatorClass; + return this; + } + + public void generate() throws IOException { + assert targetSourceRoot != null : "Don't forget to call configure()"; + + GeneratorsFileUtil.writeFileIfContentChanged(getOutputFile(), generateText().toString()); + } + + public File getOutputFile() { + String outputFileName = targetSourceRoot + "/" + injectorPackageName.replace(".", "/") + "/" + injectorClassName + ".java"; + return new File(outputFileName); + } + + public CharSequence generateText() throws IOException { + assert generatorClass != null : "Don't forget to call configure()"; fields.addAll(dependencies.satisfyDependencies()); reportUnusedParameters(injectorPackageName, injectorClassName); @@ -80,7 +105,7 @@ public class DependencyInjectorGenerator { p.popIndent(); p.println("}"); // class - importManager.addClass(org.jetbrains.annotations.NotNull.class); + importManager.addClass(NotNull.class); importManager.addClass(javax.annotation.PreDestroy.class); StringBuilder imports = new StringBuilder(); generateImports(new Printer(imports), injectorPackageName); @@ -88,8 +113,7 @@ public class DependencyInjectorGenerator { StringBuilder text = new StringBuilder(preamble); text.append(imports); text.append(body); - - GeneratorsFileUtil.writeFileIfContentChanged(file, text.toString()); + return text; } private void reportUnusedParameters(String injectorPackageName, String injectorClassName) {