From 578745290f3abdbc824fbf077e110f29b9446879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20Nicolas?= Date: Tue, 12 Apr 2016 18:40:20 -0700 Subject: [PATCH 1/7] Make factories use directly member injectors. --- .../factory/generators/FactoryGenerator.java | 12 ++-- .../compiler/factory/FactoryTest.java | 68 ++++++++++++------- .../factory/ProcessorTestUtilities.java | 5 ++ 3 files changed, 53 insertions(+), 32 deletions(-) diff --git a/toothpick-compiler/src/main/java/toothpick/compiler/factory/generators/FactoryGenerator.java b/toothpick-compiler/src/main/java/toothpick/compiler/factory/generators/FactoryGenerator.java index 8d4819a5..992236c7 100644 --- a/toothpick-compiler/src/main/java/toothpick/compiler/factory/generators/FactoryGenerator.java +++ b/toothpick-compiler/src/main/java/toothpick/compiler/factory/generators/FactoryGenerator.java @@ -46,7 +46,8 @@ public String brewJava() { return javaFile.toString(); } - @Override public String getFqcn() { + @Override + public String getFqcn() { return factoryInjectionTarget.builtClass.getQualifiedName().toString() + FACTORY_SUFFIX; } @@ -80,14 +81,9 @@ private void emitCreateInstance(TypeSpec.Builder builder) { localVarStatement.append(")"); createInstanceBuilder.addStatement(localVarStatement.toString()); if (factoryInjectionTarget.needsMemberInjection) { - StringBuilder injectStatement = new StringBuilder("injector.inject("); - injectStatement.append(varName); - injectStatement.append(")"); - createInstanceBuilder.addStatement(injectStatement.toString()); + createInstanceBuilder.addStatement("new $L$$$$MemberInjector().inject($L, injector)", className, varName); } - StringBuilder returnStatement = new StringBuilder("return "); - returnStatement.append(varName); - createInstanceBuilder.addStatement(returnStatement.toString()); + createInstanceBuilder.addStatement("return $L", varName); builder.addMethod(createInstanceBuilder.build()); } diff --git a/toothpick-compiler/src/test/java/toothpick/compiler/factory/FactoryTest.java b/toothpick-compiler/src/test/java/toothpick/compiler/factory/FactoryTest.java index e551ccb0..17a632b1 100644 --- a/toothpick-compiler/src/test/java/toothpick/compiler/factory/FactoryTest.java +++ b/toothpick-compiler/src/test/java/toothpick/compiler/factory/FactoryTest.java @@ -13,7 +13,8 @@ import static org.junit.Assert.fail; public class FactoryTest { - @Test public void testEmptyConstructor() { + @Test + public void testEmptyConstructor() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestEmptyConstructor", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -53,7 +54,8 @@ public class FactoryTest { .generatesSources(expectedSource); } - @Test public void testPrivateConstructor() { + @Test + public void testPrivateConstructor() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestPrivateConstructor", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -69,7 +71,8 @@ public class FactoryTest { .withErrorContaining("@Inject constructors must not be private in class test.TestPrivateConstructor"); } - @Test public void testInjectedConstructorInPrivateClass() { + @Test + public void testInjectedConstructorInPrivateClass() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestConstructorInPrivateClass", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -85,7 +88,8 @@ public class FactoryTest { .withErrorContaining("Class test.TestConstructorInPrivateClass is private. @Inject constructors are not allowed in non public classes."); } - @Test public void test2InjectedConstructors() { + @Test + public void test2InjectedConstructors() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestPrivateConstructor", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -102,7 +106,8 @@ public class FactoryTest { .withErrorContaining("Class test.TestPrivateConstructor cannot have more than one @Inject annotated constructor."); } - @Test public void testAClassThatNeedsInjection_withAnInjectedField() { + @Test + public void testAClassThatNeedsInjection_withAnInjectedField() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestAClassThatNeedsInjection", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -122,7 +127,7 @@ public class FactoryTest { " @Override", // " public TestAClassThatNeedsInjection createInstance(Injector injector) {", // " TestAClassThatNeedsInjection testAClassThatNeedsInjection = new TestAClassThatNeedsInjection();", // - " injector.inject(testAClassThatNeedsInjection);", // + " new test.TestAClassThatNeedsInjection$$MemberInjector().inject(testAClassThatNeedsInjection, injector);", // " return testAClassThatNeedsInjection;", // " }", // " @Override", // @@ -138,13 +143,14 @@ public class FactoryTest { assert_().about(javaSource()) .that(source) - .processedWith(ProcessorTestUtilities.factoryProcessors()) + .processedWith(ProcessorTestUtilities.factoryAndMemberInjectorProcessors()) .compilesWithoutError() .and() .generatesSources(expectedSource); } - @Test public void testAClassThatNeedsInjection_withAnInjectedMethod() { + @Test + public void testAClassThatNeedsInjection_withAnInjectedMethod() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestAClassThatNeedsInjection", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -164,7 +170,7 @@ public class FactoryTest { " @Override", // " public TestAClassThatNeedsInjection createInstance(Injector injector) {", // " TestAClassThatNeedsInjection testAClassThatNeedsInjection = new TestAClassThatNeedsInjection();", // - " injector.inject(testAClassThatNeedsInjection);", // + " new test.TestAClassThatNeedsInjection$$MemberInjector().inject(testAClassThatNeedsInjection, injector);", // " return testAClassThatNeedsInjection;", // " }", // " @Override", // @@ -180,13 +186,14 @@ public class FactoryTest { assert_().about(javaSource()) .that(source) - .processedWith(ProcessorTestUtilities.factoryProcessors()) + .processedWith(ProcessorTestUtilities.factoryAndMemberInjectorProcessors()) .compilesWithoutError() .and() .generatesSources(expectedSource); } - @Test public void testNonEmptyConstructor() { + @Test + public void testNonEmptyConstructor() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestNonEmptyConstructor", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -230,7 +237,8 @@ public class FactoryTest { .generatesSources(expectedSource); } - @Test public void testInvalidClassConstructor() { + @Test + public void testInvalidClassConstructor() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestInvalidClassConstructor", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -242,7 +250,8 @@ public class FactoryTest { assertThatCompileWithoutErrorButNoFactoryIsNotCreated(source, "test", "TestAbstractClassConstructor"); } - @Test public void testSingletonAnnotation() { + @Test + public void testSingletonAnnotation() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestNonEmptyConstructor", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -288,7 +297,8 @@ public class FactoryTest { .generatesSources(expectedSource); } - @Test public void testProducesSingletonAnnotation() { + @Test + public void testProducesSingletonAnnotation() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestNonEmptyConstructor", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -334,7 +344,8 @@ public class FactoryTest { .generatesSources(expectedSource); } - @Test public void testOptimisticFactoryCreationForInjectedField() { + @Test + public void testOptimisticFactoryCreationForInjectedField() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestOptimisticFactoryCreationForInjectedField", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -353,7 +364,8 @@ public class FactoryTest { .generatesFileNamed(StandardLocation.locationFor("CLASS_OUTPUT"), "test", "Foo$$Factory.class"); } - @Test public void testOptimisticFactoryCreationForInjectedField_shouldFail_WhenFieldIsInvalid() { + @Test + public void testOptimisticFactoryCreationForInjectedField_shouldFail_WhenFieldIsInvalid() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestOptimisticFactoryCreationForInjectedField", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -371,7 +383,8 @@ public class FactoryTest { .withErrorContaining("@Inject annotated fields must be non private : test.TestOptimisticFactoryCreationForInjectedField.foo"); } - @Test public void testOptimisticFactoryCreationForInjectedField_shouldWorkButNoFactoryIsProduced_whenTypeIsAbstract() { + @Test + public void testOptimisticFactoryCreationForInjectedField_shouldWorkButNoFactoryIsProduced_whenTypeIsAbstract() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestOptimisticFactoryCreationForInjectedField", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -385,7 +398,8 @@ public class FactoryTest { assertThatCompileWithoutErrorButNoFactoryIsNotCreated(source, "test", "Foo"); } - @Test public void testOptimisticFactoryCreationForInjectedField_shouldWorkButNoFactoryIsProduced_whenTypeHasANonDefaultConstructor() { + @Test + public void testOptimisticFactoryCreationForInjectedField_shouldWorkButNoFactoryIsProduced_whenTypeHasANonDefaultConstructor() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestOptimisticFactoryCreationForInjectedField", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -401,7 +415,8 @@ public class FactoryTest { assertThatCompileWithoutErrorButNoFactoryIsNotCreated(source, "test", "Foo"); } - @Test public void testOptimisticFactoryCreationForInjectedField_shouldWorkButNoFactoryIsProduced_whenTypeHasAPrivateDefaultConstructor() { + @Test + public void testOptimisticFactoryCreationForInjectedField_shouldWorkButNoFactoryIsProduced_whenTypeHasAPrivateDefaultConstructor() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestOptimisticFactoryCreationForInjectedField", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -417,7 +432,8 @@ public class FactoryTest { assertThatCompileWithoutErrorButNoFactoryIsNotCreated(source, "test", "Foo"); } - @Test public void testOptimisticFactoryCreationForInjectedMethod() { + @Test + public void testOptimisticFactoryCreationForInjectedMethod() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestOptimisticFactoryCreationForInjectedMethod", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -436,7 +452,8 @@ public class FactoryTest { .generatesFileNamed(StandardLocation.locationFor("CLASS_OUTPUT"), "test", "Foo$$Factory.class"); } - @Test public void testOptimisticFactoryCreationForInjectedMethod_shouldWorkButNoFactoryIsProduced_whenTypeIsPrivate() { + @Test + public void testOptimisticFactoryCreationForInjectedMethod_shouldWorkButNoFactoryIsProduced_whenTypeIsPrivate() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestOptimisticFactoryCreationForInjectedMethod", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -450,7 +467,8 @@ public class FactoryTest { assertThatCompileWithoutErrorButNoFactoryIsNotCreated(source, "test", "Foo"); } - @Test public void testOptimisticFactoryCreationForInjectedMethod_shouldFail_whenMethodIsInvalid() { + @Test + public void testOptimisticFactoryCreationForInjectedMethod_shouldFail_whenMethodIsInvalid() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestOptimisticFactoryCreationForInjectedMethod", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -468,7 +486,8 @@ public class FactoryTest { .withErrorContaining("@Inject annotated methods must not be private : test.TestOptimisticFactoryCreationForInjectedMethod.m"); } - @Test public void testOptimisticFactoryCreationForInjectedConstructor() { + @Test + public void testOptimisticFactoryCreationForInjectedConstructor() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestOptimisticFactoryCreationForInjectedConstructor", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -487,7 +506,8 @@ public class FactoryTest { .generatesFileNamed(StandardLocation.locationFor("CLASS_OUTPUT"), "test", "Foo$$Factory.class"); } - @Test public void testOptimisticFactoryCreationForInjectedConstructor_shouldWorkButNoFactoryIsProduced_whenTypeIsInterface() { + @Test + public void testOptimisticFactoryCreationForInjectedConstructor_shouldWorkButNoFactoryIsProduced_whenTypeIsInterface() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestOptimisticFactoryCreationForInjectedConstructor", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // diff --git a/toothpick-compiler/src/test/java/toothpick/compiler/factory/ProcessorTestUtilities.java b/toothpick-compiler/src/test/java/toothpick/compiler/factory/ProcessorTestUtilities.java index ce95a71c..5cbafcc1 100644 --- a/toothpick-compiler/src/test/java/toothpick/compiler/factory/ProcessorTestUtilities.java +++ b/toothpick-compiler/src/test/java/toothpick/compiler/factory/ProcessorTestUtilities.java @@ -3,6 +3,7 @@ import java.util.Arrays; import java.util.List; import javax.annotation.processing.Processor; +import toothpick.compiler.memberinjector.MemberInjectorProcessor; final class ProcessorTestUtilities { private ProcessorTestUtilities() { @@ -12,6 +13,10 @@ static Iterable factoryProcessors() { return Arrays.asList(new FactoryProcessor()); } + static Iterable factoryAndMemberInjectorProcessors() { + return Arrays.asList(new MemberInjectorProcessor(), new FactoryProcessor()); + } + static Iterable factoryProcessors(String toothpickRegistryPackageName, List toothpickRegistryChildrenPackageNameList) { FactoryProcessor factoryProcessor = new FactoryProcessor(); factoryProcessor.setToothpickRegistryPackageName(toothpickRegistryPackageName); From 46fac47e134c1462017f5c63e700ea8a6917ea2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20Nicolas?= Date: Tue, 12 Apr 2016 18:49:02 -0700 Subject: [PATCH 2/7] Make member injectors use directly super member injectors. --- .../generators/MemberInjectorGenerator.java | 6 ++--- .../FieldMemberInjectorTest.java | 25 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/generators/MemberInjectorGenerator.java b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/generators/MemberInjectorGenerator.java index 2ed74403..99dbc4e9 100644 --- a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/generators/MemberInjectorGenerator.java +++ b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/generators/MemberInjectorGenerator.java @@ -67,8 +67,7 @@ private void emitSuperMemberInjectorFieldIfNeeded(TypeSpec.Builder injectorMembe FieldSpec.Builder superMemberInjectorField = FieldSpec.builder(memberInjectorSuperParameterizedTypeName, "superMemberInjector", Modifier.PRIVATE) //TODO use proper typing here - .initializer("$T.getMemberInjector($L.class)", ClassName.get("toothpick.registries.memberinjector", "MemberInjectorRegistryLocator"), - superTypeThatNeedsInjection.simpleName()); + .initializer("new $L$$$$MemberInjector()", superTypeThatNeedsInjection); injectorMemberTypeSpec.addField(superMemberInjectorField.build()); } } @@ -150,7 +149,8 @@ private void emitInjectFields(List fieldInjectionTargetLis } } - @Override public String getFqcn() { + @Override + public String getFqcn() { return targetClass.getQualifiedName().toString() + MEMBER_INJECTOR_SUFFIX; } } diff --git a/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/FieldMemberInjectorTest.java b/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/FieldMemberInjectorTest.java index 4198e155..012c0df4 100644 --- a/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/FieldMemberInjectorTest.java +++ b/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/FieldMemberInjectorTest.java @@ -10,7 +10,8 @@ import static toothpick.compiler.memberinjector.ProcessorTestUtilities.memberInjectorProcessors; public class FieldMemberInjectorTest { - @Test public void testSimpleFieldInjection() { + @Test + public void testSimpleFieldInjection() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestFieldInjection", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -44,7 +45,8 @@ public class FieldMemberInjectorTest { .generatesSources(expectedSource); } - @Test public void testProviderFieldInjection() { + @Test + public void testProviderFieldInjection() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestFieldInjection", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -79,7 +81,8 @@ public class FieldMemberInjectorTest { .generatesSources(expectedSource); } - @Test public void testLazyFieldInjection() { + @Test + public void testLazyFieldInjection() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestFieldInjection", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -114,7 +117,8 @@ public class FieldMemberInjectorTest { .generatesSources(expectedSource); } - @Test public void testFutureFieldInjection() { + @Test + public void testFutureFieldInjection() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestFieldInjection", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -149,7 +153,8 @@ public class FieldMemberInjectorTest { .generatesSources(expectedSource); } - @Test public void testFieldInjection_shouldProduceMemberInjector_whenClassHas2Fields() { + @Test + public void testFieldInjection_shouldProduceMemberInjector_whenClassHas2Fields() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestFieldInjection", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -185,7 +190,8 @@ public class FieldMemberInjectorTest { .generatesSources(expectedSource); } - @Test public void testFieldInjection_shouldFail_whenFieldIsPrivate() { + @Test + public void testFieldInjection_shouldFail_whenFieldIsPrivate() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestFieldInjection", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -203,7 +209,8 @@ public class FieldMemberInjectorTest { .withErrorContaining("@Inject annotated fields must be non private : test.TestFieldInjection.foo"); } - @Test public void testMemberInjection_shouldInjectAsAnInstanceOfSuperClass_whenSuperClassHasInjectedMembers() { + @Test + public void testMemberInjection_shouldInjectAsAnInstanceOfSuperClass_whenSuperClassHasInjectedMembers() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestMemberInjection", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -222,11 +229,9 @@ public class FieldMemberInjectorTest { "import java.lang.Override;", // "import toothpick.Injector;", // "import toothpick.MemberInjector;", // - "import toothpick.registries.memberinjector.MemberInjectorRegistryLocator;", // "", // "public final class TestMemberInjection$$MemberInjector implements MemberInjector {", // - " private MemberInjector superMemberInjector " - + "= MemberInjectorRegistryLocator.getMemberInjector(TestMemberInjectionParent.class);", + " private MemberInjector superMemberInjector " + "= new test.TestMemberInjectionParent$$MemberInjector();", // " @Override", // " public void inject(TestMemberInjection target, Injector injector) {", // From 9b72b737ad4bd0c72cd77618efcaef2bae04fd4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20Nicolas?= Date: Tue, 12 Apr 2016 21:37:02 -0700 Subject: [PATCH 3/7] Move to scope works and tested --- .../example/smoothie/LessSimpleActivity.java | 16 +- .../com/example/smoothie/PersistActivity.java | 26 ++- .../com/example/smoothie/SimpleActivity.java | 16 +- .../java/com/example/smoothie/SimpleApp.java | 6 +- .../example/smoothie/deps/ContextNamer.java | 5 - .../example/smoothie/SimpleActivityTest.java | 6 +- .../compiler/ToothpickProcessor.java | 6 +- .../compiler/factory/FactoryProcessor.java | 2 +- .../factory/generators/FactoryGenerator.java | 8 +- .../MemberInjectorProcessor.java | 16 +- .../generators/MemberInjectorGenerator.java | 54 ++--- .../MemberInjectorRegistryGenerator.java | 11 +- .../targets/FieldInjectionTarget.java | 2 +- ...MemberInjectorRegistryInjectionTarget.java | 2 +- .../targets/MethodInjectionTarget.java | 2 +- .../javax.annotation.processing.Processor | 2 +- .../compiler/factory/FactoryTest.java | 40 ++-- .../factory/ProcessorTestUtilities.java | 2 +- .../FieldMemberInjectorTest.java | 44 ++-- .../MemberInjectorRegistryTest.java | 16 +- .../MethodMemberInjectorTest.java | 16 +- .../ProcessorTestUtilities.java | 2 +- .../AbstractMemberInjectorRegistry.java | 6 +- .../MemberInjectorRegistryLocator.java | 2 +- .../ReflectionMemberInjectorRegistry.java | 8 +- .../src/main/java/toothpick/InjectorImpl.java | 162 +------------ .../src/main/java/toothpick/ProviderImpl.java | 18 +- .../src/main/java/toothpick/ScopeImpl.java | 156 +++++++++++++ .../src/main/java/toothpick/ToothPick.java | 41 ++-- ...jectorImplTest.java => ScopeImplTest.java} | 34 +-- .../java/toothpick/ToothPickBaseTest.java | 5 +- .../test/java/toothpick/ToothPickTest.java | 80 +++---- .../toothpick/bindings/AllBindingsTest.java | 84 +++---- .../SimpleInstanceCreationWithModuleTest.java | 20 +- ...mpleInstanceCreationWithoutModuleTest.java | 14 +- .../SingletonCreationWithModuleTest.java | 13 +- .../SingletonCreationWithoutModuleTest.java | 10 +- ...CreatedInstancesAreInjectedWhenNeeded.java | 28 +-- .../inject/InjectionAndInheritanceTest.java | 13 +- .../inject/InjectionWithoutModuleTest.java | 9 +- .../future/InjectionOfFutureProviderTest.java | 9 +- .../lazy/InjectionOfLazyProviderTest.java | 9 +- .../provider/InjectionOfProviderTest.java | 13 +- .../java/toothpick/scoping/ScopingTest.java | 38 +-- .../toothpick/sample/SimpleEntryPoint.java | 6 +- .../java/toothpick/sample/ComputerTest.java | 4 +- .../sample/SimpleEntryPointTest.java | 8 +- .../src/main/java/toothpick/Factory.java | 4 +- .../src/main/java/toothpick/Injector.java | 221 +----------------- .../main/java/toothpick/MemberInjector.java | 8 +- toothpick/src/main/java/toothpick/Scope.java | 218 +++++++++++++++++ 51 files changed, 783 insertions(+), 758 deletions(-) create mode 100644 toothpick-runtime/src/main/java/toothpick/ScopeImpl.java rename toothpick-runtime/src/test/java/toothpick/{InjectorImplTest.java => ScopeImplTest.java} (67%) create mode 100644 toothpick/src/main/java/toothpick/Scope.java diff --git a/smoothie-sample/src/main/java/com/example/smoothie/LessSimpleActivity.java b/smoothie-sample/src/main/java/com/example/smoothie/LessSimpleActivity.java index ff4bd7fe..a1c3ca09 100644 --- a/smoothie-sample/src/main/java/com/example/smoothie/LessSimpleActivity.java +++ b/smoothie-sample/src/main/java/com/example/smoothie/LessSimpleActivity.java @@ -12,7 +12,7 @@ import butterknife.ButterKnife; import com.example.smoothie.deps.ContextNamer; import javax.inject.Inject; -import toothpick.Injector; +import toothpick.Scope; import toothpick.ToothPick; import toothpick.smoothie.module.DefaultActivityModule; @@ -24,7 +24,7 @@ public class LessSimpleActivity extends Activity { @Inject AlarmManager alarmManager; @Inject FragmentManager fragmentManager; @Inject Activity activity; - private Injector injector; + private Scope scope; @Inject ContextNamer contextNamer; @Bind(R.id.title) TextView title; @@ -33,11 +33,11 @@ public class LessSimpleActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Injector appInjector = ToothPick.openInjector(getApplication()); - injector = ToothPick.openInjector(this); - injector.installModules(new DefaultActivityModule(this)); - appInjector.addChild(injector); - injector.inject(this); + Scope appScope = ToothPick.openScope(getApplication()); + scope = ToothPick.openScope(this); + scope.installModules(new DefaultActivityModule(this)); + appScope.addChild(scope); + ToothPick.inject(this, scope); setContentView(R.layout.simple_activity); ButterKnife.bind(this); title.setText(contextNamer.getApplicationName()); @@ -46,7 +46,7 @@ protected void onCreate(Bundle savedInstanceState) { @Override protected void onDestroy() { - ToothPick.closeInjector(this); + ToothPick.closeScope(this); super.onDestroy(); } } \ No newline at end of file diff --git a/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java b/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java index 021d0675..f2a07cc1 100644 --- a/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java +++ b/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java @@ -9,7 +9,7 @@ import butterknife.ButterKnife; import com.example.smoothie.deps.ContextNamer; import javax.inject.Inject; -import toothpick.Injector; +import toothpick.Scope; import toothpick.ToothPick; import toothpick.config.Module; import toothpick.smoothie.module.DefaultActivityModule; @@ -17,7 +17,7 @@ public class PersistActivity extends Activity { public static final String PRESENTER_SCOPE = "PRESENTER_SCOPE"; - private Injector injector; + private Scope scope; @Inject ContextNamer contextNamer; @Bind(R.id.title) TextView title; @@ -27,14 +27,16 @@ public class PersistActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Injector appInjector = ToothPick.openInjector(getApplication()); - Injector metaInjector = ToothPick.openInjector(PRESENTER_SCOPE); - appInjector.addChild(metaInjector); - injector = ToothPick.openInjector(this); - metaInjector.addChild(injector); - injector.installModules(new DefaultActivityModule(this)); - injector.inject(this); - metaInjector.installModules(new PresenterModule()); + + Scope appScope = ToothPick.openScope(getApplication()); + Scope metaScope = ToothPick.openScope(PRESENTER_SCOPE); + appScope.addChild(metaScope); + scope = ToothPick.openScope(this); + metaScope.addChild(scope); + scope.installModules(new DefaultActivityModule(this)); + ToothPick.inject(this, scope); + metaScope.installModules(new PresenterModule()); + setContentView(R.layout.simple_activity); ButterKnife.bind(this); title.setText("Persist"); @@ -44,13 +46,13 @@ protected void onCreate(Bundle savedInstanceState) { @Override protected void onDestroy() { - ToothPick.closeInjector(this); + ToothPick.closeScope(this); super.onDestroy(); } @Override public void onBackPressed() { - ToothPick.closeInjector(PRESENTER_SCOPE); + ToothPick.closeScope(PRESENTER_SCOPE); super.onBackPressed(); } diff --git a/smoothie-sample/src/main/java/com/example/smoothie/SimpleActivity.java b/smoothie-sample/src/main/java/com/example/smoothie/SimpleActivity.java index 52eac0c5..c2a0f960 100644 --- a/smoothie-sample/src/main/java/com/example/smoothie/SimpleActivity.java +++ b/smoothie-sample/src/main/java/com/example/smoothie/SimpleActivity.java @@ -10,13 +10,13 @@ import butterknife.OnClick; import com.example.smoothie.deps.ContextNamer; import javax.inject.Inject; -import toothpick.Injector; +import toothpick.Scope; import toothpick.ToothPick; import toothpick.smoothie.module.DefaultActivityModule; public class SimpleActivity extends Activity { - private Injector injector; + private Scope scope; @Inject ContextNamer contextNamer; @Bind(R.id.title) TextView title; @@ -26,11 +26,11 @@ public class SimpleActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Injector appInjector = ToothPick.openInjector(getApplication()); - injector = ToothPick.openInjector(this); - injector.installModules(new DefaultActivityModule(this)); - appInjector.addChild(injector); - injector.inject(this); + Scope appScope = ToothPick.openScope(getApplication()); + scope = ToothPick.openScope(this); + scope.installModules(new DefaultActivityModule(this)); + appScope.addChild(scope); + ToothPick.inject(this, scope); setContentView(R.layout.simple_activity); ButterKnife.bind(this); title.setText(contextNamer.getApplicationName()); @@ -46,7 +46,7 @@ void startNewActivity() { @Override protected void onDestroy() { - ToothPick.closeInjector(this); + ToothPick.closeScope(this); super.onDestroy(); } } \ No newline at end of file diff --git a/smoothie-sample/src/main/java/com/example/smoothie/SimpleApp.java b/smoothie-sample/src/main/java/com/example/smoothie/SimpleApp.java index a1fd3e56..ab0f2847 100644 --- a/smoothie-sample/src/main/java/com/example/smoothie/SimpleApp.java +++ b/smoothie-sample/src/main/java/com/example/smoothie/SimpleApp.java @@ -1,7 +1,7 @@ package com.example.smoothie; import android.app.Application; -import toothpick.Injector; +import toothpick.Scope; import toothpick.ToothPick; import toothpick.smoothie.module.DefaultApplicationModule; @@ -9,7 +9,7 @@ public class SimpleApp extends Application { @Override public void onCreate() { super.onCreate(); - Injector appInjector = ToothPick.openInjector(this); - appInjector.installModules(new DefaultApplicationModule(this)); + Scope appScope = ToothPick.openScope(this); + appScope.installModules(new DefaultApplicationModule(this)); } } \ No newline at end of file diff --git a/smoothie-sample/src/main/java/com/example/smoothie/deps/ContextNamer.java b/smoothie-sample/src/main/java/com/example/smoothie/deps/ContextNamer.java index a9e0bf3f..731b3c83 100644 --- a/smoothie-sample/src/main/java/com/example/smoothie/deps/ContextNamer.java +++ b/smoothie-sample/src/main/java/com/example/smoothie/deps/ContextNamer.java @@ -13,11 +13,6 @@ public class ContextNamer { public ContextNamer() { countInstances++; - try { - throw new RuntimeException(); - } catch (RuntimeException e) { - e.printStackTrace(); - } } public String getApplicationName() { diff --git a/smoothie-sample/src/test/java/com/example/smoothie/SimpleActivityTest.java b/smoothie-sample/src/test/java/com/example/smoothie/SimpleActivityTest.java index 2fcc8915..1bec6859 100644 --- a/smoothie-sample/src/test/java/com/example/smoothie/SimpleActivityTest.java +++ b/smoothie-sample/src/test/java/com/example/smoothie/SimpleActivityTest.java @@ -7,7 +7,7 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import org.robolectric.util.ActivityController; -import toothpick.Injector; +import toothpick.Scope; import toothpick.ToothPick; import toothpick.config.Module; @@ -29,8 +29,8 @@ public void verifyInjectionAtOnCreate() { expect(mockContextNamer.getActivityName()).andReturn("bar"); ActivityController controllerSimpleActivity = Robolectric.buildActivity(SimpleActivity.class); SimpleActivity activity = controllerSimpleActivity.get(); - Injector injector = ToothPick.openInjector(activity); - injector.installTestModules(new TestModule(mockContextNamer)); + Scope scope = ToothPick.openScope(activity); + scope.installTestModules(new TestModule(mockContextNamer)); replay(mockContextNamer); //WHEN diff --git a/toothpick-compiler/src/main/java/toothpick/compiler/ToothpickProcessor.java b/toothpick-compiler/src/main/java/toothpick/compiler/ToothpickProcessor.java index 98e4af0f..795248a5 100644 --- a/toothpick-compiler/src/main/java/toothpick/compiler/ToothpickProcessor.java +++ b/toothpick-compiler/src/main/java/toothpick/compiler/ToothpickProcessor.java @@ -40,7 +40,7 @@ public abstract class ToothpickProcessor extends AbstractProcessor { public static final String PARAMETER_REGISTRY_PACKAGE_NAME = "toothpick_registry_package_name"; /** - * The name of the annotation processor option to exclude classes from the creation of member injectors & factories. + * The name of the annotation processor option to exclude classes from the creation of member scopes & factories. */ public static final String PARAMETER_EXCLUDES = "toothpick_excludes"; @@ -161,7 +161,7 @@ protected boolean isValidInjectField(VariableElement fieldElement) { valid = false; } - // Verify parentInjector modifiers. + // Verify parentScope modifiers. Set parentModifiers = enclosingElement.getModifiers(); //TODO should not be a non static inner class neither if (parentModifiers.contains(PRIVATE)) { @@ -184,7 +184,7 @@ protected boolean isValidInjectMethod(Element methodElement) { valid = false; } - // Verify parentInjector modifiers. + // Verify parentScope modifiers. Set parentModifiers = enclosingElement.getModifiers(); //TODO should not be a non static inner class neither if (parentModifiers.contains(PRIVATE)) { diff --git a/toothpick-compiler/src/main/java/toothpick/compiler/factory/FactoryProcessor.java b/toothpick-compiler/src/main/java/toothpick/compiler/factory/FactoryProcessor.java index fbc926a6..2703778e 100644 --- a/toothpick-compiler/src/main/java/toothpick/compiler/factory/FactoryProcessor.java +++ b/toothpick-compiler/src/main/java/toothpick/compiler/factory/FactoryProcessor.java @@ -199,7 +199,7 @@ private boolean isValidInjectConstructor(Element element) { valid = false; } - // Verify parentInjector modifiers. + // Verify parentScope modifiers. Set parentModifiers = enclosingElement.getModifiers(); //TODO should not be a non static inner class neither if (!parentModifiers.contains(PUBLIC)) { diff --git a/toothpick-compiler/src/main/java/toothpick/compiler/factory/generators/FactoryGenerator.java b/toothpick-compiler/src/main/java/toothpick/compiler/factory/generators/FactoryGenerator.java index 992236c7..a7fb2773 100644 --- a/toothpick-compiler/src/main/java/toothpick/compiler/factory/generators/FactoryGenerator.java +++ b/toothpick-compiler/src/main/java/toothpick/compiler/factory/generators/FactoryGenerator.java @@ -9,7 +9,7 @@ import javax.lang.model.element.Modifier; import javax.lang.model.type.TypeMirror; import toothpick.Factory; -import toothpick.Injector; +import toothpick.Scope; import toothpick.compiler.CodeGenerator; import toothpick.compiler.factory.targets.FactoryInjectionTarget; @@ -56,7 +56,7 @@ private void emitCreateInstance(TypeSpec.Builder builder) { MethodSpec.Builder createInstanceBuilder = MethodSpec.methodBuilder("createInstance") .addAnnotation(Override.class) .addModifiers(Modifier.PUBLIC) - .addParameter(ClassName.get(Injector.class), "injector") + .addParameter(ClassName.get(Scope.class), "scope") .returns(className); StringBuilder localVarStatement = new StringBuilder(""); @@ -72,7 +72,7 @@ private void emitCreateInstance(TypeSpec.Builder builder) { for (TypeMirror typeMirror : factoryInjectionTarget.parameters) { String paramName = "param" + counter++; TypeName paramType = TypeName.get(typeMirror); - createInstanceBuilder.addStatement("$T $L = injector.getInstance($T.class)", paramType, paramName, paramType); + createInstanceBuilder.addStatement("$T $L = scope.getInstance($T.class)", paramType, paramName, paramType); localVarStatement.append(prefix); localVarStatement.append(paramName); prefix = ", "; @@ -81,7 +81,7 @@ private void emitCreateInstance(TypeSpec.Builder builder) { localVarStatement.append(")"); createInstanceBuilder.addStatement(localVarStatement.toString()); if (factoryInjectionTarget.needsMemberInjection) { - createInstanceBuilder.addStatement("new $L$$$$MemberInjector().inject($L, injector)", className, varName); + createInstanceBuilder.addStatement("new $L$$$$MemberInjector().inject($L, scope)", className, varName); } createInstanceBuilder.addStatement("return $L", varName); diff --git a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/MemberInjectorProcessor.java b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/MemberInjectorProcessor.java index de5230e7..88ad10ca 100644 --- a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/MemberInjectorProcessor.java +++ b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/MemberInjectorProcessor.java @@ -1,4 +1,4 @@ -package toothpick.compiler.memberinjector; +package toothpick.compiler.memberscope; import java.util.ArrayList; import java.util.HashSet; @@ -22,11 +22,11 @@ import toothpick.MemberInjector; import toothpick.compiler.ToothpickProcessor; import toothpick.compiler.factory.FactoryProcessor; -import toothpick.compiler.memberinjector.generators.MemberInjectorGenerator; -import toothpick.compiler.memberinjector.generators.MemberInjectorRegistryGenerator; -import toothpick.compiler.memberinjector.targets.FieldInjectionTarget; -import toothpick.compiler.memberinjector.targets.MemberInjectorRegistryInjectionTarget; -import toothpick.compiler.memberinjector.targets.MethodInjectionTarget; +import toothpick.compiler.memberscope.generators.MemberInjectorGenerator; +import toothpick.compiler.memberscope.generators.MemberInjectorRegistryGenerator; +import toothpick.compiler.memberscope.targets.FieldInjectionTarget; +import toothpick.compiler.memberscope.targets.MemberInjectorRegistryInjectionTarget; +import toothpick.compiler.memberscope.targets.MethodInjectionTarget; /** * Same as {@link FactoryProcessor} but for {@link MemberInjector} classes. @@ -54,7 +54,7 @@ public boolean process(Set annotations, RoundEnvironment return false; } - // Generate member injectors + // Generate member scopes Set elementWithInjectionSet = new HashSet<>(); elementWithInjectionSet.addAll(mapTypeElementToFieldInjectorTargetList.keySet()); elementWithInjectionSet.addAll(mapTypeElementToMethodInjectorTargetList.keySet()); @@ -122,7 +122,7 @@ private void parseInjectedField(VariableElement fieldElement, } //TODO take overrides into account. If the method is an override, do not generate a call to it - //it will be performed by the super class member injector already. + //it will be performed by the super class member scope already. private void parseInjectedMethod(ExecutableElement methodElement, Map> mapTypeElementToMemberInjectorTargetList) { TypeElement enclosingElement = (TypeElement) methodElement.getEnclosingElement(); diff --git a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/generators/MemberInjectorGenerator.java b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/generators/MemberInjectorGenerator.java index 99dbc4e9..1f902d45 100644 --- a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/generators/MemberInjectorGenerator.java +++ b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/generators/MemberInjectorGenerator.java @@ -1,4 +1,4 @@ -package toothpick.compiler.memberinjector.generators; +package toothpick.compiler.memberscope.generators; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.FieldSpec; @@ -11,11 +11,11 @@ import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; -import toothpick.Injector; import toothpick.MemberInjector; +import toothpick.Scope; import toothpick.compiler.CodeGenerator; -import toothpick.compiler.memberinjector.targets.FieldInjectionTarget; -import toothpick.compiler.memberinjector.targets.MethodInjectionTarget; +import toothpick.compiler.memberscope.targets.FieldInjectionTarget; +import toothpick.compiler.memberscope.targets.MethodInjectionTarget; /** * Generates a {@link MemberInjector} for a given collection of {@link FieldInjectionTarget}. @@ -49,17 +49,17 @@ public String brewJava() { ParameterizedTypeName memberInjectorInterfaceParameterizedTypeName = ParameterizedTypeName.get(ClassName.get(MemberInjector.class), className); // Build class - TypeSpec.Builder injectorMemberTypeSpec = TypeSpec.classBuilder(className.simpleName() + MEMBER_INJECTOR_SUFFIX) + TypeSpec.Builder scopeMemberTypeSpec = TypeSpec.classBuilder(className.simpleName() + MEMBER_INJECTOR_SUFFIX) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addSuperinterface(memberInjectorInterfaceParameterizedTypeName); - emitSuperMemberInjectorFieldIfNeeded(injectorMemberTypeSpec); - emitInjectMethod(injectorMemberTypeSpec, fieldInjectionTargetList, methodInjectionTargetList); + emitSuperMemberInjectorFieldIfNeeded(scopeMemberTypeSpec); + emitInjectMethod(scopeMemberTypeSpec, fieldInjectionTargetList, methodInjectionTargetList); - JavaFile javaFile = JavaFile.builder(className.packageName(), injectorMemberTypeSpec.build()).build(); + JavaFile javaFile = JavaFile.builder(className.packageName(), scopeMemberTypeSpec.build()).build(); return javaFile.toString(); } - private void emitSuperMemberInjectorFieldIfNeeded(TypeSpec.Builder injectorMemberTypeSpec) { + private void emitSuperMemberInjectorFieldIfNeeded(TypeSpec.Builder scopeMemberTypeSpec) { if (superClassThatNeedsInjection != null) { ClassName superTypeThatNeedsInjection = ClassName.get(superClassThatNeedsInjection); ParameterizedTypeName memberInjectorSuperParameterizedTypeName = @@ -68,27 +68,27 @@ private void emitSuperMemberInjectorFieldIfNeeded(TypeSpec.Builder injectorMembe FieldSpec.builder(memberInjectorSuperParameterizedTypeName, "superMemberInjector", Modifier.PRIVATE) //TODO use proper typing here .initializer("new $L$$$$MemberInjector()", superTypeThatNeedsInjection); - injectorMemberTypeSpec.addField(superMemberInjectorField.build()); + scopeMemberTypeSpec.addField(superMemberInjectorField.build()); } } - private void emitInjectMethod(TypeSpec.Builder injectorMemberTypeSpec, List fieldInjectionTargetList, + private void emitInjectMethod(TypeSpec.Builder scopeMemberTypeSpec, List fieldInjectionTargetList, List methodInjectionTargetList) { MethodSpec.Builder injectMethodBuilder = MethodSpec.methodBuilder("inject") .addAnnotation(Override.class) .addModifiers(Modifier.PUBLIC) .addParameter(ClassName.get(targetClass), "target") - .addParameter(ClassName.get(Injector.class), "injector"); + .addParameter(ClassName.get(Scope.class), "scope"); emitInjectFields(fieldInjectionTargetList, injectMethodBuilder); emitInjectMethods(methodInjectionTargetList, injectMethodBuilder); if (superClassThatNeedsInjection != null) { - injectMethodBuilder.addStatement("superMemberInjector.inject(target, injector)"); + injectMethodBuilder.addStatement("superMemberInjector.inject(target, scope)"); } - injectorMemberTypeSpec.addMethod(injectMethodBuilder.build()); + scopeMemberTypeSpec.addMethod(injectMethodBuilder.build()); } private void emitInjectMethods(List methodInjectionTargetList, MethodSpec.Builder injectMethodBuilder) { @@ -107,7 +107,7 @@ private void emitInjectMethods(List methodInjectionTarget for (TypeMirror typeMirror : methodInjectionTarget.parameters) { String paramName = "param" + counter++; TypeName paramType = TypeName.get(typeMirror); - injectMethodBuilder.addStatement("$T $L = injector.getInstance($L.class)", paramType, paramName, paramType); + injectMethodBuilder.addStatement("$T $L = scope.getInstance($L.class)", paramType, paramName, paramType); injectedMethodCallStatement.append(prefix); injectedMethodCallStatement.append(paramName); prefix = ", "; @@ -122,30 +122,30 @@ private void emitInjectFields(List fieldInjectionTargetLis if (fieldInjectionTargetList == null) { return; } - for (FieldInjectionTarget injectorInjectionTarget : fieldInjectionTargetList) { - final String injectorGetMethodName; + for (FieldInjectionTarget scopeInjectionTarget : fieldInjectionTargetList) { + final String scopeGetMethodName; final ClassName className; - switch (injectorInjectionTarget.kind) { + switch (scopeInjectionTarget.kind) { case INSTANCE: - injectorGetMethodName = "getInstance"; - className = ClassName.get(injectorInjectionTarget.memberClass); + scopeGetMethodName = "getInstance"; + className = ClassName.get(scopeInjectionTarget.memberClass); break; case PROVIDER: - injectorGetMethodName = "getProvider"; - className = ClassName.get(injectorInjectionTarget.kindParamClass); + scopeGetMethodName = "getProvider"; + className = ClassName.get(scopeInjectionTarget.kindParamClass); break; case LAZY: - injectorGetMethodName = "getLazy"; - className = ClassName.get(injectorInjectionTarget.kindParamClass); + scopeGetMethodName = "getLazy"; + className = ClassName.get(scopeInjectionTarget.kindParamClass); break; case FUTURE: - injectorGetMethodName = "getFuture"; - className = ClassName.get(injectorInjectionTarget.kindParamClass); + scopeGetMethodName = "getFuture"; + className = ClassName.get(scopeInjectionTarget.kindParamClass); break; default: throw new IllegalStateException("The kind can't be null."); } - injectBuilder.addStatement("target.$L = injector.$L($T.class)", injectorInjectionTarget.memberName, injectorGetMethodName, className); + injectBuilder.addStatement("target.$L = scope.$L($T.class)", scopeInjectionTarget.memberName, scopeGetMethodName, className); } } diff --git a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/generators/MemberInjectorRegistryGenerator.java b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/generators/MemberInjectorRegistryGenerator.java index 80991582..3b9a4ead 100644 --- a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/generators/MemberInjectorRegistryGenerator.java +++ b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/generators/MemberInjectorRegistryGenerator.java @@ -1,4 +1,4 @@ -package toothpick.compiler.memberinjector.generators; +package toothpick.compiler.memberscope.generators; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; @@ -11,10 +11,10 @@ import javax.lang.model.element.TypeElement; import toothpick.MemberInjector; import toothpick.compiler.CodeGenerator; -import toothpick.compiler.memberinjector.MemberInjectorProcessor; -import toothpick.compiler.memberinjector.targets.MemberInjectorRegistryInjectionTarget; +import toothpick.compiler.memberscope.MemberInjectorProcessor; +import toothpick.compiler.memberscope.targets.MemberInjectorRegistryInjectionTarget; import toothpick.registries.MemberInjectorRegistry; -import toothpick.registries.memberinjector.AbstractMemberInjectorRegistry; +import toothpick.registries.memberscope.AbstractMemberInjectorRegistry; /** * Generates a {@link MemberInjectorRegistry} for a given {@link MemberInjectorRegistryInjectionTarget}. @@ -80,7 +80,8 @@ private void emitGetMemberInjectorMethod(TypeSpec.Builder memberInjectorRegistry memberInjectorRegistryTypeSpec.addMethod(getMemberInjectorMethod.build()); } - @Override public String getFqcn() { + @Override + public String getFqcn() { return memberInjectorRegistryInjectionTarget.getFqcn(); } } diff --git a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/targets/FieldInjectionTarget.java b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/targets/FieldInjectionTarget.java index ac7eaec0..5cf8dcb0 100644 --- a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/targets/FieldInjectionTarget.java +++ b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/targets/FieldInjectionTarget.java @@ -1,4 +1,4 @@ -package toothpick.compiler.memberinjector.targets; +package toothpick.compiler.memberscope.targets; import javax.lang.model.element.TypeElement; diff --git a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/targets/MemberInjectorRegistryInjectionTarget.java b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/targets/MemberInjectorRegistryInjectionTarget.java index 67491d2a..7f92997e 100644 --- a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/targets/MemberInjectorRegistryInjectionTarget.java +++ b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/targets/MemberInjectorRegistryInjectionTarget.java @@ -1,4 +1,4 @@ -package toothpick.compiler.memberinjector.targets; +package toothpick.compiler.memberscope.targets; import java.util.Collection; import javax.lang.model.element.TypeElement; diff --git a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/targets/MethodInjectionTarget.java b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/targets/MethodInjectionTarget.java index 61cfe767..5056f5c9 100644 --- a/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/targets/MethodInjectionTarget.java +++ b/toothpick-compiler/src/main/java/toothpick/compiler/memberinjector/targets/MethodInjectionTarget.java @@ -1,4 +1,4 @@ -package toothpick.compiler.memberinjector.targets; +package toothpick.compiler.memberscope.targets; import java.util.ArrayList; import java.util.List; diff --git a/toothpick-compiler/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/toothpick-compiler/src/main/resources/META-INF/services/javax.annotation.processing.Processor index 9b957070..4b2b86f9 100644 --- a/toothpick-compiler/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ b/toothpick-compiler/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -1,2 +1,2 @@ toothpick.compiler.factory.FactoryProcessor -toothpick.compiler.memberinjector.MemberInjectorProcessor +toothpick.compiler.memberscope.MemberInjectorProcessor diff --git a/toothpick-compiler/src/test/java/toothpick/compiler/factory/FactoryTest.java b/toothpick-compiler/src/test/java/toothpick/compiler/factory/FactoryTest.java index 17a632b1..e6cebebe 100644 --- a/toothpick-compiler/src/test/java/toothpick/compiler/factory/FactoryTest.java +++ b/toothpick-compiler/src/test/java/toothpick/compiler/factory/FactoryTest.java @@ -27,11 +27,11 @@ public void testEmptyConstructor() { "package test;", // "import java.lang.Override;", // "import toothpick.Factory;", // - "import toothpick.Injector;", // + "import toothpick.Scope;", // "", // "public final class TestEmptyConstructor$$Factory implements Factory {", // " @Override", // - " public TestEmptyConstructor createInstance(Injector injector) {", // + " public TestEmptyConstructor createInstance(Scope scope) {", // " TestEmptyConstructor testEmptyConstructor = new TestEmptyConstructor();", // " return testEmptyConstructor;", // " }", // @@ -121,13 +121,13 @@ public void testAClassThatNeedsInjection_withAnInjectedField() { "package test;", // "import java.lang.Override;", // "import toothpick.Factory;", // - "import toothpick.Injector;", // + "import toothpick.Scope;", // "", // "public final class TestAClassThatNeedsInjection$$Factory implements Factory {", // " @Override", // - " public TestAClassThatNeedsInjection createInstance(Injector injector) {", // + " public TestAClassThatNeedsInjection createInstance(Scope scope) {", // " TestAClassThatNeedsInjection testAClassThatNeedsInjection = new TestAClassThatNeedsInjection();", // - " new test.TestAClassThatNeedsInjection$$MemberInjector().inject(testAClassThatNeedsInjection, injector);", // + " new test.TestAClassThatNeedsInjection$$MemberInjector().inject(testAClassThatNeedsInjection, scope);", // " return testAClassThatNeedsInjection;", // " }", // " @Override", // @@ -164,13 +164,13 @@ public void testAClassThatNeedsInjection_withAnInjectedMethod() { "package test;", // "import java.lang.Override;", // "import toothpick.Factory;", // - "import toothpick.Injector;", // + "import toothpick.Scope;", // "", // "public final class TestAClassThatNeedsInjection$$Factory implements Factory {", // " @Override", // - " public TestAClassThatNeedsInjection createInstance(Injector injector) {", // + " public TestAClassThatNeedsInjection createInstance(Scope scope) {", // " TestAClassThatNeedsInjection testAClassThatNeedsInjection = new TestAClassThatNeedsInjection();", // - " new test.TestAClassThatNeedsInjection$$MemberInjector().inject(testAClassThatNeedsInjection, injector);", // + " new test.TestAClassThatNeedsInjection$$MemberInjector().inject(testAClassThatNeedsInjection, scope);", // " return testAClassThatNeedsInjection;", // " }", // " @Override", // @@ -208,13 +208,13 @@ public void testNonEmptyConstructor() { "import java.lang.Override;", // "import java.lang.String;", // "import toothpick.Factory;", // - "import toothpick.Injector;", // + "import toothpick.Scope;", // "", // "public final class TestNonEmptyConstructor$$Factory implements Factory {", // " @Override", // - " public TestNonEmptyConstructor createInstance(Injector injector) {", // - " String param1 = injector.getInstance(String.class);", // - " Integer param2 = injector.getInstance(Integer.class);", // + " public TestNonEmptyConstructor createInstance(Scope scope) {", // + " String param1 = scope.getInstance(String.class);", // + " Integer param2 = scope.getInstance(Integer.class);", // " TestNonEmptyConstructor testNonEmptyConstructor = new TestNonEmptyConstructor(param1, param2);", // " return testNonEmptyConstructor;", // " }", // @@ -268,13 +268,13 @@ public void testSingletonAnnotation() { "import java.lang.Override;", // "import java.lang.String;", // "import toothpick.Factory;", // - "import toothpick.Injector;", // + "import toothpick.Scope;", // "", // "public final class TestNonEmptyConstructor$$Factory implements Factory {", // " @Override", // - " public TestNonEmptyConstructor createInstance(Injector injector) {", // - " String param1 = injector.getInstance(String.class);", // - " Integer param2 = injector.getInstance(Integer.class);", // + " public TestNonEmptyConstructor createInstance(Scope scope) {", // + " String param1 = scope.getInstance(String.class);", // + " Integer param2 = scope.getInstance(Integer.class);", // " TestNonEmptyConstructor testNonEmptyConstructor = new TestNonEmptyConstructor(param1, param2);", // " return testNonEmptyConstructor;", // " }", // @@ -315,13 +315,13 @@ public void testProducesSingletonAnnotation() { "import java.lang.Override;", // "import java.lang.String;", // "import toothpick.Factory;", // - "import toothpick.Injector;", // + "import toothpick.Scope;", // "", // "public final class TestNonEmptyConstructor$$Factory implements Factory {", // " @Override", // - " public TestNonEmptyConstructor createInstance(Injector injector) {", // - " String param1 = injector.getInstance(String.class);", // - " Integer param2 = injector.getInstance(Integer.class);", // + " public TestNonEmptyConstructor createInstance(Scope scope) {", // + " String param1 = scope.getInstance(String.class);", // + " Integer param2 = scope.getInstance(Integer.class);", // " TestNonEmptyConstructor testNonEmptyConstructor = new TestNonEmptyConstructor(param1, param2);", // " return testNonEmptyConstructor;", // " }", // diff --git a/toothpick-compiler/src/test/java/toothpick/compiler/factory/ProcessorTestUtilities.java b/toothpick-compiler/src/test/java/toothpick/compiler/factory/ProcessorTestUtilities.java index 5cbafcc1..45c9775c 100644 --- a/toothpick-compiler/src/test/java/toothpick/compiler/factory/ProcessorTestUtilities.java +++ b/toothpick-compiler/src/test/java/toothpick/compiler/factory/ProcessorTestUtilities.java @@ -3,7 +3,7 @@ import java.util.Arrays; import java.util.List; import javax.annotation.processing.Processor; -import toothpick.compiler.memberinjector.MemberInjectorProcessor; +import toothpick.compiler.memberscope.MemberInjectorProcessor; final class ProcessorTestUtilities { private ProcessorTestUtilities() { diff --git a/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/FieldMemberInjectorTest.java b/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/FieldMemberInjectorTest.java index 012c0df4..bc5282d2 100644 --- a/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/FieldMemberInjectorTest.java +++ b/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/FieldMemberInjectorTest.java @@ -1,4 +1,4 @@ -package toothpick.compiler.memberinjector; +package toothpick.compiler.memberscope; import com.google.common.base.Joiner; import com.google.testing.compile.JavaFileObjects; @@ -7,7 +7,7 @@ import static com.google.common.truth.Truth.assert_; import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; -import static toothpick.compiler.memberinjector.ProcessorTestUtilities.memberInjectorProcessors; +import static toothpick.compiler.memberscope.ProcessorTestUtilities.memberInjectorProcessors; public class FieldMemberInjectorTest { @Test @@ -26,13 +26,13 @@ public void testSimpleFieldInjection() { "package test;", // "", // "import java.lang.Override;", // - "import toothpick.Injector;", // "import toothpick.MemberInjector;", // + "import toothpick.Scope;", // "", // "public final class TestFieldInjection$$MemberInjector implements MemberInjector {", // " @Override", // - " public void inject(TestFieldInjection target, Injector injector) {", // - " target.foo = injector.getInstance(Foo.class);", // + " public void inject(TestFieldInjection target, Scope scope) {", // + " target.foo = scope.getInstance(Foo.class);", // " }", // "}" // )); @@ -62,13 +62,13 @@ public void testProviderFieldInjection() { "package test;", // "", // "import java.lang.Override;", // - "import toothpick.Injector;", // "import toothpick.MemberInjector;", // + "import toothpick.Scope;", // "", // "public final class TestFieldInjection$$MemberInjector implements MemberInjector {", // " @Override", // - " public void inject(TestFieldInjection target, Injector injector) {", // - " target.foo = injector.getProvider(Foo.class);", // + " public void inject(TestFieldInjection target, Scope scope) {", // + " target.foo = scope.getProvider(Foo.class);", // " }", // "}" // )); @@ -98,13 +98,13 @@ public void testLazyFieldInjection() { "package test;", // "", // "import java.lang.Override;", // - "import toothpick.Injector;", // "import toothpick.MemberInjector;", // + "import toothpick.Scope;", // "", // "public final class TestFieldInjection$$MemberInjector implements MemberInjector {", // " @Override", // - " public void inject(TestFieldInjection target, Injector injector) {", // - " target.foo = injector.getLazy(Foo.class);", // + " public void inject(TestFieldInjection target, Scope scope) {", // + " target.foo = scope.getLazy(Foo.class);", // " }", // "}" // )); @@ -134,13 +134,13 @@ public void testFutureFieldInjection() { "package test;", // "", // "import java.lang.Override;", // - "import toothpick.Injector;", // "import toothpick.MemberInjector;", // + "import toothpick.Scope;", // "", // "public final class TestFieldInjection$$MemberInjector implements MemberInjector {", // " @Override", // - " public void inject(TestFieldInjection target, Injector injector) {", // - " target.foo = injector.getFuture(Foo.class);", // + " public void inject(TestFieldInjection target, Scope scope) {", // + " target.foo = scope.getFuture(Foo.class);", // " }", // "}" // )); @@ -170,14 +170,14 @@ public void testFieldInjection_shouldProduceMemberInjector_whenClassHas2Fields() "package test;", // "", // "import java.lang.Override;", // - "import toothpick.Injector;", // "import toothpick.MemberInjector;", // + "import toothpick.Scope;", // "", // "public final class TestFieldInjection$$MemberInjector implements MemberInjector {", // " @Override", // - " public void inject(TestFieldInjection target, Injector injector) {", // - " target.foo = injector.getInstance(Foo.class);", // - " target.foo2 = injector.getInstance(Foo.class);", // + " public void inject(TestFieldInjection target, Scope scope) {", // + " target.foo = scope.getInstance(Foo.class);", // + " target.foo2 = scope.getInstance(Foo.class);", // " }", // "}" // )); @@ -227,16 +227,16 @@ public void testMemberInjection_shouldInjectAsAnInstanceOfSuperClass_whenSuperCl "package test;", // "", // "import java.lang.Override;", // - "import toothpick.Injector;", // "import toothpick.MemberInjector;", // + "import toothpick.Scope;", // "", // "public final class TestMemberInjection$$MemberInjector implements MemberInjector {", // " private MemberInjector superMemberInjector " + "= new test.TestMemberInjectionParent$$MemberInjector();", // " @Override", // - " public void inject(TestMemberInjection target, Injector injector) {", // - " target.foo = injector.getInstance(Foo.class);", // - " superMemberInjector.inject(target, injector);", // + " public void inject(TestMemberInjection target, Scope scope) {", // + " target.foo = scope.getInstance(Foo.class);", // + " superMemberInjector.inject(target, scope);", // " }", // "}" // )); diff --git a/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/MemberInjectorRegistryTest.java b/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/MemberInjectorRegistryTest.java index 87b5377a..64f14ce4 100644 --- a/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/MemberInjectorRegistryTest.java +++ b/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/MemberInjectorRegistryTest.java @@ -1,4 +1,4 @@ -package toothpick.compiler.memberinjector; +package toothpick.compiler.memberscope; import com.google.common.base.Joiner; import com.google.testing.compile.JavaFileObjects; @@ -11,7 +11,8 @@ import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; public class MemberInjectorRegistryTest { - @Test public void testASimpleRegistry() { + @Test + public void testASimpleRegistry() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestASimpleRegistry", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -24,7 +25,7 @@ public class MemberInjectorRegistryTest { "package toothpick;", // "", // "import java.lang.Class;", // - "import toothpick.registries.memberinjector.AbstractMemberInjectorRegistry;", // + "import toothpick.registries.memberscope.AbstractMemberInjectorRegistry;", // "", // "public final class MemberInjectorRegistry extends AbstractMemberInjectorRegistry {", // " public MemberInjectorRegistry() {", // @@ -43,13 +44,14 @@ public class MemberInjectorRegistryTest { assert_().about(javaSource()) .that(source) - .processedWith(toothpick.compiler.memberinjector.ProcessorTestUtilities.memberInjectorProcessors("toothpick", Collections.EMPTY_LIST)) + .processedWith(toothpick.compiler.memberscope.ProcessorTestUtilities.memberInjectorProcessors("toothpick", Collections.EMPTY_LIST)) .compilesWithoutError() .and() .generatesSources(expectedSource); } - @Test public void testARegistry_withDependencies() { + @Test + public void testARegistry_withDependencies() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestARegistry", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -62,7 +64,7 @@ public class MemberInjectorRegistryTest { "package toothpick;", // "", // "import java.lang.Class;", // - "import toothpick.registries.memberinjector.AbstractMemberInjectorRegistry;", // + "import toothpick.registries.memberscope.AbstractMemberInjectorRegistry;", // "", // "public final class MemberInjectorRegistry extends AbstractMemberInjectorRegistry {", // " public MemberInjectorRegistry() {", // @@ -84,7 +86,7 @@ public class MemberInjectorRegistryTest { assert_().about(javaSource()) .that(source) .processedWith( - toothpick.compiler.memberinjector.ProcessorTestUtilities.memberInjectorProcessors("toothpick", Arrays.asList("toothpick", "toothpick"))) + toothpick.compiler.memberscope.ProcessorTestUtilities.memberInjectorProcessors("toothpick", Arrays.asList("toothpick", "toothpick"))) .compilesWithoutError() .and() .generatesSources(expectedSource); diff --git a/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/MethodMemberInjectorTest.java b/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/MethodMemberInjectorTest.java index 3da43291..317149f3 100644 --- a/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/MethodMemberInjectorTest.java +++ b/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/MethodMemberInjectorTest.java @@ -1,4 +1,4 @@ -package toothpick.compiler.memberinjector; +package toothpick.compiler.memberscope; import com.google.common.base.Joiner; import com.google.testing.compile.JavaFileObjects; @@ -7,10 +7,11 @@ import static com.google.common.truth.Truth.assert_; import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; -import static toothpick.compiler.memberinjector.ProcessorTestUtilities.memberInjectorProcessors; +import static toothpick.compiler.memberscope.ProcessorTestUtilities.memberInjectorProcessors; public class MethodMemberInjectorTest { - @Test public void testSimpleMethodInjection() { + @Test + public void testSimpleMethodInjection() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestMethodInjection", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // @@ -25,13 +26,13 @@ public class MethodMemberInjectorTest { "package test;", // "", // "import java.lang.Override;", // - "import toothpick.Injector;", // "import toothpick.MemberInjector;", // + "import toothpick.Scope;", // "", // "public final class TestMethodInjection$$MemberInjector implements MemberInjector {", // " @Override", // - " public void inject(TestMethodInjection target, Injector injector) {", // - " Foo param1 = injector.getInstance(test.Foo.class);", // + " public void inject(TestMethodInjection target, Scope scope) {", // + " Foo param1 = scope.getInstance(test.Foo.class);", // " target.m(param1);", // " }", // "}" // @@ -45,7 +46,8 @@ public class MethodMemberInjectorTest { .generatesSources(expectedSource); } - @Test public void testMethodInjection_shouldFail_whenInjectedMethodIsPrivate() { + @Test + public void testMethodInjection_shouldFail_whenInjectedMethodIsPrivate() { JavaFileObject source = JavaFileObjects.forSourceString("test.TestMethodInjection", Joiner.on('\n').join(// "package test;", // "import javax.inject.Inject;", // diff --git a/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/ProcessorTestUtilities.java b/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/ProcessorTestUtilities.java index 80534814..ccc2a535 100644 --- a/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/ProcessorTestUtilities.java +++ b/toothpick-compiler/src/test/java/toothpick/compiler/memberinjector/ProcessorTestUtilities.java @@ -1,4 +1,4 @@ -package toothpick.compiler.memberinjector; +package toothpick.compiler.memberscope; import java.util.Arrays; import java.util.List; diff --git a/toothpick-generated-core/src/main/java/toothpick/registries/memberinjector/AbstractMemberInjectorRegistry.java b/toothpick-generated-core/src/main/java/toothpick/registries/memberinjector/AbstractMemberInjectorRegistry.java index 3b67654d..b77f00c1 100644 --- a/toothpick-generated-core/src/main/java/toothpick/registries/memberinjector/AbstractMemberInjectorRegistry.java +++ b/toothpick-generated-core/src/main/java/toothpick/registries/memberinjector/AbstractMemberInjectorRegistry.java @@ -1,9 +1,9 @@ -package toothpick.registries.memberinjector; +package toothpick.registries.memberscope; import java.util.ArrayList; import java.util.List; -import toothpick.registries.MemberInjectorRegistry; import toothpick.MemberInjector; +import toothpick.registries.MemberInjectorRegistry; /** * The base class of the {@link MemberInjectorRegistry} classes generated by the toothpick annotation processor. @@ -22,7 +22,7 @@ public void addChildRegistry(MemberInjectorRegistry childRegistry) { /** * Explore the subtree of children registries via DFS to retrieve a {@link MemberInjector} for a given class. - * This method will be called automatically by all member injectors generated by toothpick, if it is provided + * This method will be called automatically by all member scopes generated by toothpick, if it is provided * appropriate parameters when compiling each library. * * @param clazz the class to look the {@link MemberInjector} for. diff --git a/toothpick-generated-core/src/main/java/toothpick/registries/memberinjector/MemberInjectorRegistryLocator.java b/toothpick-generated-core/src/main/java/toothpick/registries/memberinjector/MemberInjectorRegistryLocator.java index f4f89022..4be10f82 100644 --- a/toothpick-generated-core/src/main/java/toothpick/registries/memberinjector/MemberInjectorRegistryLocator.java +++ b/toothpick-generated-core/src/main/java/toothpick/registries/memberinjector/MemberInjectorRegistryLocator.java @@ -1,4 +1,4 @@ -package toothpick.registries.memberinjector; +package toothpick.registries.memberscope; import java.util.ArrayList; import java.util.List; diff --git a/toothpick-generated-core/src/main/java/toothpick/registries/memberinjector/ReflectionMemberInjectorRegistry.java b/toothpick-generated-core/src/main/java/toothpick/registries/memberinjector/ReflectionMemberInjectorRegistry.java index 9eb095b9..8876868c 100644 --- a/toothpick-generated-core/src/main/java/toothpick/registries/memberinjector/ReflectionMemberInjectorRegistry.java +++ b/toothpick-generated-core/src/main/java/toothpick/registries/memberinjector/ReflectionMemberInjectorRegistry.java @@ -1,4 +1,4 @@ -package toothpick.registries.memberinjector; +package toothpick.registries.memberscope; import toothpick.Factory; import toothpick.MemberInjector; @@ -18,11 +18,11 @@ public MemberInjector getMemberInjector(Class clazz) { Class> memberInjectorClass = (Class>) Class.forName(clazz.getName() + "$$MemberInjector"); return memberInjectorClass.newInstance(); } catch (ClassNotFoundException e) { - throw new RuntimeException("Impossible to get the member injector class for class " + clazz.getName() + ". Add an inject annotated field."); + throw new RuntimeException("Impossible to get the member scope class for class " + clazz.getName() + ". Add an inject annotated field."); } catch (InstantiationException e) { - throw new RuntimeException("This should not happen. Impossible to create member injector for class " + clazz.getName()); + throw new RuntimeException("This should not happen. Impossible to create member scope for class " + clazz.getName()); } catch (IllegalAccessException e) { - throw new RuntimeException("This should not happen. Impossible to access member injector constructor for class " + clazz.getName()); + throw new RuntimeException("This should not happen. Impossible to access member scope constructor for class " + clazz.getName()); } } } diff --git a/toothpick-runtime/src/main/java/toothpick/InjectorImpl.java b/toothpick-runtime/src/main/java/toothpick/InjectorImpl.java index d828094c..862ab261 100644 --- a/toothpick-runtime/src/main/java/toothpick/InjectorImpl.java +++ b/toothpick-runtime/src/main/java/toothpick/InjectorImpl.java @@ -1,166 +1,14 @@ package toothpick; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import javax.inject.Provider; -import toothpick.config.Binding; -import toothpick.config.Module; -import toothpick.registries.factory.FactoryRegistryLocator; -import toothpick.registries.memberinjector.MemberInjectorRegistryLocator; - -import static java.lang.String.format; +import toothpick.registries.memberscope.MemberInjectorRegistryLocator; /** - * This class should never be used outside of the toothpick library. + * Default implementation of an scope. */ -public final class InjectorImpl extends Injector { - public static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(4); - private boolean hasTestModules; - - public InjectorImpl(Object name) { - super(name); - } - +public final class InjectorImpl implements Injector { @Override - public void inject(T obj) { + public void inject(T obj, Scope scope) { MemberInjector memberInjector = MemberInjectorRegistryLocator.getMemberInjector((Class) obj.getClass()); - memberInjector.inject(obj, this); - } - - public IdentityHashMap getScope() { - return scope; - } - - @Override - public T getInstance(Class clazz) { - return getProvider(clazz).get(); - } - - @Override - public Provider getProvider(Class clazz) { - if (clazz == null) { - throw new IllegalArgumentException("TP can't get an instance of a null class."); - } - synchronized (clazz) { - Provider scopedProvider = getScopedProvider(clazz); - if (scopedProvider != null) { - return scopedProvider; - } - Iterator iterator = parentInjectors.iterator(); - while (iterator.hasNext()) { - Injector parentInjector = iterator.next(); - Provider parentScopedProvider = parentInjector.getScopedProvider(clazz); - if (parentScopedProvider != null) { - return parentScopedProvider; - } - } - } - //classes discovered at runtime, not bound by any module - Factory factory = FactoryRegistryLocator.getFactory(clazz); - final Provider newProvider; - synchronized (clazz) { - if (factory.hasSingletonAnnotation()) { - //singleton classes discovered dynamically go to root scope. - newProvider = new ProviderImpl(factory.createInstance(this)); - getRootInjector().scope.put(clazz, newProvider); - } else { - newProvider = new ProviderImpl(this, factory, false); - scope.put(clazz, newProvider); - } - } - return newProvider; - } - - //TODO explain the change to daniel, we were having some troubles - //we could not be using a provider in multi-thread, it has to be - //thread safe. The best was a multi DCL. - //now all access to the injector scopes are locked on the class - //all provider are locked on themselves. - //I won't do unit tests, because they are too hard and don't bring much - //TODO create a plugin system so that we can inject anything (handler/plugin ?) - //Kill the 2 methods below - //for @Inject Foo - //generate getProvider(Bar.class, Foo.class) --> Foo becomes a modifier - //for @inject @Foo Bar - //generate getInstance(Bar.class, Foo.class) --> Foo becomes a modifier (JSR 330) - //if Foo is added as extension point to the compiler - //and devs can provide their own Injector that knows what to do to create - //a Foo being passed a Provider - @Override - public Lazy getLazy(Class clazz) { - Provider provider = getProvider(clazz); - return new ProviderImpl<>(provider, true); - } - - @Override - public Future getFuture(Class clazz) { - final Provider provider = getProvider(clazz); - return EXECUTOR_SERVICE.submit(new ProviderCallable<>(provider)); - } - - @Override - public void installTestModules(Module... modules) { - //we allow multiple calls to this method - boolean oldHasTestModules = hasTestModules; - hasTestModules = false; - installModules(modules); - boolean doOverrideModulesExist = modules != null; - hasTestModules = oldHasTestModules || doOverrideModulesExist; - } - - @Override - public void installModules(Module... modules) { - for (Module module : modules) { - installModule(module); - } - } - - private void installModule(Module module) { - for (Binding binding : module.getBindingSet()) { - if (binding == null) { - throw new IllegalStateException("A module can't have a null binding."); - } - Class key = binding.getKey(); - synchronized (key) { - if (!hasTestModules || !scope.containsKey(key)) { - scope.put(key, toProvider(binding)); - } - } - } - } - - //do not change the return type to Provider. - //it would be cool and more convenient for bindings, but it would - //make the APIs very unstable as you could not get any instance of the - //implementation class via an injector, it would fail but be syntactically valid. - //only creating an instance of the interface is valid with this syntax. - /*VisibleForTesting*/ Provider toProvider(Binding binding) { - if (binding == null) { - throw new IllegalStateException("null binding are not allowed. Should not happen unless getBindingSet is overridden."); - } - switch (binding.getMode()) { - case SIMPLE: - Factory factory = FactoryRegistryLocator.getFactory(binding.getKey()); - return new ProviderImpl<>(this, factory, false); - case CLASS: - Factory factory2 = FactoryRegistryLocator.getFactory(binding.getImplementationClass()); - return new ProviderImpl<>(this, factory2, false); - case INSTANCE: - return new ProviderImpl<>(binding.getInstance()); - case PROVIDER_INSTANCE: - //to ensure providers do not have to deal with concurrency, we wrap them in a thread safe provider - return new ProviderImpl<>(binding.getProviderInstance(), false); - case PROVIDER_CLASS: - Factory> providerFactory = FactoryRegistryLocator.getFactory(binding.getProviderClass()); - return new ProviderImpl<>(this, providerFactory, true); - - //JACOCO:OFF - default: - throw new IllegalStateException(format("mode is not handled: %s. This should not happen.", binding.getMode())); - //JACOCO:ON - } + memberInjector.inject(obj, scope); } } diff --git a/toothpick-runtime/src/main/java/toothpick/ProviderImpl.java b/toothpick-runtime/src/main/java/toothpick/ProviderImpl.java index 4999478e..20053450 100644 --- a/toothpick-runtime/src/main/java/toothpick/ProviderImpl.java +++ b/toothpick-runtime/src/main/java/toothpick/ProviderImpl.java @@ -2,10 +2,10 @@ import javax.inject.Provider; -//TODO only the provider created by injector.getProvider need to be thread safe, all others +//TODO only the provider created by scope.getProvider need to be thread safe, all others //are already accessed with a lock public class ProviderImpl implements Provider, Lazy { - private Injector injector; + private Scope scope; private volatile T instance; private Factory factory; private volatile Provider providerInstance; @@ -21,8 +21,8 @@ public ProviderImpl(Provider providerInstance, boolean isLazy) { this.isLazy = isLazy; } - public ProviderImpl(Injector injector, Factory factory, boolean isProviderFactory) { - this.injector = injector; + public ProviderImpl(Scope scope, Factory factory, boolean isProviderFactory) { + this.scope = scope; if (isProviderFactory) { this.providerFactory = (Factory>) factory; } else { @@ -53,12 +53,12 @@ public T get() { } if (factory != null) { if (!factory.hasSingletonAnnotation()) { - return factory.createInstance(injector); + return factory.createInstance(scope); } //DCL if (instance == null) { synchronized (this) { - instance = factory.createInstance(injector); + instance = factory.createInstance(scope); } } return instance; @@ -68,7 +68,7 @@ public T get() { //DCL if (instance == null) { synchronized (this) { - instance = providerFactory.createInstance(injector).get(); + instance = providerFactory.createInstance(scope).get(); } } return instance; @@ -77,7 +77,7 @@ public T get() { if (providerInstance == null) { //DCL synchronized (this) { - providerInstance = providerFactory.createInstance(injector); + providerInstance = providerFactory.createInstance(scope); } } //to ensure the wrapped provider doesn't have to deal @@ -86,7 +86,7 @@ public T get() { return providerInstance.get(); } } - Provider provider = providerFactory.createInstance(injector); + Provider provider = providerFactory.createInstance(scope); //to ensure the wrapped provider doesn't have to deal //with concurrency synchronized (this) { diff --git a/toothpick-runtime/src/main/java/toothpick/ScopeImpl.java b/toothpick-runtime/src/main/java/toothpick/ScopeImpl.java new file mode 100644 index 00000000..a2bc3d6e --- /dev/null +++ b/toothpick-runtime/src/main/java/toothpick/ScopeImpl.java @@ -0,0 +1,156 @@ +package toothpick; + +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import javax.inject.Provider; +import toothpick.config.Binding; +import toothpick.config.Module; +import toothpick.registries.factory.FactoryRegistryLocator; + +import static java.lang.String.format; + +public class ScopeImpl extends Scope { + public static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(4); + private boolean hasTestModules; + + public ScopeImpl(Object name) { + super(name); + } + + public IdentityHashMap getScope() { + return mapClassesToProviders; + } + + @Override + public T getInstance(Class clazz) { + return getProvider(clazz).get(); + } + + @Override + public Provider getProvider(Class clazz) { + if (clazz == null) { + throw new IllegalArgumentException("TP can't get an instance of a null class."); + } + synchronized (clazz) { + Provider scopedProvider = getScopedProvider(clazz); + if (scopedProvider != null) { + return scopedProvider; + } + Iterator iterator = parentScopes.iterator(); + while (iterator.hasNext()) { + Scope parentScope = iterator.next(); + Provider parentScopedProvider = parentScope.getScopedProvider(clazz); + if (parentScopedProvider != null) { + return parentScopedProvider; + } + } + } + //classes discovered at runtime, not bound by any module + Factory factory = FactoryRegistryLocator.getFactory(clazz); + final Provider newProvider; + synchronized (clazz) { + if (factory.hasSingletonAnnotation()) { + //singleton classes discovered dynamically go to root scope. + newProvider = new ProviderImpl(factory.createInstance(this)); + getRootScope().mapClassesToProviders.put(clazz, newProvider); + } else { + newProvider = new ProviderImpl(this, factory, false); + mapClassesToProviders.put(clazz, newProvider); + } + } + return newProvider; + } + + //TODO explain the change to daniel, we were having some troubles + //we could not be using a provider in multi-thread, it has to be + //thread safe. The best was a multi DCL. + //now all access to the scope scopes are locked on the class + //all provider are locked on themselves. + //I won't do unit tests, because they are too hard and don't bring much + //TODO create a plugin system so that we can inject anything (handler/plugin ?) + //Kill the 2 methods below + //for @Inject Foo + //generate getProvider(Bar.class, Foo.class) --> Foo becomes a modifier + //for @inject @Foo Bar + //generate getInstance(Bar.class, Foo.class) --> Foo becomes a modifier (JSR 330) + //if Foo is added as extension point to the compiler + //and devs can provide their own Injector that knows what to do to create + //a Foo being passed a Provider + @Override + public Lazy getLazy(Class clazz) { + Provider provider = getProvider(clazz); + return new ProviderImpl<>(provider, true); + } + + @Override + public Future getFuture(Class clazz) { + final Provider provider = getProvider(clazz); + return EXECUTOR_SERVICE.submit(new ProviderCallable<>(provider)); + } + + @Override + public void installTestModules(Module... modules) { + //we allow multiple calls to this method + boolean oldHasTestModules = hasTestModules; + hasTestModules = false; + installModules(modules); + boolean doOverrideModulesExist = modules != null; + hasTestModules = oldHasTestModules || doOverrideModulesExist; + } + + @Override + public void installModules(Module... modules) { + for (Module module : modules) { + installModule(module); + } + } + + private void installModule(Module module) { + for (Binding binding : module.getBindingSet()) { + if (binding == null) { + throw new IllegalStateException("A module can't have a null binding."); + } + Class key = binding.getKey(); + synchronized (key) { + if (!hasTestModules || !mapClassesToProviders.containsKey(key)) { + mapClassesToProviders.put(key, toProvider(binding)); + } + } + } + } + + //do not change the return type to Provider. + //it would be cool and more convenient for bindings, but it would + //make the APIs very unstable as you could not get any instance of the + //implementation class via an scope, it would fail but be syntactically valid. + //only creating an instance of the interface is valid with this syntax. + /*VisibleForTesting*/ Provider toProvider(Binding binding) { + if (binding == null) { + throw new IllegalStateException("null binding are not allowed. Should not happen unless getBindingSet is overridden."); + } + switch (binding.getMode()) { + case SIMPLE: + Factory factory = FactoryRegistryLocator.getFactory(binding.getKey()); + return new ProviderImpl<>(this, factory, false); + case CLASS: + Factory factory2 = FactoryRegistryLocator.getFactory(binding.getImplementationClass()); + return new ProviderImpl<>(this, factory2, false); + case INSTANCE: + return new ProviderImpl<>(binding.getInstance()); + case PROVIDER_INSTANCE: + //to ensure providers do not have to deal with concurrency, we wrap them in a thread safe provider + return new ProviderImpl<>(binding.getProviderInstance(), false); + case PROVIDER_CLASS: + Factory> providerFactory = FactoryRegistryLocator.getFactory(binding.getProviderClass()); + return new ProviderImpl<>(this, providerFactory, true); + + //JACOCO:OFF + default: + throw new IllegalStateException(format("mode is not handled: %s. This should not happen.", binding.getMode())); + //JACOCO:ON + } + } +} diff --git a/toothpick-runtime/src/main/java/toothpick/ToothPick.java b/toothpick-runtime/src/main/java/toothpick/ToothPick.java index 5dac5b13..97b9a112 100644 --- a/toothpick-runtime/src/main/java/toothpick/ToothPick.java +++ b/toothpick-runtime/src/main/java/toothpick/ToothPick.java @@ -4,50 +4,55 @@ /** * Main class to access toothpick features. - * It allows to create / retrieve injectors. + * It allows to create / retrieve scopes. */ public final class ToothPick { //http://stackoverflow.com/a/29421697/693752 //it should really be final, if not volatile - private static final ConcurrentHashMap MAP_KEY_TO_INJECTOR = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap MAP_KEY_TO_INJECTOR = new ConcurrentHashMap<>(); + private static Injector injector = new InjectorImpl(); private ToothPick() { throw new RuntimeException("Constructor can't be invoked even via reflection."); } - public static Injector openInjector(Object key) { - Injector injector = MAP_KEY_TO_INJECTOR.get(key); - if (injector == null) { + public static Scope openScope(Object name) { + Scope scope = MAP_KEY_TO_INJECTOR.get(name); + if (scope == null) { synchronized (MAP_KEY_TO_INJECTOR) { - injector = MAP_KEY_TO_INJECTOR.get(key); - if (injector == null) { - injector = new InjectorImpl(key); - MAP_KEY_TO_INJECTOR.put(key, injector); + scope = MAP_KEY_TO_INJECTOR.get(name); + if (scope == null) { + scope = new ScopeImpl(name); + MAP_KEY_TO_INJECTOR.put(name, scope); } } } - return injector; + return scope; } - public static void closeInjector(Object key) { - Injector injector = openInjector(key); - if (injector == null) { + public static void closeScope(Object key) { + Scope scope = openScope(key); + if (scope == null) { return; } MAP_KEY_TO_INJECTOR.remove(key); - for (Injector childInjector : injector.childrenInjector) { - MAP_KEY_TO_INJECTOR.remove(childInjector.getName()); + for (Scope childScope : scope.childrenScopes) { + MAP_KEY_TO_INJECTOR.remove(scope.getName()); } - Injector parentInjector = injector.getParentInjector(); - if (parentInjector != null) { - parentInjector.removeChild(injector); + Scope parentScope = scope.getParentScope(); + if (parentScope != null) { + parentScope.removeChild(scope); } } public static void reset() { MAP_KEY_TO_INJECTOR.clear(); } + + public static void inject(Object obj, Scope scope) { + injector.inject(obj, scope); + } } diff --git a/toothpick-runtime/src/test/java/toothpick/InjectorImplTest.java b/toothpick-runtime/src/test/java/toothpick/ScopeImplTest.java similarity index 67% rename from toothpick-runtime/src/test/java/toothpick/InjectorImplTest.java rename to toothpick-runtime/src/test/java/toothpick/ScopeImplTest.java index a83f4645..4f7a99c9 100644 --- a/toothpick-runtime/src/test/java/toothpick/InjectorImplTest.java +++ b/toothpick-runtime/src/test/java/toothpick/ScopeImplTest.java @@ -10,17 +10,17 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; -public class InjectorImplTest extends ToothPickBaseTest { +public class ScopeImplTest extends ToothPickBaseTest { @Test(expected = IllegalArgumentException.class) public void toProvider_shoudThrowException_whenBindingIsNull() throws Exception { //GIVEN Module module = new Module(); module.getBindingSet().add(null); - InjectorImpl injector = new InjectorImpl(module); + ScopeImpl scope = new ScopeImpl(module); //WHEN - injector.getInstance(null); + scope.getInstance(null); //THEN fail("Should not allow null bindings"); @@ -32,11 +32,11 @@ public void toProvider_shoudThrowException_whenBindingIsNull() throws Exception public void installOverrideModules_shoudInstallOverrideBindings_whenCalledOnce() { //GIVEN Foo testFoo = new Foo(); - InjectorImpl injector = new InjectorImpl(new ProdModule()); - injector.installTestModules(new TestModule(testFoo)); + ScopeImpl scope = new ScopeImpl(new ProdModule()); + scope.installTestModules(new TestModule(testFoo)); //WHEN - Foo instance = injector.getInstance(Foo.class); + Foo instance = scope.getInstance(Foo.class); //THEN assertThat(instance, sameInstance(testFoo)); @@ -45,11 +45,11 @@ public void installOverrideModules_shoudInstallOverrideBindings_whenCalledOnce() @Test public void installOverrideModules_shoudNotInstallOverrideBindings_whenCalledWithoutTestModules() { //GIVEN - InjectorImpl injector = new InjectorImpl(new ProdModule()); - injector.installTestModules(); + ScopeImpl scope = new ScopeImpl(new ProdModule()); + scope.installTestModules(); //WHEN - Foo instance = injector.getInstance(Foo.class); + Foo instance = scope.getInstance(Foo.class); //THEN assertThat(instance, notNullValue()); @@ -60,12 +60,12 @@ public void installOverrideModules_shoudInstallOverrideBindingsAgain_whenCalledT //GIVEN Foo testFoo = new Foo(); Foo testFoo2 = new Foo(); - InjectorImpl injector = new InjectorImpl(new ProdModule()); - injector.installTestModules(new TestModule(testFoo)); - injector.installTestModules(new TestModule(testFoo2)); + ScopeImpl scope = new ScopeImpl(new ProdModule()); + scope.installTestModules(new TestModule(testFoo)); + scope.installTestModules(new TestModule(testFoo2)); //WHEN - Foo instance = injector.getInstance(Foo.class); + Foo instance = scope.getInstance(Foo.class); //THEN assertThat(instance, sameInstance(testFoo2)); @@ -75,12 +75,12 @@ public void installOverrideModules_shoudInstallOverrideBindingsAgain_whenCalledT public void installOverrideModules_shoudNotOverrideOtherBindings() { //GIVEN Foo testFoo = new Foo(); - InjectorImpl injector = new InjectorImpl(new ProdModule2()); - injector.installTestModules(new TestModule(testFoo)); + ScopeImpl scope = new ScopeImpl(new ProdModule2()); + scope.installTestModules(new TestModule(testFoo)); //WHEN - Foo fooInstance = injector.getInstance(Foo.class); - Bar barInstance = injector.getInstance(Bar.class); + Foo fooInstance = scope.getInstance(Foo.class); + Bar barInstance = scope.getInstance(Bar.class); //THEN assertThat(fooInstance, sameInstance(testFoo)); diff --git a/toothpick-runtime/src/test/java/toothpick/ToothPickBaseTest.java b/toothpick-runtime/src/test/java/toothpick/ToothPickBaseTest.java index 8d3c175f..2387e1b3 100644 --- a/toothpick-runtime/src/test/java/toothpick/ToothPickBaseTest.java +++ b/toothpick-runtime/src/test/java/toothpick/ToothPickBaseTest.java @@ -2,13 +2,14 @@ import org.junit.BeforeClass; import toothpick.registries.factory.FactoryRegistryLocator; -import toothpick.registries.memberinjector.MemberInjectorRegistryLocator; +import toothpick.registries.memberscope.MemberInjectorRegistryLocator; public class ToothPickBaseTest { protected ToothPickBaseTest() { } - @BeforeClass public static void setUp() throws Exception { + @BeforeClass + public static void setUp() throws Exception { MemberInjectorRegistryLocator.addRegistry(new toothpick.test.MemberInjectorRegistry()); FactoryRegistryLocator.addRegistry(new toothpick.test.FactoryRegistry()); } diff --git a/toothpick-runtime/src/test/java/toothpick/ToothPickTest.java b/toothpick-runtime/src/test/java/toothpick/ToothPickTest.java index 4526286b..44c232c0 100644 --- a/toothpick-runtime/src/test/java/toothpick/ToothPickTest.java +++ b/toothpick-runtime/src/test/java/toothpick/ToothPickTest.java @@ -15,106 +15,106 @@ public class ToothPickTest extends ToothPickBaseTest { @Test - public void getInjector_shouldNotReturnNull_whenNoInjectorByThisKeyWasCreated() throws Exception { + public void getScope_shouldNotReturnNull_whenNoScopeByThisKeyWasCreated() throws Exception { //GIVEN //WHEN - Injector injector = ToothPick.openInjector(this); + Scope scope = ToothPick.openScope(this); //THEN - assertThat(injector, notNullValue()); + assertThat(scope, notNullValue()); } @Test - public void getInjector_shouldReturnAnInjector_whenThisInjectorByThisKeyWasCreated() throws Exception { + public void getScope_shouldReturnAnScope_whenThisScopeByThisKeyWasCreated() throws Exception { //GIVEN - Injector injector = ToothPick.openInjector(this); + Scope scope = ToothPick.openScope(this); //WHEN - Injector injector2 = ToothPick.openInjector(this); + Scope scope2 = ToothPick.openScope(this); //THEN - assertThat(injector, notNullValue()); - assertThat(injector, sameInstance(injector2)); + assertThat(scope, notNullValue()); + assertThat(scope, sameInstance(scope2)); } @Test - public void createInjector_shouldReturnAnInjectorWithAParent_whenThisInjectorByThisKeyWasCreatedWithAParent() throws Exception { + public void createScope_shouldReturnAnScopeWithAParent_whenThisScopeByThisKeyWasCreatedWithAParent() throws Exception { //GIVEN - Injector injectorParent = ToothPick.openInjector("foo"); + Scope scopeParent = ToothPick.openScope("foo"); //WHEN - Injector injector = ToothPick.openInjector("bar"); - injectorParent.addChild(injector); + Scope scope = ToothPick.openScope("bar"); + scopeParent.addChild(scope); //THEN - assertThat(injector, notNullValue()); - assertThat(injector.getParentInjector(), sameInstance(injectorParent)); + assertThat(scope, notNullValue()); + assertThat(scope.getParentScope(), sameInstance(scopeParent)); } @Test - public void reset_shouldClear_WhenSomeInjectorsWereCreated() throws Exception { + public void reset_shouldClear_WhenSomeScopesWereCreated() throws Exception { //GIVEN - Injector injector0 = ToothPick.openInjector("foo"); - Injector injector1 = ToothPick.openInjector("bar"); + Scope scope0 = ToothPick.openScope("foo"); + Scope scope1 = ToothPick.openScope("bar"); //WHEN ToothPick.reset(); - Injector injector0AfterReset = ToothPick.openInjector("foo"); - Injector injector1AfterReset = ToothPick.openInjector("bar"); + Scope scope0AfterReset = ToothPick.openScope("foo"); + Scope scope1AfterReset = ToothPick.openScope("bar"); //THEN - assertThat(injector0AfterReset, not(sameInstance(injector0))); - assertThat(injector1AfterReset, not(sameInstance(injector1))); + assertThat(scope0AfterReset, not(sameInstance(scope0))); + assertThat(scope1AfterReset, not(sameInstance(scope1))); } @Test - public void destroyInjector_shouldClearThisInjector_WhenThisInjectorsWasCreated() throws Exception { + public void destroyScope_shouldClearThisScope_WhenThisScopesWasCreated() throws Exception { //GIVEN - Injector injector = ToothPick.openInjector("foo"); + Scope scope = ToothPick.openScope("foo"); //WHEN - ToothPick.closeInjector("foo"); - Injector injectorAfterReset = ToothPick.openInjector("foo"); + ToothPick.closeScope("foo"); + Scope scopeAfterReset = ToothPick.openScope("foo"); //THEN - assertThat(injectorAfterReset, not(sameInstance(injector))); + assertThat(scopeAfterReset, not(sameInstance(scope))); } @Test - public void getOrCreateInjector_shouldReturnSameInjector_WhenOneWasCreatedWithSameKey() throws Exception { + public void getOrCreateScope_shouldReturnSameScope_WhenOneWasCreatedWithSameKey() throws Exception { //GIVEN - Injector injector = ToothPick.openInjector("foo"); + Scope scope = ToothPick.openScope("foo"); //WHEN - Injector injector2 = ToothPick.openInjector("foo"); + Scope scope2 = ToothPick.openScope("foo"); //THEN - assertThat(injector, sameInstance(injector2)); + assertThat(scope, sameInstance(scope2)); } @Test - public void getOrCreateInjector_shouldReturnANewInjectorInjector_WhenOneWasNotCreatedWithSameKey() throws Exception { + public void getOrCreateScope_shouldReturnANewScopeScope_WhenOneWasNotCreatedWithSameKey() throws Exception { //GIVEN - Injector injectorParent = ToothPick.openInjector("bar"); + Scope scopeParent = ToothPick.openScope("bar"); //WHEN - Injector injector = ToothPick.openInjector("foo"); - injectorParent.addChild(injector); - Injector injector2 = ToothPick.openInjector("foo"); + Scope scope = ToothPick.openScope("foo"); + scopeParent.addChild(scope); + Scope scope2 = ToothPick.openScope("foo"); //THEN - assertThat(injector, notNullValue()); - assertThat(injector2, sameInstance(injector)); - assertThat(injector.getParentInjector(), sameInstance(injectorParent)); + assertThat(scope, notNullValue()); + assertThat(scope2, sameInstance(scope)); + assertThat(scope.getParentScope(), sameInstance(scopeParent)); } @Test - public void destroyInjector_shouldNotFail_WhenThisInjectorsWasNotCreated() throws Exception { + public void destroyScope_shouldNotFail_WhenThisScopesWasNotCreated() throws Exception { //GIVEN //WHEN - ToothPick.closeInjector("foo"); + ToothPick.closeScope("foo"); //THEN } diff --git a/toothpick-runtime/src/test/java/toothpick/bindings/AllBindingsTest.java b/toothpick-runtime/src/test/java/toothpick/bindings/AllBindingsTest.java index 0c088490..cc229739 100644 --- a/toothpick-runtime/src/test/java/toothpick/bindings/AllBindingsTest.java +++ b/toothpick-runtime/src/test/java/toothpick/bindings/AllBindingsTest.java @@ -2,8 +2,8 @@ import javax.inject.Provider; import org.junit.Test; -import toothpick.Injector; -import toothpick.InjectorImpl; +import toothpick.Scope; +import toothpick.ScopeImpl; import toothpick.ToothPickBaseTest; import toothpick.config.Module; import toothpick.data.Bar; @@ -45,16 +45,16 @@ public class AllBindingsTest extends ToothPickBaseTest { @Test public void simpleBinding_shouldCreateInjectedInstances_whenNotSingleton() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(Foo.class); } }); //WHEN - Foo foo = injector.getInstance(Foo.class); - Foo foo2 = injector.getInstance(Foo.class); + Foo foo = scope.getInstance(Foo.class); + Foo foo2 = scope.getInstance(Foo.class); //THEN assertThat(foo, notNullValue()); @@ -66,16 +66,16 @@ public void simpleBinding_shouldCreateInjectedInstances_whenNotSingleton() throw @Test public void simpleBinding_shouldCreateInjectedSingletons_whenSingleton() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(FooSingleton.class); } }); //WHEN - FooSingleton foo = injector.getInstance(FooSingleton.class); - FooSingleton foo2 = injector.getInstance(FooSingleton.class); + FooSingleton foo = scope.getInstance(FooSingleton.class); + FooSingleton foo2 = scope.getInstance(FooSingleton.class); //THEN assertThat(foo, notNullValue()); @@ -88,16 +88,16 @@ public void simpleBinding_shouldCreateInjectedSingletons_whenSingleton() throws public void singletonBinding_shouldCreateNonInjectedSingleton() throws Exception { //GIVEN final Foo instance = new Foo(); - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(Foo.class).to(instance); } }); //WHEN - Foo foo = injector.getInstance(Foo.class); - Foo foo2 = injector.getInstance(Foo.class); + Foo foo = scope.getInstance(Foo.class); + Foo foo2 = scope.getInstance(Foo.class); //THEN assertThat(foo, notNullValue()); @@ -109,16 +109,16 @@ public void singletonBinding_shouldCreateNonInjectedSingleton() throws Exception @Test public void bindToClass_shouldCreateInjectedInstances_whenBoundClassNotAnnotatedSingleton() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(IFoo.class).to(Foo.class); } }); //WHEN - IFoo foo = injector.getInstance(IFoo.class); - IFoo foo2 = injector.getInstance(IFoo.class); + IFoo foo = scope.getInstance(IFoo.class); + IFoo foo2 = scope.getInstance(IFoo.class); //THEN assertThat(foo, notNullValue()); @@ -134,16 +134,16 @@ public void bindToClass_shouldCreateInjectedInstances_whenBoundClassNotAnnotated @Test public void bindToClass_shouldCreateInjectedSingletons_whenBoundClassAnnotatedSingleton() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(IFooSingleton.class).to(FooSingleton.class); } }); //WHEN - FooSingleton foo = injector.getInstance(FooSingleton.class); - FooSingleton foo2 = injector.getInstance(FooSingleton.class); + FooSingleton foo = scope.getInstance(FooSingleton.class); + FooSingleton foo2 = scope.getInstance(FooSingleton.class); //THEN assertThat(foo, notNullValue()); @@ -160,16 +160,16 @@ public void bindToProviderInstance_shouldCreateNonInjectedInstances() throws Exc //GIVEN final Provider providerInstance = new IFooProvider(); - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(IFoo.class).toProvider(providerInstance); } }); //WHEN - IFoo foo = injector.getInstance(IFoo.class); - IFoo foo2 = injector.getInstance(IFoo.class); + IFoo foo = scope.getInstance(IFoo.class); + IFoo foo2 = scope.getInstance(IFoo.class); //THEN assertThat(foo, notNullValue()); @@ -182,16 +182,16 @@ public void bindToProviderInstance_shouldCreateNonInjectedInstances() throws Exc @Test public void bindToProviderClass_shouldCreateNonInjectedInstances_whenProviderClassIsNotAnnotated() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(IFoo.class).toProvider(IFooProvider.class); } }); //WHEN - IFoo foo = injector.getInstance(IFoo.class); - IFoo foo2 = injector.getInstance(IFoo.class); + IFoo foo = scope.getInstance(IFoo.class); + IFoo foo2 = scope.getInstance(IFoo.class); //THEN assertThat(foo, notNullValue()); @@ -205,16 +205,16 @@ public void bindToProviderClass_shouldCreateNonInjectedInstances_whenProviderCla @Test public void bindToProviderClass_shouldCreateInjectedProvider() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(IFoo.class).toProvider(IFooWithBarProvider.class); } }); //WHEN - IFoo foo = injector.getInstance(IFoo.class); - IFoo foo2 = injector.getInstance(IFoo.class); + IFoo foo = scope.getInstance(IFoo.class); + IFoo foo2 = scope.getInstance(IFoo.class); //THEN assertThat(foo, notNullValue()); @@ -226,16 +226,16 @@ public void bindToProviderClass_shouldCreateInjectedProvider() throws Exception @Test public void bindToProviderClass_shouldCreateNonInjectedInstancesWithProviderSingleton_whenProviderClassIsAnnotatedSingleton() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(IFoo.class).toProvider(IFooProviderAnnotatedSingleton.class); } }); //WHEN - IFoo foo = injector.getInstance(IFoo.class); - IFoo foo2 = injector.getInstance(IFoo.class); + IFoo foo = scope.getInstance(IFoo.class); + IFoo foo2 = scope.getInstance(IFoo.class); //THEN assertThat(foo, notNullValue()); @@ -247,16 +247,16 @@ public void bindToProviderClass_shouldCreateNonInjectedInstancesWithProviderSing @Test public void bindToProviderClass_shouldCreateNonInjectedSingleton_whenProviderClassIsAnnotatedProvidesSingleton() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(IFoo.class).toProvider(IFooProviderAnnotatedProvidesSingleton.class); } }); //WHEN - IFoo foo = injector.getInstance(IFoo.class); - IFoo foo2 = injector.getInstance(IFoo.class); + IFoo foo = scope.getInstance(IFoo.class); + IFoo foo2 = scope.getInstance(IFoo.class); //THEN assertThat(foo, notNullValue()); diff --git a/toothpick-runtime/src/test/java/toothpick/getInstance/SimpleInstanceCreationWithModuleTest.java b/toothpick-runtime/src/test/java/toothpick/getInstance/SimpleInstanceCreationWithModuleTest.java index 59906301..3df13f18 100644 --- a/toothpick-runtime/src/test/java/toothpick/getInstance/SimpleInstanceCreationWithModuleTest.java +++ b/toothpick-runtime/src/test/java/toothpick/getInstance/SimpleInstanceCreationWithModuleTest.java @@ -1,8 +1,8 @@ package toothpick.getInstance; import org.junit.Test; -import toothpick.Injector; -import toothpick.InjectorImpl; +import toothpick.Scope; +import toothpick.ScopeImpl; import toothpick.ToothPickBaseTest; import toothpick.config.Module; import toothpick.data.Foo; @@ -18,24 +18,26 @@ */ public class SimpleInstanceCreationWithModuleTest extends ToothPickBaseTest { - @Test public void testSimpleInjection() throws Exception { + @Test + public void testSimpleInjection() throws Exception { //GIVEN - Injector injector = new InjectorImpl(new SimpleModule()); + Scope scope = new ScopeImpl(new SimpleModule()); //WHEN - Foo instance = injector.getInstance(Foo.class); + Foo instance = scope.getInstance(Foo.class); //THEN assertThat(instance, notNullValue()); } - @Test public void testSimpleInjectionIsNotProducingSingleton() throws Exception { + @Test + public void testSimpleInjectionIsNotProducingSingleton() throws Exception { //GIVEN - Injector injector = new InjectorImpl(new SimpleModule()); + Scope scope = new ScopeImpl(new SimpleModule()); //WHEN - Foo instance = injector.getInstance(Foo.class); - Foo instance2 = injector.getInstance(Foo.class); + Foo instance = scope.getInstance(Foo.class); + Foo instance2 = scope.getInstance(Foo.class); //THEN assertThat(instance, notNullValue()); diff --git a/toothpick-runtime/src/test/java/toothpick/getInstance/SimpleInstanceCreationWithoutModuleTest.java b/toothpick-runtime/src/test/java/toothpick/getInstance/SimpleInstanceCreationWithoutModuleTest.java index 43cec0bd..7baa7405 100644 --- a/toothpick-runtime/src/test/java/toothpick/getInstance/SimpleInstanceCreationWithoutModuleTest.java +++ b/toothpick-runtime/src/test/java/toothpick/getInstance/SimpleInstanceCreationWithoutModuleTest.java @@ -1,8 +1,8 @@ package toothpick.getInstance; import org.junit.Test; -import toothpick.Injector; -import toothpick.InjectorImpl; +import toothpick.Scope; +import toothpick.ScopeImpl; import toothpick.ToothPickBaseTest; import toothpick.data.Foo; @@ -20,10 +20,10 @@ public class SimpleInstanceCreationWithoutModuleTest extends ToothPickBaseTest { @Test public void testSimpleInjection() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); + Scope scope = new ScopeImpl(""); //WHEN - Foo instance = injector.getInstance(Foo.class); + Foo instance = scope.getInstance(Foo.class); //THEN assertThat(instance, notNullValue()); @@ -32,11 +32,11 @@ public void testSimpleInjection() throws Exception { @Test public void testSimpleInjectionIsNotProducingSingleton() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); + Scope scope = new ScopeImpl(""); //WHEN - Foo instance = injector.getInstance(Foo.class); - Foo instance2 = injector.getInstance(Foo.class); + Foo instance = scope.getInstance(Foo.class); + Foo instance2 = scope.getInstance(Foo.class); //THEN assertThat(instance, notNullValue()); diff --git a/toothpick-runtime/src/test/java/toothpick/getInstance/SingletonCreationWithModuleTest.java b/toothpick-runtime/src/test/java/toothpick/getInstance/SingletonCreationWithModuleTest.java index 5380e4a6..2a1da664 100644 --- a/toothpick-runtime/src/test/java/toothpick/getInstance/SingletonCreationWithModuleTest.java +++ b/toothpick-runtime/src/test/java/toothpick/getInstance/SingletonCreationWithModuleTest.java @@ -1,8 +1,8 @@ package toothpick.getInstance; import org.junit.Test; -import toothpick.Injector; -import toothpick.InjectorImpl; +import toothpick.Scope; +import toothpick.ScopeImpl; import toothpick.ToothPickBaseTest; import toothpick.config.Module; import toothpick.data.FooSingleton; @@ -17,13 +17,14 @@ */ public class SingletonCreationWithModuleTest extends ToothPickBaseTest { - @Test public void testIsProducingSingleton() throws Exception { + @Test + public void testIsProducingSingleton() throws Exception { //GIVEN - Injector injector = new InjectorImpl(new SimpleModule()); + Scope scope = new ScopeImpl(new SimpleModule()); //WHEN - FooSingleton instance = injector.getInstance(FooSingleton.class); - FooSingleton instance2 = injector.getInstance(FooSingleton.class); + FooSingleton instance = scope.getInstance(FooSingleton.class); + FooSingleton instance2 = scope.getInstance(FooSingleton.class); //THEN assertThat(instance, notNullValue()); diff --git a/toothpick-runtime/src/test/java/toothpick/getInstance/SingletonCreationWithoutModuleTest.java b/toothpick-runtime/src/test/java/toothpick/getInstance/SingletonCreationWithoutModuleTest.java index a083b71c..b3614171 100644 --- a/toothpick-runtime/src/test/java/toothpick/getInstance/SingletonCreationWithoutModuleTest.java +++ b/toothpick-runtime/src/test/java/toothpick/getInstance/SingletonCreationWithoutModuleTest.java @@ -1,8 +1,8 @@ package toothpick.getInstance; import org.junit.Test; -import toothpick.Injector; -import toothpick.InjectorImpl; +import toothpick.Scope; +import toothpick.ScopeImpl; import toothpick.ToothPickBaseTest; import toothpick.data.FooSingleton; @@ -19,11 +19,11 @@ public class SingletonCreationWithoutModuleTest extends ToothPickBaseTest { @Test public void testIsProducingSingleton() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); + Scope scope = new ScopeImpl(""); //WHEN - FooSingleton instance = injector.getInstance(FooSingleton.class); - FooSingleton instance2 = injector.getInstance(FooSingleton.class); + FooSingleton instance = scope.getInstance(FooSingleton.class); + FooSingleton instance2 = scope.getInstance(FooSingleton.class); //THEN assertThat(instance, notNullValue()); diff --git a/toothpick-runtime/src/test/java/toothpick/getInstance/inject/CreatedInstancesAreInjectedWhenNeeded.java b/toothpick-runtime/src/test/java/toothpick/getInstance/inject/CreatedInstancesAreInjectedWhenNeeded.java index 5d0424c2..32ef5f38 100644 --- a/toothpick-runtime/src/test/java/toothpick/getInstance/inject/CreatedInstancesAreInjectedWhenNeeded.java +++ b/toothpick-runtime/src/test/java/toothpick/getInstance/inject/CreatedInstancesAreInjectedWhenNeeded.java @@ -2,8 +2,8 @@ import javax.inject.Provider; import org.junit.Test; -import toothpick.Injector; -import toothpick.InjectorImpl; +import toothpick.Scope; +import toothpick.ScopeImpl; import toothpick.ToothPickBaseTest; import toothpick.config.Module; import toothpick.data.Bar; @@ -24,15 +24,15 @@ public class CreatedInstancesAreInjectedWhenNeeded extends ToothPickBaseTest { @Test public void createdInstance_shouldBeInjected_whenBindingToAClassWithInjectFields() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(Foo.class).to(Foo.class); } }); //WHEN - Foo foo = injector.getInstance(Foo.class); + Foo foo = scope.getInstance(Foo.class); //THEN assertThat(foo.bar, notNullValue()); @@ -42,8 +42,8 @@ public void createdInstance_shouldBeInjected_whenBindingToAClassWithInjectFields @Test public void createdInstance_shouldNotBeInjected_whenBindingToAProvider() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(Foo.class).toProvider(new Provider() { @Override @@ -55,7 +55,7 @@ public Foo get() { }); //WHEN - Foo foo = injector.getInstance(Foo.class); + Foo foo = scope.getInstance(Foo.class); //THEN assertThat(foo.bar, nullValue()); @@ -64,15 +64,15 @@ public Foo get() { @Test public void createdInstance_shouldNotBeInjected_whenBindingToAProviderClass() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(Foo.class).toProvider(FooProvider.class); } }); //WHEN - Foo foo = injector.getInstance(Foo.class); + Foo foo = scope.getInstance(Foo.class); //THEN assertThat(foo.bar, nullValue()); @@ -81,15 +81,15 @@ public void createdInstance_shouldNotBeInjected_whenBindingToAProviderClass() th @Test public void createdProvider_shouldBeInjected_whenBindingToAProviderClassThatHasInjectedFields() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scope.installModules(new Module() { { bind(Foo.class).toProvider(FooProvider.class); } }); //WHEN - Foo foo = injector.getInstance(Foo.class); + Foo foo = scope.getInstance(Foo.class); //THEN assertThat(foo.bar, nullValue()); diff --git a/toothpick-runtime/src/test/java/toothpick/inject/InjectionAndInheritanceTest.java b/toothpick-runtime/src/test/java/toothpick/inject/InjectionAndInheritanceTest.java index 7eaa4ce4..1a0ef7d9 100644 --- a/toothpick-runtime/src/test/java/toothpick/inject/InjectionAndInheritanceTest.java +++ b/toothpick-runtime/src/test/java/toothpick/inject/InjectionAndInheritanceTest.java @@ -1,8 +1,9 @@ package toothpick.inject; import org.junit.Test; -import toothpick.Injector; -import toothpick.InjectorImpl; +import toothpick.Scope; +import toothpick.ScopeImpl; +import toothpick.ToothPick; import toothpick.ToothPickBaseTest; import toothpick.data.Bar; import toothpick.data.FooChildWithInjectedFields; @@ -20,11 +21,11 @@ public class InjectionAndInheritanceTest extends ToothPickBaseTest { @Test public void inject_shouldInjectInheritedFields_whenParentDefinesInjectAnnotatedFields() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); + Scope scope = new ScopeImpl(""); FooChildWithInjectedFields foo = new FooChildWithInjectedFields(); //WHEN - injector.inject(foo); + ToothPick.inject(foo, scope); //THEN assertThat(foo.bar2, notNullValue()); @@ -36,11 +37,11 @@ public void inject_shouldInjectInheritedFields_whenParentDefinesInjectAnnotatedF @Test public void inject_shouldInjectInheritedFields_whenGrandParentDefinesInjectAnnotatedFieldsButNotParent() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); + Scope scope = new ScopeImpl(""); FooGrandChildWithInjectedFields foo = new FooGrandChildWithInjectedFields(); //WHEN - injector.inject(foo); + ToothPick.inject(foo, scope); //THEN assertThat(foo.bar2, notNullValue()); diff --git a/toothpick-runtime/src/test/java/toothpick/inject/InjectionWithoutModuleTest.java b/toothpick-runtime/src/test/java/toothpick/inject/InjectionWithoutModuleTest.java index 738d8135..18c7a4f6 100644 --- a/toothpick-runtime/src/test/java/toothpick/inject/InjectionWithoutModuleTest.java +++ b/toothpick-runtime/src/test/java/toothpick/inject/InjectionWithoutModuleTest.java @@ -1,8 +1,9 @@ package toothpick.inject; import org.junit.Test; -import toothpick.Injector; -import toothpick.InjectorImpl; +import toothpick.Scope; +import toothpick.ScopeImpl; +import toothpick.ToothPick; import toothpick.ToothPickBaseTest; import toothpick.data.Bar; import toothpick.data.Foo; @@ -20,11 +21,11 @@ public class InjectionWithoutModuleTest extends ToothPickBaseTest { @Test public void testSimpleInjection() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); + Scope scope = new ScopeImpl(""); Foo foo = new Foo(); //WHEN - injector.inject(foo); + ToothPick.inject(foo, scope); //THEN assertThat(foo.bar, notNullValue()); diff --git a/toothpick-runtime/src/test/java/toothpick/inject/future/InjectionOfFutureProviderTest.java b/toothpick-runtime/src/test/java/toothpick/inject/future/InjectionOfFutureProviderTest.java index 4f9e360a..f4818950 100644 --- a/toothpick-runtime/src/test/java/toothpick/inject/future/InjectionOfFutureProviderTest.java +++ b/toothpick-runtime/src/test/java/toothpick/inject/future/InjectionOfFutureProviderTest.java @@ -2,8 +2,9 @@ import java.util.concurrent.Future; import org.junit.Test; -import toothpick.Injector; -import toothpick.InjectorImpl; +import toothpick.Scope; +import toothpick.ScopeImpl; +import toothpick.ToothPick; import toothpick.ToothPickBaseTest; import toothpick.data.Bar; import toothpick.data.FooWithFuture; @@ -21,11 +22,11 @@ public class InjectionOfFutureProviderTest extends ToothPickBaseTest { @Test public void testSimpleInjection() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); + Scope scope = new ScopeImpl(""); FooWithFuture fooWithFuture = new FooWithFuture(); //WHEN - injector.inject(fooWithFuture); + ToothPick.inject(fooWithFuture, scope); //THEN assertThat(fooWithFuture.bar, notNullValue()); diff --git a/toothpick-runtime/src/test/java/toothpick/inject/lazy/InjectionOfLazyProviderTest.java b/toothpick-runtime/src/test/java/toothpick/inject/lazy/InjectionOfLazyProviderTest.java index fac9922e..d89ce93a 100644 --- a/toothpick-runtime/src/test/java/toothpick/inject/lazy/InjectionOfLazyProviderTest.java +++ b/toothpick-runtime/src/test/java/toothpick/inject/lazy/InjectionOfLazyProviderTest.java @@ -1,9 +1,10 @@ package toothpick.inject.lazy; import org.junit.Test; -import toothpick.Injector; -import toothpick.InjectorImpl; import toothpick.Lazy; +import toothpick.Scope; +import toothpick.ScopeImpl; +import toothpick.ToothPick; import toothpick.ToothPickBaseTest; import toothpick.data.Bar; import toothpick.data.FooWithLazy; @@ -21,11 +22,11 @@ public class InjectionOfLazyProviderTest extends ToothPickBaseTest { @Test public void testSimpleInjection() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); + Scope scope = new ScopeImpl(""); FooWithLazy fooWithLazy = new FooWithLazy(); //WHEN - injector.inject(fooWithLazy); + ToothPick.inject(fooWithLazy, scope); //THEN assertThat(fooWithLazy.bar, notNullValue()); diff --git a/toothpick-runtime/src/test/java/toothpick/inject/provider/InjectionOfProviderTest.java b/toothpick-runtime/src/test/java/toothpick/inject/provider/InjectionOfProviderTest.java index da035658..b3d77e05 100644 --- a/toothpick-runtime/src/test/java/toothpick/inject/provider/InjectionOfProviderTest.java +++ b/toothpick-runtime/src/test/java/toothpick/inject/provider/InjectionOfProviderTest.java @@ -2,8 +2,9 @@ import javax.inject.Provider; import org.junit.Test; -import toothpick.Injector; -import toothpick.InjectorImpl; +import toothpick.Scope; +import toothpick.ScopeImpl; +import toothpick.ToothPick; import toothpick.ToothPickBaseTest; import toothpick.data.Bar; import toothpick.data.FooSingleton; @@ -24,11 +25,11 @@ public class InjectionOfProviderTest extends ToothPickBaseTest { @Test public void testSimpleInjection_shouldReturnAProviderOfInstances_whenInjectedClassIsNotAnnotatedWithSingleton() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); + Scope scope = new ScopeImpl(""); FooWithProvider fooWithProvider = new FooWithProvider(); //WHEN - injector.inject(fooWithProvider); + ToothPick.inject(fooWithProvider, scope); //THEN assertThat(fooWithProvider.bar, notNullValue()); @@ -43,11 +44,11 @@ public void testSimpleInjection_shouldReturnAProviderOfInstances_whenInjectedCla @Test public void testSimpleInjection_shouldReturnAProviderOfSingleton_whenInjectedClassIsAnnotatedWithSingleton() throws Exception { //GIVEN - Injector injector = new InjectorImpl(""); + Scope scope = new ScopeImpl(""); FooWithProviderOfSingleton fooWithProviderOfSingleton = new FooWithProviderOfSingleton(); //WHEN - injector.inject(fooWithProviderOfSingleton); + ToothPick.inject(fooWithProviderOfSingleton, scope); //THEN assertThat(fooWithProviderOfSingleton.fooSingletonProvider, notNullValue()); diff --git a/toothpick-runtime/src/test/java/toothpick/scoping/ScopingTest.java b/toothpick-runtime/src/test/java/toothpick/scoping/ScopingTest.java index e2de43a0..f4f7be07 100644 --- a/toothpick-runtime/src/test/java/toothpick/scoping/ScopingTest.java +++ b/toothpick-runtime/src/test/java/toothpick/scoping/ScopingTest.java @@ -1,8 +1,8 @@ package toothpick.scoping; import org.junit.Test; -import toothpick.Injector; -import toothpick.InjectorImpl; +import toothpick.Scope; +import toothpick.ScopeImpl; import toothpick.ToothPickBaseTest; import toothpick.config.Module; import toothpick.data.Foo; @@ -22,23 +22,23 @@ public class ScopingTest extends ToothPickBaseTest { public void childInjector_shouldReturnInstancesInItsScope_whenParentAlsoHasSameKeyInHisScope() throws Exception { //GIVEN final Foo foo1 = new Foo(); - Injector injectorParent = new InjectorImpl(""); - injectorParent.installModules(new Module() { + Scope scopeParent = new ScopeImpl(""); + scopeParent.installModules(new Module() { { bind(Foo.class).to(foo1); } }); final Foo foo2 = new Foo(); - Injector injector = new InjectorImpl(""); - injectorParent.addChild(injector); - injector.installModules(new Module() { + Scope scope = new ScopeImpl(""); + scopeParent.addChild(scope); + scope.installModules(new Module() { { bind(Foo.class).to(foo2); } }); //WHEN - Foo instance = injector.getInstance(Foo.class); + Foo instance = scope.getInstance(Foo.class); //THEN assertThat(foo2, sameInstance(instance)); @@ -49,18 +49,18 @@ public void childInjector_shouldReturnInstancesInItsScope_whenParentAlsoHasSameK public void childInjector_shouldReturnInstancesInParentScope_whenParentHasKeyInHisScope() throws Exception { //GIVEN final Foo foo1 = new Foo(); - Injector injectorParent = new InjectorImpl(""); - injectorParent.installModules(new Module() { + Scope scopeParent = new ScopeImpl(""); + scopeParent.installModules(new Module() { { bind(Foo.class).to(foo1); } }); - Injector injector = new InjectorImpl(""); - injectorParent.addChild(injector); + Scope scope = new ScopeImpl(""); + scopeParent.addChild(scope); //WHEN - Foo instance = injector.getInstance(Foo.class); - Foo instance2 = injectorParent.getInstance(Foo.class); + Foo instance = scope.getInstance(Foo.class); + Foo instance2 = scopeParent.getInstance(Foo.class); //THEN assertThat(foo1, sameInstance(instance)); @@ -70,13 +70,13 @@ public void childInjector_shouldReturnInstancesInParentScope_whenParentHasKeyInH @Test public void singletonDiscoveredDynamically_shouldGoInRootScope() throws Exception { //GIVEN - Injector injectorParent = new InjectorImpl(""); - Injector injector = new InjectorImpl(""); - injectorParent.addChild(injector); + Scope scopeParent = new ScopeImpl(""); + Scope scope = new ScopeImpl(""); + scopeParent.addChild(scope); //WHEN - FooSingleton instance = injector.getInstance(FooSingleton.class); - FooSingleton instance2 = injectorParent.getInstance(FooSingleton.class); + FooSingleton instance = scope.getInstance(FooSingleton.class); + FooSingleton instance2 = scopeParent.getInstance(FooSingleton.class); //THEN assertThat(instance, sameInstance(instance2)); diff --git a/toothpick-sample/src/main/java/toothpick/sample/SimpleEntryPoint.java b/toothpick-sample/src/main/java/toothpick/sample/SimpleEntryPoint.java index d4df59d1..39c07bd8 100644 --- a/toothpick-sample/src/main/java/toothpick/sample/SimpleEntryPoint.java +++ b/toothpick-sample/src/main/java/toothpick/sample/SimpleEntryPoint.java @@ -1,7 +1,7 @@ package toothpick.sample; import javax.inject.Inject; -import toothpick.Injector; +import toothpick.Scope; import toothpick.ToothPick; public class SimpleEntryPoint { @@ -15,8 +15,8 @@ public void setComputer2(Computer2 computer2) { } public SimpleEntryPoint() { - Injector injector = ToothPick.openInjector("SimpleEntryPoint"); - injector.inject(this); + Scope scope = ToothPick.openScope("SimpleEntryPoint"); + ToothPick.inject(this, scope); } public int multiply() { diff --git a/toothpick-sample/src/test/java/toothpick/sample/ComputerTest.java b/toothpick-sample/src/test/java/toothpick/sample/ComputerTest.java index 156a4801..a478e624 100644 --- a/toothpick-sample/src/test/java/toothpick/sample/ComputerTest.java +++ b/toothpick-sample/src/test/java/toothpick/sample/ComputerTest.java @@ -7,7 +7,7 @@ import org.junit.Test; import toothpick.ToothPick; import toothpick.registries.factory.FactoryRegistryLocator; -import toothpick.registries.memberinjector.MemberInjectorRegistryLocator; +import toothpick.registries.memberscope.MemberInjectorRegistryLocator; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; @@ -15,7 +15,7 @@ public class ComputerTest { @Rule public EasyMockRule mocks = new EasyMockRule(this); - @TestSubject private Computer computerUnderTest = ToothPick.openInjector("Computer").getInstance(Computer.class); + @TestSubject private Computer computerUnderTest = ToothPick.openScope("Computer").getInstance(Computer.class); @BeforeClass public static void setUp() throws Exception { diff --git a/toothpick-sample/src/test/java/toothpick/sample/SimpleEntryPointTest.java b/toothpick-sample/src/test/java/toothpick/sample/SimpleEntryPointTest.java index a7bb69a4..28290956 100644 --- a/toothpick-sample/src/test/java/toothpick/sample/SimpleEntryPointTest.java +++ b/toothpick-sample/src/test/java/toothpick/sample/SimpleEntryPointTest.java @@ -6,11 +6,11 @@ import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; -import toothpick.Injector; +import toothpick.Scope; import toothpick.ToothPick; import toothpick.config.Module; import toothpick.registries.factory.FactoryRegistryLocator; -import toothpick.registries.memberinjector.MemberInjectorRegistryLocator; +import toothpick.registries.memberscope.MemberInjectorRegistryLocator; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; @@ -38,8 +38,8 @@ public void testMultiply() throws Exception { expect(mockComputer2.compute()).andReturn(4); replay(mockComputer, mockComputer2); - final Injector injector = ToothPick.openInjector("SimpleEntryPoint"); - injector.installTestModules(new TestModule()); + final Scope scope = ToothPick.openScope("SimpleEntryPoint"); + scope.installTestModules(new TestModule()); //WHEN int result = simpleEntryPointUnderTest.multiply(); diff --git a/toothpick/src/main/java/toothpick/Factory.java b/toothpick/src/main/java/toothpick/Factory.java index 5474327b..e079575b 100644 --- a/toothpick/src/main/java/toothpick/Factory.java +++ b/toothpick/src/main/java/toothpick/Factory.java @@ -22,10 +22,10 @@ public interface Factory { * constructor. There must be one and only annotated constructor. * If T has {@link Inject} annotated fields, then the new instance will be injected after creation. * - * @param injector the scope/injector in which to look for all dependencies of the instance T. + * @param scope the scope in which to look for all dependencies of the instance T. * @return a new instance of T, injected if needed. */ - T createInstance(Injector injector); + T createInstance(Scope scope); /** * Signals that the class is annotated with {@link Singleton}. diff --git a/toothpick/src/main/java/toothpick/Injector.java b/toothpick/src/main/java/toothpick/Injector.java index ec863aa8..785e51a4 100644 --- a/toothpick/src/main/java/toothpick/Injector.java +++ b/toothpick/src/main/java/toothpick/Injector.java @@ -1,101 +1,10 @@ package toothpick; -import java.util.ArrayList; -import java.util.Collection; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.Future; -import javax.inject.Provider; -import toothpick.config.Module; - -import static java.lang.String.format; - /** - * Allows to inject members of a given instance, - * create instances of a given class. - * An injector has its own scope. + * Allows to inject members of a given instance. + * An scope works with a scope. */ -public abstract class Injector { - protected Injector parentInjector; - protected Collection childrenInjector = new ArrayList<>(); - protected List parentInjectors = new ArrayList<>(); - protected IdentityHashMap scope = new IdentityHashMap<>(); - protected Object name; - - public Injector(Object name) { - this.name = name; - } - - /** - * @return the parentInjector of this injector. Can be null for a root injector. - */ - public Injector getParentInjector() { - return parentInjector; - } - - public Collection getChildren() { - return childrenInjector; - } - - public Object getName() { - return name; - } - - public void addChild(Injector child) { - if (child == null) { - throw new IllegalArgumentException("Child must be non null."); - } - - if (child.parentInjector != null) { - throw new IllegalStateException(format("Injector %s already has a parent: %s" + child, child.parentInjector)); - } - - childrenInjector.add(child); - child.parentInjector = this; - child.parentInjectors = new ArrayList<>(); - child.parentInjectors.add(this); - child.parentInjectors.addAll(parentInjectors); - } - - public void removeChild(Injector child) { - if (child == null) { - throw new IllegalArgumentException("Child must be non null."); - } - - if (child.parentInjector != this) { - throw new IllegalStateException(format("Injector %s has a different parent: %s" + child, child.parentInjector)); - } - - childrenInjector.remove(child); - //make the ex-child a new root. - child.parentInjectors = new ArrayList<>(); - } - - /** - * @return the root injector of this injector. - * The root injector is the injector itself if the injector has no parent. - * Otherwise, if it has parents, it is the highest parent in the hierarchy of parents. - */ - protected Injector getRootInjector() { - if (parentInjectors.isEmpty()) { - return this; - } - return parentInjectors.get(parentInjectors.size() - 1); - } - - /** - * Obtains the provider of the class {@code clazz} that is scoped in the current scope, if any. - * Ancestors are not taken into account. - * - * @param clazz the class for which to obtain the scoped provider of this injector, if one is scoped. - * @param the type of {@code clazz}. - * @return the scoped provider of this injector, if one is scoped, {@code Null} otherwise. - */ - protected Provider getScopedProvider(Class clazz) { - return scope.get(clazz); - } - +public interface Injector { /** * Injects all fields of an object. This object will be the starting point of an injection sub-graph, i.e. * all dependencies of this object will be injected as well when created. @@ -103,127 +12,5 @@ protected Provider getScopedProvider(Class clazz) { * @param obj the object of which to all fields will be injected. * @param the type of {@code clazz}. */ - public abstract void inject(T obj); - - /** - * Returns the instance of {@code clazz} if one is scoped in the current - * scope, or its ancestors. If there is no such instance, the factory associated - * to the clazz will be used. - * All {@link javax.inject.Inject} annotated fields of the instance are injected after creation. - * If the {@param clazz} is annotated with {@link javax.inject.Singleton} then the created instance - * will be scoped in the root scope of the current scope. - * - * @param clazz the class for which to obtain an instance in the scope of this injector. - * @param the type of {@code clazz}. - * @return a scoped instance or a new one produced by the factory associated to {@code clazz}. - */ - public abstract T getInstance(Class clazz); - - /** - * Returns a {@code Provider} of {@code clazz} if one is scoped in the current - * scope, or its ancestors. If there is no such provider, the factory associated - * to the clazz will be used to create one. - * All {@link javax.inject.Inject} annotated fields of the instance are injected after creation. - * If the {@param clazz} is annotated with {@link javax.inject.Singleton} then the created provider - * will be scoped in the root scope of the current scope. - * - * @param clazz the class for which to obtain a provider in the scope of this injector. - * @param the type of {@code clazz}. - * @return a scoped provider or a new one using the factory associated to {@code clazz}. - */ - public abstract Provider getProvider(Class clazz); - - /** - * Returns a {@code Lazy} of {@code clazz} if one provider is scoped in the current - * scope, or its ancestors. If there is no such provider, the factory associated - * to the clazz will be used to create one. - * All {@link javax.inject.Inject} annotated fields of the instance are injected after creation. - * If the {@param clazz} is annotated with {@link javax.inject.Singleton} then the created provider - * will be scoped in the root scope of the current scope. - * - * @param clazz the class for which to obtain a lazy in the scope of this injector. - * @param the type of {@code clazz}. - * @return a scoped lazy or a new one using the factory associated to {@code clazz}. - * @see #getProvider(Class) - */ - public abstract Lazy getLazy(Class clazz); - - /** - * Returns a {@code Future} of {@code clazz} if one provider is scoped in the current - * scope, or its ancestors. If there is no such provider, the factory associated - * to the clazz will be used to create one. - * All {@link javax.inject.Inject} annotated fields of the instance are injected after creation. - * If the {@param clazz} is annotated with {@link javax.inject.Singleton} then the created provider - * will be scoped in the root scope of the current scope. - * - * All future are executed on a background thread pool. TODO make this configurable. - * - * @param clazz the class for which to obtain a future in the scope of this injector. - * @param the type of {@code clazz}. - * @return a scoped future or a new one using the factory associated to {@code clazz}. - * @see #getProvider(Class) - */ - public abstract Future getFuture(Class clazz); - - /** - * Allows to define test modules. These method should only be used for testing. - * DO NOT USE IT IN PRODUCTION. - * Test modules have precedence over other normal modules, allowing to define stubs/fake/mocks. - * All bindings defined in a test module cannot be overridden by a future call to {@link #installModules(Module...)}. - * But they can still be overridden by a future call to {@link #installTestModules(Module...)}. - * - * @param modules an array of modules that define test bindings. - */ - public abstract void installTestModules(Module... modules); - - /** - * Allows to define modules. - * - * @param modules an array of modules that define bindings. - * @See #installTestModules - */ - public abstract void installModules(Module... modules); - - @Override - public String toString() { - final String branch = "---"; - final char lastNode = '\\'; - final char node = '+'; - final String indent = " "; - - StringBuilder builder = new StringBuilder(); - builder.append(name); - builder.append(':'); - builder.append(System.identityHashCode(this)); - builder.append('\n'); - - builder.append('['); - for (Class aClass : scope.keySet()) { - builder.append(aClass.getName()); - builder.append(','); - } - builder.deleteCharAt(builder.length() - 1); - builder.append(']'); - builder.append('\n'); - - Iterator iterator = childrenInjector.iterator(); - while (iterator.hasNext()) { - Injector injector = iterator.next(); - boolean isLast = !iterator.hasNext(); - builder.append(isLast ? lastNode : node); - builder.append(branch); - String childString = injector.toString(); - String[] split = childString.split("\n"); - for (int i = 0; i < split.length; i++) { - String childLine = split[i]; - if (i != 0) { - builder.append(indent); - } - builder.append(childLine); - builder.append('\n'); - } - } - - return builder.toString(); - } + void inject(T obj, Scope scope); } diff --git a/toothpick/src/main/java/toothpick/MemberInjector.java b/toothpick/src/main/java/toothpick/MemberInjector.java index f18da75e..a5654e68 100644 --- a/toothpick/src/main/java/toothpick/MemberInjector.java +++ b/toothpick/src/main/java/toothpick/MemberInjector.java @@ -2,11 +2,11 @@ /** * Inject member of an instance of a class. - * All injected members are gonna be obtained in the scope of the current injector. + * All injected members are gonna be obtained in the scope of the current scope. * MemberInjector are discovered via a {@link AbstractMemberInjectorRegistry}. * Implementations are generated during annotation processing. * As soon as a class as an {@link javax.inject.Inject} annotated field or method, - * a member injector is created. All classes that need to be injected via toothpick + * a member scope is created. All classes that need to be injected via toothpick * need to be package private, otherwise we will fall back on reflection and emit * a warning at runtime. * @@ -17,7 +17,7 @@ public interface MemberInjector { * Injects all fields of an object. This object will be the starting point of an injection sub-graph. * * @param t the object in which to inject all dependencies. - * @param injector/scope in which all dependencies will be looked for. + * @param scope the scope in which all dependencies of {@code t} will be looked for. */ - void inject(T t, Injector injector); + void inject(T t, Scope scope); } diff --git a/toothpick/src/main/java/toothpick/Scope.java b/toothpick/src/main/java/toothpick/Scope.java new file mode 100644 index 00000000..98b4bc57 --- /dev/null +++ b/toothpick/src/main/java/toothpick/Scope.java @@ -0,0 +1,218 @@ +package toothpick; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.Future; +import javax.inject.Provider; +import toothpick.config.Module; + +import static java.lang.String.format; + +/** + * Allows to create instances of a given class. + */ +public abstract class Scope { + protected Scope parentScope; + protected Collection childrenScopes = new ArrayList<>(); + protected List parentScopes = new ArrayList<>(); + protected IdentityHashMap mapClassesToProviders = new IdentityHashMap<>(); + protected Object name; + + public Scope(Object name) { + this.name = name; + } + + /** + * @return the parentScope of this scope. Can be null for a root scope. + */ + public Scope getParentScope() { + return parentScope; + } + + public Collection getChildren() { + return childrenScopes; + } + + public Object getName() { + return name; + } + + public void addChild(Scope child) { + if (child == null) { + throw new IllegalArgumentException("Child must be non null."); + } + + if (child.parentScope != null && child.parentScope != this) { + throw new IllegalStateException(format("Injector %s already has a parent: %s", child, child.parentScope)); + } + + childrenScopes.add(child); + child.parentScope = this; + child.parentScopes = new ArrayList<>(); + child.parentScopes.add(this); + child.parentScopes.addAll(parentScopes); + } + + public void removeChild(Scope child) { + if (child == null) { + throw new IllegalArgumentException("Child must be non null."); + } + + if (child.parentScope != this) { + throw new IllegalStateException(format("Injector %s has a different parent: %s", child, child.parentScope)); + } + + childrenScopes.remove(child); + //make the ex-child a new root. + child.parentScopes = new ArrayList<>(); + } + + /** + * @return the root scope of this scope. + * The root scope is the scope itself if the scope has no parent. + * Otherwise, if it has parents, it is the highest parent in the hierarchy of parents. + */ + protected Scope getRootScope() { + if (parentScopes.isEmpty()) { + return this; + } + return parentScopes.get(parentScopes.size() - 1); + } + + /** + * Obtains the provider of the class {@code clazz} that is scoped in the current scope, if any. + * Ancestors are not taken into account. + * + * @param clazz the class for which to obtain the scoped provider of this scope, if one is scoped. + * @param the type of {@code clazz}. + * @return the scoped provider of this scope, if one is scoped, {@code Null} otherwise. + */ + protected Provider getScopedProvider(Class clazz) { + return mapClassesToProviders.get(clazz); + } + + /** + * Returns the instance of {@code clazz} if one is scoped in the current + * scope, or its ancestors. If there is no such instance, the factory associated + * to the clazz will be used. + * All {@link javax.inject.Inject} annotated fields of the instance are injected after creation. + * If the {@param clazz} is annotated with {@link javax.inject.Singleton} then the created instance + * will be scoped in the root scope of the current scope. + * + * @param clazz the class for which to obtain an instance in the scope of this scope. + * @param the type of {@code clazz}. + * @return a scoped instance or a new one produced by the factory associated to {@code clazz}. + */ + public abstract T getInstance(Class clazz); + + /** + * Returns a {@code Provider} of {@code clazz} if one is scoped in the current + * scope, or its ancestors. If there is no such provider, the factory associated + * to the clazz will be used to create one. + * All {@link javax.inject.Inject} annotated fields of the instance are injected after creation. + * If the {@param clazz} is annotated with {@link javax.inject.Singleton} then the created provider + * will be scoped in the root scope of the current scope. + * + * @param clazz the class for which to obtain a provider in the scope of this scope. + * @param the type of {@code clazz}. + * @return a scoped provider or a new one using the factory associated to {@code clazz}. + */ + public abstract Provider getProvider(Class clazz); + + /** + * Returns a {@code Lazy} of {@code clazz} if one provider is scoped in the current + * scope, or its ancestors. If there is no such provider, the factory associated + * to the clazz will be used to create one. + * All {@link javax.inject.Inject} annotated fields of the instance are injected after creation. + * If the {@param clazz} is annotated with {@link javax.inject.Singleton} then the created provider + * will be scoped in the root scope of the current scope. + * + * @param clazz the class for which to obtain a lazy in the scope of this scope. + * @param the type of {@code clazz}. + * @return a scoped lazy or a new one using the factory associated to {@code clazz}. + * @see #getProvider(Class) + */ + public abstract Lazy getLazy(Class clazz); + + /** + * Returns a {@code Future} of {@code clazz} if one provider is scoped in the current + * scope, or its ancestors. If there is no such provider, the factory associated + * to the clazz will be used to create one. + * All {@link javax.inject.Inject} annotated fields of the instance are injected after creation. + * If the {@param clazz} is annotated with {@link javax.inject.Singleton} then the created provider + * will be scoped in the root scope of the current scope. + * + * All future are executed on a background thread pool. TODO make this configurable. + * + * @param clazz the class for which to obtain a future in the scope of this scope. + * @param the type of {@code clazz}. + * @return a scoped future or a new one using the factory associated to {@code clazz}. + * @see #getProvider(Class) + */ + public abstract Future getFuture(Class clazz); + + /** + * Allows to define test modules. These method should only be used for testing. + * DO NOT USE IT IN PRODUCTION. + * Test modules have precedence over other normal modules, allowing to define stubs/fake/mocks. + * All bindings defined in a test module cannot be overridden by a future call to {@link #installModules(Module...)}. + * But they can still be overridden by a future call to {@link #installTestModules(Module...)}. + * + * @param modules an array of modules that define test bindings. + */ + public abstract void installTestModules(Module... modules); + + /** + * Allows to define modules. + * + * @param modules an array of modules that define bindings. + * @See #installTestModules + */ + public abstract void installModules(Module... modules); + + @Override + public String toString() { + final String branch = "---"; + final char lastNode = '\\'; + final char node = '+'; + final String indent = " "; + + StringBuilder builder = new StringBuilder(); + builder.append(name); + builder.append(':'); + builder.append(System.identityHashCode(this)); + builder.append('\n'); + + builder.append('['); + for (Class aClass : mapClassesToProviders.keySet()) { + builder.append(aClass.getName()); + builder.append(','); + } + builder.deleteCharAt(builder.length() - 1); + builder.append(']'); + builder.append('\n'); + + Iterator iterator = childrenScopes.iterator(); + while (iterator.hasNext()) { + Scope scope = iterator.next(); + boolean isLast = !iterator.hasNext(); + builder.append(isLast ? lastNode : node); + builder.append(branch); + String childString = scope.toString(); + String[] split = childString.split("\n"); + for (int i = 0; i < split.length; i++) { + String childLine = split[i]; + if (i != 0) { + builder.append(indent); + } + builder.append(childLine); + builder.append('\n'); + } + } + + return builder.toString(); + } +} From 3cdd8db3877ef2f7666e8bbb0b0e5dfc34c14a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20Nicolas?= Date: Tue, 12 Apr 2016 21:48:40 -0700 Subject: [PATCH 4/7] Simplify syntax...:) --- .../example/smoothie/LessSimpleActivity.java | 5 ++--- .../com/example/smoothie/PersistActivity.java | 8 ++------ .../com/example/smoothie/SimpleActivity.java | 4 +--- .../src/main/java/toothpick/ToothPick.java | 18 ++++++++++++++++++ 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/smoothie-sample/src/main/java/com/example/smoothie/LessSimpleActivity.java b/smoothie-sample/src/main/java/com/example/smoothie/LessSimpleActivity.java index a1c3ca09..ebf66ec4 100644 --- a/smoothie-sample/src/main/java/com/example/smoothie/LessSimpleActivity.java +++ b/smoothie-sample/src/main/java/com/example/smoothie/LessSimpleActivity.java @@ -33,10 +33,9 @@ public class LessSimpleActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Scope appScope = ToothPick.openScope(getApplication()); - scope = ToothPick.openScope(this); + scope = ToothPick.openScopes(getApplication(), this); + scope.installModules(new DefaultActivityModule(this)); scope.installModules(new DefaultActivityModule(this)); - appScope.addChild(scope); ToothPick.inject(this, scope); setContentView(R.layout.simple_activity); ButterKnife.bind(this); diff --git a/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java b/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java index f2a07cc1..6266f098 100644 --- a/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java +++ b/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java @@ -28,14 +28,10 @@ public class PersistActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Scope appScope = ToothPick.openScope(getApplication()); - Scope metaScope = ToothPick.openScope(PRESENTER_SCOPE); - appScope.addChild(metaScope); - scope = ToothPick.openScope(this); - metaScope.addChild(scope); + scope = ToothPick.openScopes(getApplication(), PRESENTER_SCOPE, this); scope.installModules(new DefaultActivityModule(this)); ToothPick.inject(this, scope); - metaScope.installModules(new PresenterModule()); + ToothPick.openScope(PRESENTER_SCOPE).installModules(new PresenterModule()); setContentView(R.layout.simple_activity); ButterKnife.bind(this); diff --git a/smoothie-sample/src/main/java/com/example/smoothie/SimpleActivity.java b/smoothie-sample/src/main/java/com/example/smoothie/SimpleActivity.java index c2a0f960..64e23839 100644 --- a/smoothie-sample/src/main/java/com/example/smoothie/SimpleActivity.java +++ b/smoothie-sample/src/main/java/com/example/smoothie/SimpleActivity.java @@ -26,10 +26,8 @@ public class SimpleActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Scope appScope = ToothPick.openScope(getApplication()); - scope = ToothPick.openScope(this); + scope = ToothPick.openScopes(getApplication(), this); scope.installModules(new DefaultActivityModule(this)); - appScope.addChild(scope); ToothPick.inject(this, scope); setContentView(R.layout.simple_activity); ButterKnife.bind(this); diff --git a/toothpick-runtime/src/main/java/toothpick/ToothPick.java b/toothpick-runtime/src/main/java/toothpick/ToothPick.java index 97b9a112..5f6c5130 100644 --- a/toothpick-runtime/src/main/java/toothpick/ToothPick.java +++ b/toothpick-runtime/src/main/java/toothpick/ToothPick.java @@ -17,6 +17,24 @@ private ToothPick() { throw new RuntimeException("Constructor can't be invoked even via reflection."); } + public static Scope openScopes(Object... names) { + if (names == null) { + throw new IllegalArgumentException("null scopes can't be open."); + } + + Scope previousScope = null; + Scope lastScope = null; + for (Object name : names) { + previousScope = lastScope; + lastScope = openScope(name); + if (previousScope != null) { + previousScope.addChild(lastScope); + } + } + + return lastScope; + } + public static Scope openScope(Object name) { Scope scope = MAP_KEY_TO_INJECTOR.get(name); if (scope == null) { From b6a721cceba44a13918c148c70bb111754346f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20Nicolas?= Date: Tue, 12 Apr 2016 21:51:20 -0700 Subject: [PATCH 5/7] comment --- .../src/main/java/com/example/smoothie/PersistActivity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java b/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java index 6266f098..d720da63 100644 --- a/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java +++ b/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java @@ -48,6 +48,8 @@ protected void onDestroy() { @Override public void onBackPressed() { + //when we leave the presenter flow, + //we close its scope ToothPick.closeScope(PRESENTER_SCOPE); super.onBackPressed(); } From 9bc087df256f4adf671a247054f2bc6ed0ef8313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20Nicolas?= Date: Tue, 12 Apr 2016 21:58:39 -0700 Subject: [PATCH 6/7] Simpler Naming for smoothie modules --- .../main/java/com/example/smoothie/LessSimpleActivity.java | 6 +++--- .../src/main/java/com/example/smoothie/PersistActivity.java | 4 ++-- .../src/main/java/com/example/smoothie/SimpleActivity.java | 4 ++-- .../src/main/java/com/example/smoothie/SimpleApp.java | 4 ++-- .../{DefaultActivityModule.java => ActivityModule.java} | 4 ++-- ...DefaultApplicationModule.java => ApplicationModule.java} | 4 ++-- ...upportActivityModule.java => SupportActivityModule.java} | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) rename smoothie/src/main/java/toothpick/smoothie/module/{DefaultActivityModule.java => ActivityModule.java} (82%) rename smoothie/src/main/java/toothpick/smoothie/module/{DefaultApplicationModule.java => ApplicationModule.java} (97%) rename smoothie/src/main/java/toothpick/smoothie/module/{DefaultSupportActivityModule.java => SupportActivityModule.java} (82%) diff --git a/smoothie-sample/src/main/java/com/example/smoothie/LessSimpleActivity.java b/smoothie-sample/src/main/java/com/example/smoothie/LessSimpleActivity.java index ebf66ec4..d1083f09 100644 --- a/smoothie-sample/src/main/java/com/example/smoothie/LessSimpleActivity.java +++ b/smoothie-sample/src/main/java/com/example/smoothie/LessSimpleActivity.java @@ -14,7 +14,7 @@ import javax.inject.Inject; import toothpick.Scope; import toothpick.ToothPick; -import toothpick.smoothie.module.DefaultActivityModule; +import toothpick.smoothie.module.ActivityModule; public class LessSimpleActivity extends Activity { @@ -34,8 +34,8 @@ public class LessSimpleActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); scope = ToothPick.openScopes(getApplication(), this); - scope.installModules(new DefaultActivityModule(this)); - scope.installModules(new DefaultActivityModule(this)); + scope.installModules(new ActivityModule(this)); + scope.installModules(new ActivityModule(this)); ToothPick.inject(this, scope); setContentView(R.layout.simple_activity); ButterKnife.bind(this); diff --git a/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java b/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java index d720da63..78b2b9fa 100644 --- a/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java +++ b/smoothie-sample/src/main/java/com/example/smoothie/PersistActivity.java @@ -12,7 +12,7 @@ import toothpick.Scope; import toothpick.ToothPick; import toothpick.config.Module; -import toothpick.smoothie.module.DefaultActivityModule; +import toothpick.smoothie.module.ActivityModule; public class PersistActivity extends Activity { @@ -29,7 +29,7 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); scope = ToothPick.openScopes(getApplication(), PRESENTER_SCOPE, this); - scope.installModules(new DefaultActivityModule(this)); + scope.installModules(new ActivityModule(this)); ToothPick.inject(this, scope); ToothPick.openScope(PRESENTER_SCOPE).installModules(new PresenterModule()); diff --git a/smoothie-sample/src/main/java/com/example/smoothie/SimpleActivity.java b/smoothie-sample/src/main/java/com/example/smoothie/SimpleActivity.java index 64e23839..fda83c89 100644 --- a/smoothie-sample/src/main/java/com/example/smoothie/SimpleActivity.java +++ b/smoothie-sample/src/main/java/com/example/smoothie/SimpleActivity.java @@ -12,7 +12,7 @@ import javax.inject.Inject; import toothpick.Scope; import toothpick.ToothPick; -import toothpick.smoothie.module.DefaultActivityModule; +import toothpick.smoothie.module.ActivityModule; public class SimpleActivity extends Activity { @@ -27,7 +27,7 @@ public class SimpleActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); scope = ToothPick.openScopes(getApplication(), this); - scope.installModules(new DefaultActivityModule(this)); + scope.installModules(new ActivityModule(this)); ToothPick.inject(this, scope); setContentView(R.layout.simple_activity); ButterKnife.bind(this); diff --git a/smoothie-sample/src/main/java/com/example/smoothie/SimpleApp.java b/smoothie-sample/src/main/java/com/example/smoothie/SimpleApp.java index ab0f2847..7c16f13c 100644 --- a/smoothie-sample/src/main/java/com/example/smoothie/SimpleApp.java +++ b/smoothie-sample/src/main/java/com/example/smoothie/SimpleApp.java @@ -3,13 +3,13 @@ import android.app.Application; import toothpick.Scope; import toothpick.ToothPick; -import toothpick.smoothie.module.DefaultApplicationModule; +import toothpick.smoothie.module.ApplicationModule; public class SimpleApp extends Application { @Override public void onCreate() { super.onCreate(); Scope appScope = ToothPick.openScope(this); - appScope.installModules(new DefaultApplicationModule(this)); + appScope.installModules(new ApplicationModule(this)); } } \ No newline at end of file diff --git a/smoothie/src/main/java/toothpick/smoothie/module/DefaultActivityModule.java b/smoothie/src/main/java/toothpick/smoothie/module/ActivityModule.java similarity index 82% rename from smoothie/src/main/java/toothpick/smoothie/module/DefaultActivityModule.java rename to smoothie/src/main/java/toothpick/smoothie/module/ActivityModule.java index 6bb6e3ec..e17e60f2 100644 --- a/smoothie/src/main/java/toothpick/smoothie/module/DefaultActivityModule.java +++ b/smoothie/src/main/java/toothpick/smoothie/module/ActivityModule.java @@ -7,8 +7,8 @@ import toothpick.smoothie.provider.FragmentManagerProvider; import toothpick.smoothie.provider.LoaderManagerProvider; -public class DefaultActivityModule extends Module { - public DefaultActivityModule(Activity activity) { +public class ActivityModule extends Module { + public ActivityModule(Activity activity) { bind(Activity.class).to(activity); bind(FragmentManager.class).toProvider(FragmentManagerProvider.class); bind(LoaderManager.class).toProvider(LoaderManagerProvider.class); diff --git a/smoothie/src/main/java/toothpick/smoothie/module/DefaultApplicationModule.java b/smoothie/src/main/java/toothpick/smoothie/module/ApplicationModule.java similarity index 97% rename from smoothie/src/main/java/toothpick/smoothie/module/DefaultApplicationModule.java rename to smoothie/src/main/java/toothpick/smoothie/module/ApplicationModule.java index e70d8270..ed3043b6 100644 --- a/smoothie/src/main/java/toothpick/smoothie/module/DefaultApplicationModule.java +++ b/smoothie/src/main/java/toothpick/smoothie/module/ApplicationModule.java @@ -47,8 +47,8 @@ import static android.content.Context.VIBRATOR_SERVICE; import static android.content.Context.WINDOW_SERVICE; -public class DefaultApplicationModule extends Module { - public DefaultApplicationModule(Application application) { +public class ApplicationModule extends Module { + public ApplicationModule(Application application) { bind(Application.class).to(application); bind(AccountManager.class).toProvider(AccountManagerProvider.class); bind(AssetManager.class).toProvider(AssetManagerProvider.class); diff --git a/smoothie/src/main/java/toothpick/smoothie/module/DefaultSupportActivityModule.java b/smoothie/src/main/java/toothpick/smoothie/module/SupportActivityModule.java similarity index 82% rename from smoothie/src/main/java/toothpick/smoothie/module/DefaultSupportActivityModule.java rename to smoothie/src/main/java/toothpick/smoothie/module/SupportActivityModule.java index a1d021c4..7c760b59 100644 --- a/smoothie/src/main/java/toothpick/smoothie/module/DefaultSupportActivityModule.java +++ b/smoothie/src/main/java/toothpick/smoothie/module/SupportActivityModule.java @@ -8,8 +8,8 @@ import toothpick.smoothie.provider.SupportFragmentManagerProvider; import toothpick.smoothie.provider.SupportLoaderManagerProvider; -public class DefaultSupportActivityModule extends Module { - public DefaultSupportActivityModule(FragmentActivity activity) { +public class SupportActivityModule extends Module { + public SupportActivityModule(FragmentActivity activity) { bind(Activity.class).to(activity); bind(FragmentManager.class).toProvider(SupportFragmentManagerProvider.class); bind(LoaderManager.class).toProvider(SupportLoaderManagerProvider.class); From 47ab51ba6bad8712ac086565dbd408474773eedd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ste=CC=81phane=20Nicolas?= Date: Tue, 12 Apr 2016 22:07:39 -0700 Subject: [PATCH 7/7] clean up --- .../smoothie/module/ApplicationModule.java | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/smoothie/src/main/java/toothpick/smoothie/module/ApplicationModule.java b/smoothie/src/main/java/toothpick/smoothie/module/ApplicationModule.java index ed3043b6..cc7263ef 100644 --- a/smoothie/src/main/java/toothpick/smoothie/module/ApplicationModule.java +++ b/smoothie/src/main/java/toothpick/smoothie/module/ApplicationModule.java @@ -61,23 +61,27 @@ public ApplicationModule(Application application) { // TODO check min sdk and refactor private void bindSystemServices(Application application) { - bind(LocationManager.class).toProvider(new SystemServiceProvider(application, LOCATION_SERVICE)); - bind(WindowManager.class).toProvider(new SystemServiceProvider(application, WINDOW_SERVICE)); - bind(ActivityManager.class).toProvider(new SystemServiceProvider(application, ACTIVITY_SERVICE)); - bind(PowerManager.class).toProvider(new SystemServiceProvider(application, POWER_SERVICE)); - bind(AlarmManager.class).toProvider(new SystemServiceProvider(application, ALARM_SERVICE)); - bind(NotificationManager.class).toProvider(new SystemServiceProvider(application, NOTIFICATION_SERVICE)); - bind(KeyguardManager.class).toProvider(new SystemServiceProvider(application, KEYGUARD_SERVICE)); - bind(Vibrator.class).toProvider(new SystemServiceProvider(application, VIBRATOR_SERVICE)); - bind(ConnectivityManager.class).toProvider(new SystemServiceProvider(application, CONNECTIVITY_SERVICE)); - bind(WifiManager.class).toProvider(new SystemServiceProvider(application, WINDOW_SERVICE)); - bind(InputMethodManager.class).toProvider(new SystemServiceProvider(application, INPUT_METHOD_SERVICE)); - bind(SensorManager.class).toProvider(new SystemServiceProvider(application, SENSOR_SERVICE)); - bind(TelephonyManager.class).toProvider(new SystemServiceProvider(application, TELEPHONY_SERVICE)); - bind(AudioManager.class).toProvider(new SystemServiceProvider(application, AUDIO_SERVICE)); + bindSystemService(application, LocationManager.class, LOCATION_SERVICE); + bindSystemService(application, WindowManager.class, WINDOW_SERVICE); + bindSystemService(application, ActivityManager.class, ACTIVITY_SERVICE); + bindSystemService(application, PowerManager.class, POWER_SERVICE); + bindSystemService(application, AlarmManager.class, ALARM_SERVICE); + bindSystemService(application, NotificationManager.class, NOTIFICATION_SERVICE); + bindSystemService(application, KeyguardManager.class, KEYGUARD_SERVICE); + bindSystemService(application, Vibrator.class, VIBRATOR_SERVICE); + bindSystemService(application, ConnectivityManager.class, CONNECTIVITY_SERVICE); + bindSystemService(application, WifiManager.class, WINDOW_SERVICE); + bindSystemService(application, InputMethodManager.class, INPUT_METHOD_SERVICE); + bindSystemService(application, SensorManager.class, SENSOR_SERVICE); + bindSystemService(application, TelephonyManager.class, TELEPHONY_SERVICE); + bindSystemService(application, AudioManager.class, AUDIO_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { - bind(DownloadManager.class).toProvider(new SystemServiceProvider(application, DOWNLOAD_SERVICE)); + bindSystemService(application, DownloadManager.class, DOWNLOAD_SERVICE); } bind(Application.class).to(application); } + + private void bindSystemService(Application application, Class serviceClass, String serviceName) { + bind(serviceClass).toProvider(new SystemServiceProvider(application, serviceName)); + } }