1925 lines
74 KiB
Java
1925 lines
74 KiB
Java
/*
|
|
* Copyright (C) 2015 The Dagger Authors.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package dagger.internal.codegen;
|
|
|
|
import static com.google.common.truth.Truth.assertAbout;
|
|
import static com.google.testing.compile.CompilationSubject.assertThat;
|
|
import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
|
|
import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;
|
|
import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE;
|
|
import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE;
|
|
import static dagger.internal.codegen.Compilers.compilerWithOptions;
|
|
import static javax.tools.StandardLocation.CLASS_OUTPUT;
|
|
|
|
import com.google.common.base.Joiner;
|
|
import com.google.common.collect.ImmutableList;
|
|
import com.google.common.collect.ImmutableSet;
|
|
import com.google.testing.compile.Compilation;
|
|
import com.google.testing.compile.JavaFileObjects;
|
|
import java.io.IOException;
|
|
import java.io.Writer;
|
|
import java.util.Collection;
|
|
import java.util.Set;
|
|
import javax.annotation.processing.AbstractProcessor;
|
|
import javax.annotation.processing.RoundEnvironment;
|
|
import javax.lang.model.element.TypeElement;
|
|
import javax.tools.JavaFileObject;
|
|
import org.junit.Test;
|
|
import org.junit.runner.RunWith;
|
|
import org.junit.runners.Parameterized;
|
|
import org.junit.runners.Parameterized.Parameters;
|
|
|
|
@RunWith(Parameterized.class)
|
|
public class MembersInjectionTest {
|
|
@Parameters(name = "{0}")
|
|
public static Collection<Object[]> parameters() {
|
|
return CompilerMode.TEST_PARAMETERS;
|
|
}
|
|
|
|
private final CompilerMode compilerMode;
|
|
|
|
public MembersInjectionTest(CompilerMode compilerMode) {
|
|
this.compilerMode = compilerMode;
|
|
}
|
|
|
|
@Test
|
|
public void parentClass_noInjectedMembers() {
|
|
JavaFileObject childFile = JavaFileObjects.forSourceLines("test.Child",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"public final class Child extends Parent {",
|
|
" @Inject Child() {}",
|
|
"}");
|
|
JavaFileObject parentFile = JavaFileObjects.forSourceLines("test.Parent",
|
|
"package test;",
|
|
"",
|
|
"public abstract class Parent {}");
|
|
|
|
JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Component;",
|
|
"",
|
|
"@Component",
|
|
"interface TestComponent {",
|
|
" Child child();",
|
|
"}");
|
|
JavaFileObject generatedComponent =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.DaggerTestComponent",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"final class DaggerTestComponent implements TestComponent {",
|
|
" @Override",
|
|
" public Child child() {",
|
|
" return new Child();",
|
|
" }",
|
|
"}");
|
|
Compilation compilation =
|
|
compilerWithOptions(compilerMode.javacopts())
|
|
.compile(childFile, parentFile, componentFile);
|
|
|
|
assertThat(compilation).succeeded();
|
|
assertThat(compilation)
|
|
.generatedSourceFile("test.DaggerTestComponent")
|
|
.containsElementsIn(generatedComponent);
|
|
}
|
|
|
|
@Test
|
|
public void parentClass_injectedMembersInSupertype() {
|
|
JavaFileObject childFile = JavaFileObjects.forSourceLines("test.Child",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"public final class Child extends Parent {",
|
|
" @Inject Child() {}",
|
|
"}");
|
|
JavaFileObject parentFile = JavaFileObjects.forSourceLines("test.Parent",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"public abstract class Parent {",
|
|
" @Inject Dep dep;",
|
|
"}");
|
|
JavaFileObject depFile = JavaFileObjects.forSourceLines("test.Dep",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"final class Dep {",
|
|
" @Inject Dep() {}",
|
|
"}");
|
|
JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Component;",
|
|
"",
|
|
"@Component",
|
|
"interface TestComponent {",
|
|
" Child child();",
|
|
"}");
|
|
JavaFileObject generatedComponent =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.DaggerTestComponent",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import com.google.errorprone.annotations.CanIgnoreReturnValue;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"final class DaggerTestComponent implements TestComponent {",
|
|
" @Override",
|
|
" public Child child() {",
|
|
" return injectChild(Child_Factory.newInstance());",
|
|
" }",
|
|
"",
|
|
" @CanIgnoreReturnValue",
|
|
" private Child injectChild(Child instance) {",
|
|
" Parent_MembersInjector.injectDep(instance, new Dep());",
|
|
" return instance;",
|
|
" }",
|
|
"}");
|
|
Compilation compilation =
|
|
compilerWithOptions(compilerMode.javacopts())
|
|
.compile(childFile, parentFile, depFile, componentFile);
|
|
|
|
assertThat(compilation).succeeded();
|
|
assertThat(compilation)
|
|
.generatedSourceFile("test.DaggerTestComponent")
|
|
.containsElementsIn(generatedComponent);
|
|
}
|
|
|
|
@Test public void fieldAndMethodGenerics() {
|
|
JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class GenericClass<A, B> {",
|
|
" @Inject A a;",
|
|
"",
|
|
" @Inject GenericClass() {}",
|
|
"",
|
|
" @Inject void register(B b) {}",
|
|
"}");
|
|
JavaFileObject expected =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.GenericClass_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class GenericClass_MembersInjector<A, B>",
|
|
" implements MembersInjector<GenericClass<A, B>> {",
|
|
" private final Provider<A> aProvider;",
|
|
" private final Provider<B> bProvider;",
|
|
"",
|
|
" public GenericClass_MembersInjector(Provider<A> aProvider, Provider<B> bProvider) {",
|
|
" this.aProvider = aProvider;",
|
|
" this.bProvider = bProvider;",
|
|
" }",
|
|
"",
|
|
" public static <A, B> MembersInjector<GenericClass<A, B>> create(",
|
|
" Provider<A> aProvider, Provider<B> bProvider) {",
|
|
" return new GenericClass_MembersInjector<A, B>(aProvider, bProvider);",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(GenericClass<A, B> instance) {",
|
|
" injectA(instance, aProvider.get());",
|
|
" injectRegister(instance, bProvider.get());",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.GenericClass.a\")",
|
|
" public static <A, B> void injectA(Object instance, A a) {",
|
|
" ((GenericClass<A, B>) instance).a = a;",
|
|
" }",
|
|
"",
|
|
" public static <A, B> void injectRegister(Object instance, B b) {",
|
|
" ((GenericClass<A, B>) instance).register(b);",
|
|
" }",
|
|
"}");
|
|
assertAbout(javaSource())
|
|
.that(file)
|
|
.withCompilerOptions(compilerMode.javacopts())
|
|
.processedWith(new ComponentProcessor())
|
|
.compilesWithoutError()
|
|
.and()
|
|
.generatesSources(expected);
|
|
}
|
|
|
|
@Test public void subclassedGenericMembersInjectors() {
|
|
JavaFileObject a = JavaFileObjects.forSourceLines("test.A",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"final class A {",
|
|
" @Inject A() {}",
|
|
"}");
|
|
JavaFileObject a2 = JavaFileObjects.forSourceLines("test.A2",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"final class A2 {",
|
|
" @Inject A2() {}",
|
|
"}");
|
|
JavaFileObject parent = JavaFileObjects.forSourceLines("test.Parent",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class Parent<X, Y> {",
|
|
" @Inject X x;",
|
|
" @Inject Y y;",
|
|
" @Inject A2 a2;",
|
|
"",
|
|
" @Inject Parent() {}",
|
|
"}");
|
|
JavaFileObject child = JavaFileObjects.forSourceLines("test.Child",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class Child<T> extends Parent<T, A> {",
|
|
" @Inject A a;",
|
|
" @Inject T t;",
|
|
"",
|
|
" @Inject Child() {}",
|
|
"}");
|
|
JavaFileObject expected =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.Child_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class Child_MembersInjector<T>",
|
|
" implements MembersInjector<Child<T>> {",
|
|
" private final Provider<T> xProvider;",
|
|
" private final Provider<A> yProvider;",
|
|
" private final Provider<A2> a2Provider;",
|
|
" private final Provider<A> aProvider;",
|
|
" private final Provider<T> tProvider;",
|
|
"",
|
|
" public Child_MembersInjector(",
|
|
" Provider<T> xProvider,",
|
|
" Provider<A> yProvider,",
|
|
" Provider<A2> a2Provider,",
|
|
" Provider<A> aProvider,",
|
|
" Provider<T> tProvider) {",
|
|
" this.xProvider = xProvider;",
|
|
" this.yProvider = yProvider;",
|
|
" this.a2Provider = a2Provider;",
|
|
" this.aProvider = aProvider;",
|
|
" this.tProvider = tProvider;",
|
|
" }",
|
|
"",
|
|
" public static <T> MembersInjector<Child<T>> create(",
|
|
" Provider<T> xProvider,",
|
|
" Provider<A> yProvider,",
|
|
" Provider<A2> a2Provider,",
|
|
" Provider<A> aProvider,",
|
|
" Provider<T> tProvider) {",
|
|
" return new Child_MembersInjector<T>(xProvider, yProvider, a2Provider, aProvider,"
|
|
+ " tProvider);",
|
|
"}",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(Child<T> instance) {",
|
|
" Parent_MembersInjector.injectX(instance, xProvider.get());",
|
|
" Parent_MembersInjector.injectY(instance, yProvider.get());",
|
|
" Parent_MembersInjector.injectA2(instance, a2Provider.get());",
|
|
" injectA(instance, aProvider.get());",
|
|
" injectT(instance, tProvider.get());",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.Child.a\")",
|
|
" public static <T> void injectA(Object instance, Object a) {",
|
|
" ((Child<T>) instance).a = (A) a;",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.Child.t\")",
|
|
" public static <T> void injectT(Object instance, T t) {",
|
|
" ((Child<T>) instance).t = t;",
|
|
" }",
|
|
"}");
|
|
assertAbout(javaSources())
|
|
.that(ImmutableList.of(a, a2, parent, child))
|
|
.withCompilerOptions(compilerMode.javacopts())
|
|
.processedWith(new ComponentProcessor())
|
|
.compilesWithoutError()
|
|
.and()
|
|
.generatesSources(expected);
|
|
}
|
|
|
|
@Test public void fieldInjection() {
|
|
JavaFileObject file = JavaFileObjects.forSourceLines("test.FieldInjection",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Lazy;",
|
|
"import javax.inject.Inject;",
|
|
"import javax.inject.Provider;",
|
|
"",
|
|
"class FieldInjection {",
|
|
" @Inject String string;",
|
|
" @Inject Lazy<String> lazyString;",
|
|
" @Inject Provider<String> stringProvider;",
|
|
"}");
|
|
JavaFileObject expected =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.FieldInjection_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.Lazy;",
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.DoubleCheck;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class FieldInjection_MembersInjector",
|
|
" implements MembersInjector<FieldInjection> {",
|
|
" private final Provider<String> stringProvider;",
|
|
" private final Provider<String> stringProvider2;",
|
|
" private final Provider<String> stringProvider3;",
|
|
"",
|
|
" public FieldInjection_MembersInjector(Provider<String> stringProvider,",
|
|
" Provider<String> stringProvider2, Provider<String> stringProvider3) {",
|
|
" this.stringProvider = stringProvider;",
|
|
" this.stringProvider2 = stringProvider2;",
|
|
" this.stringProvider3 = stringProvider3;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<FieldInjection> create(",
|
|
" Provider<String> stringProvider,",
|
|
" Provider<String> stringProvider2,",
|
|
" Provider<String> stringProvider3) {",
|
|
" return new FieldInjection_MembersInjector(",
|
|
" stringProvider, stringProvider2, stringProvider3);",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(FieldInjection instance) {",
|
|
" injectString(instance, stringProvider.get());",
|
|
" injectLazyString(instance, DoubleCheck.lazy(stringProvider2));",
|
|
" injectStringProvider(instance, stringProvider3);",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.FieldInjection.string\")",
|
|
" public static void injectString(Object instance, String string) {",
|
|
" ((FieldInjection) instance).string = string;",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.FieldInjection.lazyString\")",
|
|
" public static void injectLazyString(Object instance, Lazy<String> lazyString) {",
|
|
" ((FieldInjection) instance).lazyString = lazyString;",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.FieldInjection.stringProvider\")",
|
|
" public static void injectStringProvider(",
|
|
" Object instance, Provider<String> stringProvider) {",
|
|
" ((FieldInjection) instance).stringProvider = stringProvider;",
|
|
" }",
|
|
"}");
|
|
assertAbout(javaSource())
|
|
.that(file)
|
|
.withCompilerOptions(compilerMode.javacopts())
|
|
.processedWith(new ComponentProcessor())
|
|
.compilesWithoutError()
|
|
.and()
|
|
.generatesSources(expected);
|
|
}
|
|
|
|
@Test
|
|
public void fieldInjectionWithQualifier() {
|
|
JavaFileObject file =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.FieldInjectionWithQualifier",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Lazy;",
|
|
"import javax.inject.Inject;",
|
|
"import javax.inject.Named;",
|
|
"import javax.inject.Provider;",
|
|
"",
|
|
"class FieldInjectionWithQualifier {",
|
|
" @Inject @Named(\"A\") String a;",
|
|
" @Inject @Named(\"B\") String b;",
|
|
"}");
|
|
JavaFileObject expected =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.FieldInjectionWithQualifier_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Named;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class FieldInjectionWithQualifier_MembersInjector",
|
|
" implements MembersInjector<FieldInjectionWithQualifier> {",
|
|
" private final Provider<String> aProvider;",
|
|
" private final Provider<String> bProvider;",
|
|
"",
|
|
" public FieldInjectionWithQualifier_MembersInjector(Provider<String> aProvider,",
|
|
" Provider<String> bProvider) {",
|
|
" this.aProvider = aProvider;",
|
|
" this.bProvider = bProvider;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<FieldInjectionWithQualifier> create(",
|
|
" Provider<String> aProvider, Provider<String> bProvider) {",
|
|
" return new FieldInjectionWithQualifier_MembersInjector(aProvider, bProvider);",
|
|
" }",
|
|
"",
|
|
"@Override",
|
|
" public void injectMembers(FieldInjectionWithQualifier instance) {",
|
|
" injectA(instance, aProvider.get());",
|
|
" injectB(instance, bProvider.get());",
|
|
"}",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.FieldInjectionWithQualifier.a\")",
|
|
" @Named(\"A\")",
|
|
" public static void injectA(Object instance, String a) {",
|
|
" ((FieldInjectionWithQualifier) instance).a = a;",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.FieldInjectionWithQualifier.b\")",
|
|
" @Named(\"B\")",
|
|
" public static void injectB(Object instance, String b) {",
|
|
" ((FieldInjectionWithQualifier) instance).b = b;",
|
|
" }",
|
|
"}");
|
|
assertAbout(javaSource())
|
|
.that(file)
|
|
.withCompilerOptions(compilerMode.javacopts())
|
|
.processedWith(new ComponentProcessor())
|
|
.compilesWithoutError()
|
|
.and()
|
|
.generatesSources(expected);
|
|
}
|
|
|
|
@Test public void methodInjection() {
|
|
JavaFileObject file = JavaFileObjects.forSourceLines("test.MethodInjection",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Lazy;",
|
|
"import javax.inject.Inject;",
|
|
"import javax.inject.Provider;",
|
|
"",
|
|
"class MethodInjection {",
|
|
" @Inject void noArgs() {}",
|
|
" @Inject void oneArg(String string) {}",
|
|
" @Inject void manyArgs(",
|
|
" String string, Lazy<String> lazyString, Provider<String> stringProvider) {}",
|
|
"}");
|
|
JavaFileObject expected =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.MethodInjection_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.Lazy;",
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.DoubleCheck;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class MethodInjection_MembersInjector",
|
|
" implements MembersInjector<MethodInjection> {",
|
|
" private final Provider<String> stringProvider;",
|
|
" private final Provider<String> stringProvider2;",
|
|
" private final Provider<String> stringProvider3;",
|
|
" private final Provider<String> stringProvider4;",
|
|
"",
|
|
" public MethodInjection_MembersInjector(",
|
|
" Provider<String> stringProvider,",
|
|
" Provider<String> stringProvider2,",
|
|
" Provider<String> stringProvider3,",
|
|
" Provider<String> stringProvider4) {",
|
|
" this.stringProvider = stringProvider;",
|
|
" this.stringProvider2 = stringProvider2;",
|
|
" this.stringProvider3 = stringProvider3;",
|
|
" this.stringProvider4 = stringProvider4;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<MethodInjection> create(",
|
|
" Provider<String> stringProvider,",
|
|
" Provider<String> stringProvider2,",
|
|
" Provider<String> stringProvider3,",
|
|
" Provider<String> stringProvider4) {",
|
|
" return new MethodInjection_MembersInjector(",
|
|
" stringProvider, stringProvider2, stringProvider3, stringProvider4);}",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(MethodInjection instance) {",
|
|
" injectNoArgs(instance);",
|
|
" injectOneArg(instance, stringProvider.get());",
|
|
" injectManyArgs(",
|
|
" instance,",
|
|
" stringProvider2.get(),",
|
|
" DoubleCheck.lazy(stringProvider3),",
|
|
" stringProvider4);",
|
|
" }",
|
|
"",
|
|
" public static void injectNoArgs(Object instance) {",
|
|
" ((MethodInjection) instance).noArgs();",
|
|
" }",
|
|
"",
|
|
" public static void injectOneArg(Object instance, String string) {",
|
|
" ((MethodInjection) instance).oneArg(string);",
|
|
" }",
|
|
"",
|
|
" public static void injectManyArgs(",
|
|
" Object instance,",
|
|
" String string,",
|
|
" Lazy<String> lazyString,",
|
|
" Provider<String> stringProvider) {",
|
|
" ((MethodInjection) instance).manyArgs(string, lazyString, stringProvider);",
|
|
" }",
|
|
"}");
|
|
assertAbout(javaSource())
|
|
.that(file)
|
|
.withCompilerOptions(compilerMode.javacopts())
|
|
.processedWith(new ComponentProcessor())
|
|
.compilesWithoutError()
|
|
.and()
|
|
.generatesSources(expected);
|
|
}
|
|
|
|
@Test
|
|
public void mixedMemberInjection() {
|
|
JavaFileObject file = JavaFileObjects.forSourceLines(
|
|
"test.MixedMemberInjection",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Lazy;",
|
|
"import javax.inject.Inject;",
|
|
"import javax.inject.Provider;",
|
|
"",
|
|
"class MixedMemberInjection {",
|
|
" @Inject String string;",
|
|
" @Inject void setString(String s) {}",
|
|
" @Inject Object object;",
|
|
" @Inject void setObject(Object o) {}",
|
|
"}");
|
|
JavaFileObject expected =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.MixedMemberInjection_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class MixedMemberInjection_MembersInjector",
|
|
" implements MembersInjector<MixedMemberInjection> {",
|
|
" private final Provider<String> stringProvider;",
|
|
" private final Provider<Object> objectProvider;",
|
|
" private final Provider<String> sProvider;",
|
|
" private final Provider<Object> oProvider;",
|
|
"",
|
|
" public MixedMemberInjection_MembersInjector(",
|
|
" Provider<String> stringProvider,",
|
|
" Provider<Object> objectProvider,",
|
|
" Provider<String> sProvider,",
|
|
" Provider<Object> oProvider) {",
|
|
" this.stringProvider = stringProvider;",
|
|
" this.objectProvider = objectProvider;",
|
|
" this.sProvider = sProvider;",
|
|
" this.oProvider = oProvider;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<MixedMemberInjection> create(",
|
|
" Provider<String> stringProvider,",
|
|
" Provider<Object> objectProvider,",
|
|
" Provider<String> sProvider,",
|
|
" Provider<Object> oProvider) {",
|
|
" return new MixedMemberInjection_MembersInjector(",
|
|
" stringProvider, objectProvider, sProvider, oProvider);}",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(MixedMemberInjection instance) {",
|
|
" injectString(instance, stringProvider.get());",
|
|
" injectObject(instance, objectProvider.get());",
|
|
" injectSetString(instance, sProvider.get());",
|
|
" injectSetObject(instance, oProvider.get());",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.MixedMemberInjection.string\")",
|
|
" public static void injectString(Object instance, String string) {",
|
|
" ((MixedMemberInjection) instance).string = string;",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.MixedMemberInjection.object\")",
|
|
" public static void injectObject(Object instance, Object object) {",
|
|
" ((MixedMemberInjection) instance).object = object;",
|
|
" }",
|
|
"",
|
|
" public static void injectSetString(Object instance, String s) {",
|
|
" ((MixedMemberInjection) instance).setString(s);",
|
|
" }",
|
|
"",
|
|
" public static void injectSetObject(Object instance, Object o) {",
|
|
" ((MixedMemberInjection) instance).setObject(o);",
|
|
" }",
|
|
"}");
|
|
assertAbout(javaSource())
|
|
.that(file)
|
|
.withCompilerOptions(compilerMode.javacopts())
|
|
.processedWith(new ComponentProcessor())
|
|
.compilesWithoutError()
|
|
.and()
|
|
.generatesSources(expected);
|
|
}
|
|
|
|
@Test public void injectConstructorAndMembersInjection() {
|
|
JavaFileObject file = JavaFileObjects.forSourceLines("test.AllInjections",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class AllInjections {",
|
|
" @Inject String s;",
|
|
" @Inject AllInjections(String s) {}",
|
|
" @Inject void s(String s) {}",
|
|
"}");
|
|
JavaFileObject expectedMembersInjector =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.AllInjections_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class AllInjections_MembersInjector ",
|
|
" implements MembersInjector<AllInjections> {",
|
|
" private final Provider<String> sProvider;",
|
|
" private final Provider<String> sProvider2;",
|
|
"",
|
|
" public AllInjections_MembersInjector(",
|
|
" Provider<String> sProvider, Provider<String> sProvider2) {",
|
|
" this.sProvider = sProvider;",
|
|
" this.sProvider2 = sProvider2;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<AllInjections> create(",
|
|
" Provider<String> sProvider, Provider<String> sProvider2) {",
|
|
" return new AllInjections_MembersInjector(sProvider, sProvider2);}",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(AllInjections instance) {",
|
|
" injectS(instance, sProvider.get());",
|
|
" injectS2(instance, sProvider2.get());",
|
|
" }",
|
|
"",
|
|
// TODO(b/64477506): now that these all take "object", it would be nice to rename
|
|
// "instance"
|
|
// to the type name
|
|
" @InjectedFieldSignature(\"test.AllInjections.s\")",
|
|
" public static void injectS(Object instance, String s) {",
|
|
" ((AllInjections) instance).s = s;",
|
|
" }",
|
|
"",
|
|
" public static void injectS2(Object instance, String s) {",
|
|
" ((AllInjections) instance).s(s);",
|
|
" }",
|
|
"",
|
|
"}");
|
|
assertAbout(javaSource())
|
|
.that(file)
|
|
.withCompilerOptions(compilerMode.javacopts())
|
|
.processedWith(new ComponentProcessor())
|
|
.compilesWithoutError()
|
|
.and()
|
|
.generatesSources(expectedMembersInjector);
|
|
}
|
|
|
|
@Test public void supertypeMembersInjection() {
|
|
JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A",
|
|
"package test;",
|
|
"",
|
|
"class A {}");
|
|
JavaFileObject bFile = JavaFileObjects.forSourceLines("test.B",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class B extends A {",
|
|
" @Inject String s;",
|
|
"}");
|
|
JavaFileObject expectedMembersInjector =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.AllInjections_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class B_MembersInjector implements MembersInjector<B> {",
|
|
" private final Provider<String> sProvider;",
|
|
"",
|
|
" public B_MembersInjector(Provider<String> sProvider) {",
|
|
" this.sProvider = sProvider;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<B> create(Provider<String> sProvider) {",
|
|
" return new B_MembersInjector(sProvider);",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(B instance) {",
|
|
" injectS(instance, sProvider.get());",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.B.s\")",
|
|
" public static void injectS(Object instance, String s) {",
|
|
" ((B) instance).s = s;",
|
|
" }",
|
|
"}");
|
|
assertAbout(javaSources())
|
|
.that(ImmutableList.of(aFile, bFile))
|
|
.withCompilerOptions(compilerMode.javacopts())
|
|
.processedWith(new ComponentProcessor())
|
|
.compilesWithoutError()
|
|
.and()
|
|
.generatesSources(expectedMembersInjector);
|
|
}
|
|
|
|
@Test
|
|
public void simpleComponentWithNesting() {
|
|
JavaFileObject nestedTypesFile = JavaFileObjects.forSourceLines(
|
|
"test.OuterType",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Component;",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"final class OuterType {",
|
|
" static class A {",
|
|
" @Inject A() {}",
|
|
" }",
|
|
" static class B {",
|
|
" @Inject A a;",
|
|
" }",
|
|
" @Component interface SimpleComponent {",
|
|
" A a();",
|
|
" void inject(B b);",
|
|
" }",
|
|
"}");
|
|
JavaFileObject bMembersInjector =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.OuterType_B_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class OuterType_B_MembersInjector",
|
|
" implements MembersInjector<OuterType.B> {",
|
|
" private final Provider<OuterType.A> aProvider;",
|
|
"",
|
|
" public OuterType_B_MembersInjector(Provider<OuterType.A> aProvider) {",
|
|
" this.aProvider = aProvider;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<OuterType.B> create(",
|
|
" Provider<OuterType.A> aProvider) {",
|
|
" return new OuterType_B_MembersInjector(aProvider);",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(OuterType.B instance) {",
|
|
" injectA(instance, aProvider.get());",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.OuterType.B.a\")",
|
|
" public static void injectA(Object instance, Object a) {",
|
|
" ((OuterType.B) instance).a = (OuterType.A) a;",
|
|
" }",
|
|
"}");
|
|
assertAbout(javaSources())
|
|
.that(ImmutableList.of(nestedTypesFile))
|
|
.withCompilerOptions(compilerMode.javacopts())
|
|
.processedWith(new ComponentProcessor())
|
|
.compilesWithoutError()
|
|
.and()
|
|
.generatesSources(bMembersInjector);
|
|
}
|
|
|
|
@Test
|
|
public void componentWithNestingAndGeneratedType() {
|
|
JavaFileObject nestedTypesFile =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.OuterType",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Component;",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"final class OuterType {",
|
|
" @Inject GeneratedType generated;",
|
|
" static class A {",
|
|
" @Inject A() {}",
|
|
" }",
|
|
" static class B {",
|
|
" @Inject A a;",
|
|
" }",
|
|
" @Component interface SimpleComponent {",
|
|
" A a();",
|
|
" void inject(B b);",
|
|
" }",
|
|
"}");
|
|
JavaFileObject bMembersInjector =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.OuterType_B_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class OuterType_B_MembersInjector",
|
|
" implements MembersInjector<OuterType.B> {",
|
|
" private final Provider<OuterType.A> aProvider;",
|
|
"",
|
|
" public OuterType_B_MembersInjector(Provider<OuterType.A> aProvider) {",
|
|
" this.aProvider = aProvider;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<OuterType.B> create(",
|
|
" Provider<OuterType.A> aProvider) {",
|
|
" return new OuterType_B_MembersInjector(aProvider);",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(OuterType.B instance) {",
|
|
" injectA(instance, aProvider.get());",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.OuterType.B.a\")",
|
|
" public static void injectA(Object instance, Object a) {",
|
|
" ((OuterType.B) instance).a = (OuterType.A) a;",
|
|
" }",
|
|
"}");
|
|
assertAbout(javaSource())
|
|
.that(nestedTypesFile)
|
|
.withCompilerOptions(compilerMode.javacopts())
|
|
.processedWith(
|
|
new ComponentProcessor(),
|
|
new AbstractProcessor() {
|
|
private boolean done;
|
|
|
|
@Override
|
|
public Set<String> getSupportedAnnotationTypes() {
|
|
return ImmutableSet.of("*");
|
|
}
|
|
|
|
@Override
|
|
public boolean process(
|
|
Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
|
if (!done) {
|
|
done = true;
|
|
try (Writer writer =
|
|
processingEnv
|
|
.getFiler()
|
|
.createSourceFile("test.GeneratedType")
|
|
.openWriter()) {
|
|
writer.write(
|
|
Joiner.on('\n')
|
|
.join(
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class GeneratedType {",
|
|
" @Inject GeneratedType() {}",
|
|
"}"));
|
|
} catch (IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
})
|
|
.compilesWithoutError()
|
|
.and()
|
|
.generatesSources(bMembersInjector);
|
|
}
|
|
|
|
@Test
|
|
public void lowerCaseNamedMembersInjector_forLowerCaseType() {
|
|
JavaFileObject foo =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.foo",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class foo {",
|
|
" @Inject String string;",
|
|
"}");
|
|
JavaFileObject fooModule =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.fooModule",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Module;",
|
|
"import dagger.Provides;",
|
|
"",
|
|
"@Module",
|
|
"class fooModule {",
|
|
" @Provides String string() { return \"foo\"; }",
|
|
"}");
|
|
JavaFileObject fooComponent =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.fooComponent",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Component;",
|
|
"",
|
|
"@Component(modules = fooModule.class)",
|
|
"interface fooComponent {",
|
|
" void inject(foo target);",
|
|
"}");
|
|
|
|
Compilation compilation =
|
|
compilerWithOptions(compilerMode.javacopts())
|
|
.compile(foo, fooModule, fooComponent);
|
|
assertThat(compilation).succeeded();
|
|
assertThat(compilation).generatedFile(CLASS_OUTPUT, "test", "foo_MembersInjector.class");
|
|
}
|
|
|
|
@Test
|
|
public void fieldInjectionForShadowedMember() {
|
|
JavaFileObject foo =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.Foo",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class Foo {",
|
|
" @Inject Foo() {}",
|
|
"}");
|
|
JavaFileObject bar =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.Bar",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class Bar {",
|
|
" @Inject Bar() {}",
|
|
"}");
|
|
JavaFileObject parent =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.Parent",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class Parent { ",
|
|
" @Inject Foo object;",
|
|
"}");
|
|
JavaFileObject child =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.Child",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class Child extends Parent { ",
|
|
" @Inject Bar object;",
|
|
"}");
|
|
JavaFileObject component =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.C",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Component;",
|
|
"",
|
|
"@Component",
|
|
"interface C { ",
|
|
" void inject(Child child);",
|
|
"}");
|
|
|
|
JavaFileObject expectedMembersInjector =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.Child_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class Child_MembersInjector implements MembersInjector<Child> {",
|
|
" private final Provider<Foo> objectProvider;",
|
|
" private final Provider<Bar> objectProvider2;",
|
|
"",
|
|
" public Child_MembersInjector(",
|
|
" Provider<Foo> objectProvider, Provider<Bar> objectProvider2) {",
|
|
" this.objectProvider = objectProvider;",
|
|
" this.objectProvider2 = objectProvider2;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<Child> create(",
|
|
" Provider<Foo> objectProvider, Provider<Bar> objectProvider2) {",
|
|
" return new Child_MembersInjector(objectProvider, objectProvider2);",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(Child instance) {",
|
|
" Parent_MembersInjector.injectObject(instance, objectProvider.get());",
|
|
" injectObject(instance, objectProvider2.get());",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.Child.object\")",
|
|
" public static void injectObject(Object instance, Object object) {",
|
|
" ((Child) instance).object = (Bar) object;",
|
|
" }",
|
|
"}");
|
|
|
|
assertAbout(javaSources())
|
|
.that(ImmutableList.of(foo, bar, parent, child, component))
|
|
.withCompilerOptions(compilerMode.javacopts())
|
|
.processedWith(new ComponentProcessor())
|
|
.compilesWithoutError()
|
|
.and()
|
|
.generatesSources(expectedMembersInjector);
|
|
}
|
|
|
|
@Test public void privateNestedClassError() {
|
|
JavaFileObject file = JavaFileObjects.forSourceLines("test.OuterClass",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"final class OuterClass {",
|
|
" private static final class InnerClass {",
|
|
" @Inject int field;",
|
|
" }",
|
|
"}");
|
|
Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(file);
|
|
assertThat(compilation).failed();
|
|
assertThat(compilation)
|
|
.hadErrorContaining("Dagger does not support injection into private classes")
|
|
.inFile(file)
|
|
.onLine(6);
|
|
}
|
|
|
|
@Test public void privateNestedClassWarning() {
|
|
JavaFileObject file = JavaFileObjects.forSourceLines("test.OuterClass",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"final class OuterClass {",
|
|
" private static final class InnerClass {",
|
|
" @Inject int field;",
|
|
" }",
|
|
"}");
|
|
Compilation compilation =
|
|
compilerWithOptions(
|
|
compilerMode.javacopts().append("-Adagger.privateMemberValidation=WARNING"))
|
|
.compile(file);
|
|
assertThat(compilation).succeeded();
|
|
assertThat(compilation)
|
|
.hadWarningContaining("Dagger does not support injection into private classes")
|
|
.inFile(file)
|
|
.onLine(6);
|
|
}
|
|
|
|
@Test public void privateSuperclassIsOkIfNotInjectedInto() {
|
|
JavaFileObject file = JavaFileObjects.forSourceLines("test.OuterClass",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"final class OuterClass {",
|
|
" private static class BaseClass {}",
|
|
"",
|
|
" static final class DerivedClass extends BaseClass {",
|
|
" @Inject int field;",
|
|
" }",
|
|
"}");
|
|
Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(file);
|
|
assertThat(compilation).succeeded();
|
|
}
|
|
|
|
@Test
|
|
public void rawFrameworkTypeField() {
|
|
JavaFileObject file =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.RawFrameworkTypes",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Component;",
|
|
"import javax.inject.Inject;",
|
|
"import javax.inject.Provider;",
|
|
"",
|
|
"class RawProviderField {",
|
|
" @Inject Provider fieldWithRawProvider;",
|
|
"}",
|
|
"",
|
|
"@Component",
|
|
"interface C {",
|
|
" void inject(RawProviderField rawProviderField);",
|
|
"}");
|
|
|
|
Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(file);
|
|
assertThat(compilation).failed();
|
|
assertThat(compilation)
|
|
.hadErrorContaining("Provider cannot be provided")
|
|
.inFile(file)
|
|
.onLineContaining("interface C");
|
|
}
|
|
|
|
@Test
|
|
public void throwExceptionInjectedMethod() {
|
|
JavaFileObject file =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Component;",
|
|
"import javax.inject.Inject;",
|
|
"class SomeClass {",
|
|
"@Inject void inject() throws Exception {}",
|
|
"}");
|
|
|
|
Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(file);
|
|
assertThat(compilation).failed();
|
|
assertThat(compilation)
|
|
.hadErrorContaining("Methods with @Inject may not throw checked exceptions. "
|
|
+ "Please wrap your exceptions in a RuntimeException instead.")
|
|
.inFile(file)
|
|
.onLineContaining("throws Exception");
|
|
}
|
|
|
|
@Test
|
|
public void rawFrameworkTypeParameter() {
|
|
JavaFileObject file =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.RawFrameworkTypes",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Component;",
|
|
"import javax.inject.Inject;",
|
|
"import javax.inject.Provider;",
|
|
"",
|
|
"class RawProviderParameter {",
|
|
" @Inject void methodInjection(Provider rawProviderParameter) {}",
|
|
"}",
|
|
"",
|
|
"@Component",
|
|
"interface C {",
|
|
" void inject(RawProviderParameter rawProviderParameter);",
|
|
"}");
|
|
|
|
Compilation compilation = compilerWithOptions(compilerMode.javacopts()).compile(file);
|
|
assertThat(compilation).failed();
|
|
assertThat(compilation)
|
|
.hadErrorContaining("Provider cannot be provided")
|
|
.inFile(file)
|
|
.onLineContaining("interface C");
|
|
}
|
|
|
|
@Test
|
|
public void injectsPrimitive() {
|
|
JavaFileObject injectedType =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.InjectedType",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class InjectedType {",
|
|
" @Inject InjectedType() {}",
|
|
"",
|
|
" @Inject int primitiveInt;",
|
|
" @Inject Integer boxedInt;",
|
|
"}");
|
|
JavaFileObject membersInjector =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.InjectedType_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class InjectedType_MembersInjector ",
|
|
" implements MembersInjector<InjectedType> {",
|
|
" private final Provider<Integer> primitiveIntProvider;",
|
|
" private final Provider<Integer> boxedIntProvider;",
|
|
"",
|
|
" public InjectedType_MembersInjector(",
|
|
" Provider<Integer> primitiveIntProvider, Provider<Integer> boxedIntProvider) {",
|
|
" this.primitiveIntProvider = primitiveIntProvider;",
|
|
" this.boxedIntProvider = boxedIntProvider;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<InjectedType> create(",
|
|
" Provider<Integer> primitiveIntProvider, Provider<Integer> boxedIntProvider) {",
|
|
" return new InjectedType_MembersInjector(primitiveIntProvider, boxedIntProvider);}",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(InjectedType instance) {",
|
|
" injectPrimitiveInt(instance, primitiveIntProvider.get());",
|
|
" injectBoxedInt(instance, boxedIntProvider.get());",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.InjectedType.primitiveInt\")",
|
|
" public static void injectPrimitiveInt(Object instance, int primitiveInt) {",
|
|
" ((InjectedType) instance).primitiveInt = primitiveInt;",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.InjectedType.boxedInt\")",
|
|
" public static void injectBoxedInt(Object instance, Integer boxedInt) {",
|
|
" ((InjectedType) instance).boxedInt = boxedInt;",
|
|
" }",
|
|
"}");
|
|
JavaFileObject factory =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.InjectedType_Factory",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.internal.Factory;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class InjectedType_Factory implements Factory<InjectedType> {",
|
|
" private final Provider<Integer> primitiveIntProvider;",
|
|
"",
|
|
" private final Provider<Integer> boxedIntProvider;",
|
|
"",
|
|
" public InjectedType_Factory(",
|
|
" Provider<Integer> primitiveIntProvider, Provider<Integer> boxedIntProvider) {",
|
|
" this.primitiveIntProvider = primitiveIntProvider;",
|
|
" this.boxedIntProvider = boxedIntProvider;",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" public InjectedType get() {",
|
|
" InjectedType instance = newInstance();",
|
|
" InjectedType_MembersInjector.injectPrimitiveInt(",
|
|
" instance, primitiveIntProvider.get());",
|
|
" InjectedType_MembersInjector.injectBoxedInt(instance, boxedIntProvider.get());",
|
|
" return instance;",
|
|
" }",
|
|
"",
|
|
" public static InjectedType_Factory create(",
|
|
" Provider<Integer> primitiveIntProvider, Provider<Integer> boxedIntProvider) {",
|
|
" return new InjectedType_Factory(primitiveIntProvider, boxedIntProvider);",
|
|
" }",
|
|
"",
|
|
" public static InjectedType newInstance() {",
|
|
" return new InjectedType();",
|
|
" }",
|
|
"}");
|
|
Compilation compilation =
|
|
compilerWithOptions(compilerMode.javacopts()).compile(injectedType);
|
|
assertThat(compilation).succeeded();
|
|
assertThat(compilation)
|
|
.generatedSourceFile("test.InjectedType_MembersInjector")
|
|
.hasSourceEquivalentTo(membersInjector);
|
|
assertThat(compilation)
|
|
.generatedSourceFile("test.InjectedType_Factory")
|
|
.hasSourceEquivalentTo(factory);
|
|
}
|
|
|
|
@Test
|
|
public void accessibility() {
|
|
JavaFileObject foo =
|
|
JavaFileObjects.forSourceLines(
|
|
"other.Foo",
|
|
"package other;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class Foo {",
|
|
" @Inject Foo() {}",
|
|
"}");
|
|
JavaFileObject inaccessible =
|
|
JavaFileObjects.forSourceLines(
|
|
"other.Inaccessible",
|
|
"package other;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class Inaccessible {",
|
|
" @Inject Inaccessible() {}",
|
|
" @Inject Foo foo;",
|
|
" @Inject void method(Foo foo) {}",
|
|
"}");
|
|
JavaFileObject usesInaccessible =
|
|
JavaFileObjects.forSourceLines(
|
|
"other.UsesInaccessible",
|
|
"package other;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"public class UsesInaccessible {",
|
|
" @Inject UsesInaccessible(Inaccessible inaccessible) {}",
|
|
"}");
|
|
JavaFileObject component =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.TestComponent",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Component;",
|
|
"import other.UsesInaccessible;",
|
|
"",
|
|
"@Component",
|
|
"interface TestComponent {",
|
|
" UsesInaccessible usesInaccessible();",
|
|
"}");
|
|
|
|
Compilation compilation =
|
|
compilerWithOptions(compilerMode.javacopts())
|
|
.compile(foo, inaccessible, usesInaccessible, component);
|
|
assertThat(compilation).succeeded();
|
|
assertThat(compilation)
|
|
.generatedSourceFile("other.Inaccessible_MembersInjector")
|
|
.hasSourceEquivalentTo(
|
|
JavaFileObjects.forSourceLines(
|
|
"other.Inaccessible_MembersInjector",
|
|
"package other;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class Inaccessible_MembersInjector",
|
|
" implements MembersInjector<Inaccessible> {",
|
|
" private final Provider<Foo> fooProvider;",
|
|
" private final Provider<Foo> fooProvider2;",
|
|
"",
|
|
" public Inaccessible_MembersInjector(",
|
|
" Provider<Foo> fooProvider, Provider<Foo> fooProvider2) {",
|
|
" this.fooProvider = fooProvider;",
|
|
" this.fooProvider2 = fooProvider2;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<Inaccessible> create(",
|
|
" Provider<Foo> fooProvider, Provider<Foo> fooProvider2) {",
|
|
" return new Inaccessible_MembersInjector(fooProvider, fooProvider2);}",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(Inaccessible instance) {",
|
|
" injectFoo(instance, fooProvider.get());",
|
|
" injectMethod(instance, fooProvider2.get());",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"other.Inaccessible.foo\")",
|
|
" public static void injectFoo(Object instance, Object foo) {",
|
|
" ((Inaccessible) instance).foo = (Foo) foo;",
|
|
" }",
|
|
"",
|
|
" public static void injectMethod(Object instance, Object foo) {",
|
|
" ((Inaccessible) instance).method((Foo) foo);",
|
|
" }",
|
|
"}"));
|
|
JavaFileObject generatedComponent =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.DaggerTestComponent",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import com.google.errorprone.annotations.CanIgnoreReturnValue;",
|
|
"import other.Foo_Factory;",
|
|
"import other.Inaccessible_Factory;",
|
|
"import other.Inaccessible_MembersInjector;",
|
|
"import other.UsesInaccessible;",
|
|
"import other.UsesInaccessible_Factory;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"final class DaggerTestComponent implements TestComponent {",
|
|
" private Object inaccessible() {",
|
|
" return injectInaccessible(Inaccessible_Factory.newInstance());",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" public UsesInaccessible usesInaccessible() {",
|
|
" return UsesInaccessible_Factory.newInstance(",
|
|
" inaccessible());",
|
|
" }",
|
|
"",
|
|
// TODO(ronshapiro): if possible, it would be great to rename "instance", but we
|
|
// need to make sure that this doesn't conflict with any framework field in this or
|
|
// any parent component
|
|
" @CanIgnoreReturnValue",
|
|
" private Object injectInaccessible(Object instance) {",
|
|
" Inaccessible_MembersInjector.injectFoo(instance, Foo_Factory.newInstance());",
|
|
" Inaccessible_MembersInjector.injectMethod(instance, Foo_Factory.newInstance());",
|
|
" return instance;",
|
|
" }",
|
|
"}");
|
|
assertThat(compilation)
|
|
.generatedSourceFile("test.DaggerTestComponent")
|
|
.containsElementsIn(generatedComponent);
|
|
}
|
|
|
|
@Test
|
|
public void accessibleRawType_ofInaccessibleType() {
|
|
JavaFileObject inaccessible =
|
|
JavaFileObjects.forSourceLines(
|
|
"other.Inaccessible",
|
|
"package other;",
|
|
"",
|
|
"class Inaccessible {}");
|
|
JavaFileObject inaccessiblesModule =
|
|
JavaFileObjects.forSourceLines(
|
|
"other.InaccessiblesModule",
|
|
"package other;",
|
|
"",
|
|
"import dagger.Module;",
|
|
"import dagger.Provides;",
|
|
"import java.util.ArrayList;",
|
|
"import java.util.List;",
|
|
"import javax.inject.Provider;",
|
|
"import javax.inject.Singleton;",
|
|
"",
|
|
"@Module",
|
|
"public class InaccessiblesModule {",
|
|
// force Provider initialization
|
|
" @Provides @Singleton static List<Inaccessible> inaccessibles() {",
|
|
" return new ArrayList<>();",
|
|
" }",
|
|
"}");
|
|
JavaFileObject usesInaccessibles =
|
|
JavaFileObjects.forSourceLines(
|
|
"other.UsesInaccessibles",
|
|
"package other;",
|
|
"",
|
|
"import java.util.List;",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"public class UsesInaccessibles {",
|
|
" @Inject UsesInaccessibles() {}",
|
|
" @Inject List<Inaccessible> inaccessibles;",
|
|
"}");
|
|
JavaFileObject component =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.TestComponent",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Component;",
|
|
"import javax.inject.Singleton;",
|
|
"import other.UsesInaccessibles;",
|
|
"",
|
|
"@Singleton",
|
|
"@Component(modules = other.InaccessiblesModule.class)",
|
|
"interface TestComponent {",
|
|
" UsesInaccessibles usesInaccessibles();",
|
|
"}");
|
|
|
|
Compilation compilation =
|
|
compilerWithOptions(compilerMode.javacopts())
|
|
.compile(inaccessible, inaccessiblesModule, usesInaccessibles, component);
|
|
assertThat(compilation).succeeded();
|
|
JavaFileObject generatedComponent =
|
|
compilerMode
|
|
.javaFileBuilder("test.DaggerTestComponent")
|
|
.addLines(
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import com.google.errorprone.annotations.CanIgnoreReturnValue;",
|
|
"import other.InaccessiblesModule;",
|
|
"import other.InaccessiblesModule_InaccessiblesFactory;",
|
|
"import other.UsesInaccessibles;",
|
|
"import other.UsesInaccessibles_Factory;",
|
|
"import other.UsesInaccessibles_MembersInjector;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"final class DaggerTestComponent implements TestComponent {")
|
|
.addLinesIn(
|
|
FAST_INIT_MODE,
|
|
" private volatile Object listOfInaccessible = new MemoizedSentinel();",
|
|
"",
|
|
" private List listOfInaccessible() {",
|
|
" Object local = listOfInaccessible;",
|
|
" if (local instanceof MemoizedSentinel) {",
|
|
" synchronized (local) {",
|
|
" local = listOfInaccessible;",
|
|
" if (local instanceof MemoizedSentinel) {",
|
|
" local = InaccessiblesModule_InaccessiblesFactory.inaccessibles();",
|
|
" listOfInaccessible =",
|
|
" DoubleCheck.reentrantCheck(listOfInaccessible, local);",
|
|
" }",
|
|
" }",
|
|
" }",
|
|
" return (List) local;",
|
|
" }")
|
|
.addLinesIn(
|
|
DEFAULT_MODE,
|
|
" @SuppressWarnings(\"rawtypes\")",
|
|
" private Provider inaccessiblesProvider;",
|
|
"",
|
|
" @SuppressWarnings(\"unchecked\")",
|
|
" private void initialize() {",
|
|
" this.inaccessiblesProvider =",
|
|
" DoubleCheck.provider(InaccessiblesModule_InaccessiblesFactory.create());",
|
|
" }")
|
|
.addLines(
|
|
"",
|
|
" @Override",
|
|
" public UsesInaccessibles usesInaccessibles() {",
|
|
" return injectUsesInaccessibles(",
|
|
" UsesInaccessibles_Factory.newInstance());",
|
|
" }",
|
|
"",
|
|
" @CanIgnoreReturnValue",
|
|
" private UsesInaccessibles injectUsesInaccessibles(",
|
|
" UsesInaccessibles instance) {",
|
|
" UsesInaccessibles_MembersInjector.injectInaccessibles(")
|
|
.addLinesIn(
|
|
FAST_INIT_MODE,
|
|
" instance, (List) listOfInaccessible());")
|
|
.addLinesIn(
|
|
DEFAULT_MODE,
|
|
" instance, (List) inaccessiblesProvider.get());")
|
|
.addLines(
|
|
" return instance;",
|
|
" }",
|
|
"}")
|
|
.build();
|
|
assertThat(compilation)
|
|
.generatedSourceFile("test.DaggerTestComponent")
|
|
.containsElementsIn(generatedComponent);
|
|
}
|
|
|
|
@Test
|
|
public void publicSupertypeHiddenSubtype() {
|
|
JavaFileObject foo =
|
|
JavaFileObjects.forSourceLines(
|
|
"other.Foo",
|
|
"package other;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class Foo {",
|
|
" @Inject Foo() {}",
|
|
"}");
|
|
JavaFileObject supertype =
|
|
JavaFileObjects.forSourceLines(
|
|
"other.Supertype",
|
|
"package other;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"public class Supertype<T> {",
|
|
" @Inject T t;",
|
|
"}");
|
|
JavaFileObject subtype =
|
|
JavaFileObjects.forSourceLines(
|
|
"other.Subtype",
|
|
"package other;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class Subtype extends Supertype<Foo> {",
|
|
" @Inject Subtype() {}",
|
|
"}");
|
|
JavaFileObject injectsSubtype =
|
|
JavaFileObjects.forSourceLines(
|
|
"other.InjectsSubtype",
|
|
"package other;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"public class InjectsSubtype {",
|
|
" @Inject InjectsSubtype(Subtype s) {}",
|
|
"}");
|
|
JavaFileObject component =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.TestComponent",
|
|
"package test;",
|
|
"",
|
|
"import dagger.Component;",
|
|
"",
|
|
"@Component",
|
|
"interface TestComponent {",
|
|
" other.InjectsSubtype injectsSubtype();",
|
|
"}");
|
|
|
|
Compilation compilation =
|
|
compilerWithOptions(compilerMode.javacopts())
|
|
.compile(foo, supertype, subtype, injectsSubtype, component);
|
|
assertThat(compilation).succeeded();
|
|
JavaFileObject generatedComponent =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.DaggerTestComponent",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import com.google.errorprone.annotations.CanIgnoreReturnValue;",
|
|
"import other.Foo_Factory;",
|
|
"import other.InjectsSubtype;",
|
|
"import other.InjectsSubtype_Factory;",
|
|
"import other.Subtype_Factory;",
|
|
"import other.Supertype;",
|
|
"import other.Supertype_MembersInjector;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"final class DaggerTestComponent implements TestComponent {",
|
|
" private Object subtype() {",
|
|
" return injectSubtype(Subtype_Factory.newInstance());",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" public InjectsSubtype injectsSubtype() {",
|
|
" return InjectsSubtype_Factory.newInstance(subtype());",
|
|
" }",
|
|
"",
|
|
" @CanIgnoreReturnValue",
|
|
" private Object injectSubtype(Object instance) {",
|
|
" Supertype_MembersInjector.injectT(",
|
|
" (Supertype) instance, Foo_Factory.newInstance());",
|
|
" return instance;",
|
|
" }",
|
|
"}");
|
|
|
|
assertThat(compilation)
|
|
.generatedSourceFile("test.DaggerTestComponent")
|
|
.containsElementsIn(generatedComponent);
|
|
}
|
|
|
|
// Shows that we shouldn't create a members injector for a type that doesn't have
|
|
// @Inject fields or @Inject constructor even if it extends and is extended by types that do.
|
|
@Test
|
|
public void middleClassNoFieldInjection() {
|
|
JavaFileObject classA =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.A",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class A extends B {",
|
|
" @Inject String valueA;",
|
|
"}");
|
|
JavaFileObject classB =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.B",
|
|
"package test;",
|
|
"",
|
|
"class B extends C {",
|
|
"}");
|
|
JavaFileObject classC =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.C",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class C { ",
|
|
" @Inject String valueC;",
|
|
"}");
|
|
JavaFileObject expectedAMembersInjector =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.A_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class A_MembersInjector implements MembersInjector<A> {",
|
|
" private final Provider<String> valueCProvider;",
|
|
" private final Provider<String> valueAProvider;",
|
|
"",
|
|
" public A_MembersInjector(",
|
|
" Provider<String> valueCProvider, Provider<String> valueAProvider) {",
|
|
" this.valueCProvider = valueCProvider;",
|
|
" this.valueAProvider = valueAProvider;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<A> create(",
|
|
" Provider<String> valueCProvider, Provider<String> valueAProvider) {",
|
|
" return new A_MembersInjector(valueCProvider, valueAProvider);",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(A instance) {",
|
|
" C_MembersInjector.injectValueC(instance, valueCProvider.get());",
|
|
" injectValueA(instance, valueAProvider.get());",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.A.valueA\")",
|
|
" public static void injectValueA(Object instance, String valueA) {",
|
|
" ((A) instance).valueA = valueA;",
|
|
" }",
|
|
"}");
|
|
|
|
JavaFileObject expectedCMembersInjector =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.C_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class C_MembersInjector implements MembersInjector<C> {",
|
|
" private final Provider<String> valueCProvider;",
|
|
"",
|
|
" public C_MembersInjector(Provider<String> valueCProvider) {",
|
|
" this.valueCProvider = valueCProvider;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<C> create(",
|
|
" Provider<String> valueCProvider) {",
|
|
" return new C_MembersInjector(valueCProvider);",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(C instance) {",
|
|
" injectValueC(instance, valueCProvider.get());",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.C.valueC\")",
|
|
" public static void injectValueC(Object instance, String valueC) {",
|
|
" ((C) instance).valueC = valueC;",
|
|
" }",
|
|
"}");
|
|
|
|
|
|
Compilation compilation =
|
|
compilerWithOptions(compilerMode.javacopts())
|
|
.compile(classA, classB, classC);
|
|
assertThat(compilation).succeeded();
|
|
assertThat(compilation)
|
|
.generatedSourceFile("test.A_MembersInjector")
|
|
.hasSourceEquivalentTo(expectedAMembersInjector);
|
|
assertThat(compilation)
|
|
.generatedSourceFile("test.C_MembersInjector")
|
|
.hasSourceEquivalentTo(expectedCMembersInjector);
|
|
|
|
try {
|
|
assertThat(compilation).generatedSourceFile("test.B_MembersInjector");
|
|
// Can't throw an assertion error since it would be caught.
|
|
throw new IllegalStateException("Test generated a B_MembersInjector");
|
|
} catch (AssertionError expected) {
|
|
}
|
|
}
|
|
|
|
// Shows that we do generate a MembersInjector for a type that has an @Inject
|
|
// constructor and that extends a type with @Inject fields, even if it has no local field
|
|
// injection sites
|
|
// TODO(erichang): Are these even used anymore?
|
|
@Test
|
|
public void testConstructorInjectedFieldInjection() {
|
|
JavaFileObject classA =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.A",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class A extends B {",
|
|
" @Inject A() {}",
|
|
"}");
|
|
JavaFileObject classB =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.B",
|
|
"package test;",
|
|
"",
|
|
"import javax.inject.Inject;",
|
|
"",
|
|
"class B { ",
|
|
" @Inject String valueB;",
|
|
"}");
|
|
JavaFileObject expectedAMembersInjector =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.A_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class A_MembersInjector implements MembersInjector<A> {",
|
|
" private final Provider<String> valueBProvider;",
|
|
"",
|
|
" public A_MembersInjector(Provider<String> valueBProvider) {",
|
|
" this.valueBProvider = valueBProvider;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<A> create(Provider<String> valueBProvider) {",
|
|
" return new A_MembersInjector(valueBProvider);",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(A instance) {",
|
|
" B_MembersInjector.injectValueB(instance, valueBProvider.get());",
|
|
" }",
|
|
"}");
|
|
|
|
JavaFileObject expectedBMembersInjector =
|
|
JavaFileObjects.forSourceLines(
|
|
"test.B_MembersInjector",
|
|
"package test;",
|
|
"",
|
|
GeneratedLines.generatedImports(
|
|
"import dagger.MembersInjector;",
|
|
"import dagger.internal.InjectedFieldSignature;",
|
|
"import javax.inject.Provider;"),
|
|
"",
|
|
GeneratedLines.generatedAnnotations(),
|
|
"public final class B_MembersInjector implements MembersInjector<B> {",
|
|
" private final Provider<String> valueBProvider;",
|
|
"",
|
|
" public B_MembersInjector(Provider<String> valueBProvider) {",
|
|
" this.valueBProvider = valueBProvider;",
|
|
" }",
|
|
"",
|
|
" public static MembersInjector<B> create(",
|
|
" Provider<String> valueBProvider) {",
|
|
" return new B_MembersInjector(valueBProvider);",
|
|
" }",
|
|
"",
|
|
" @Override",
|
|
" public void injectMembers(B instance) {",
|
|
" injectValueB(instance, valueBProvider.get());",
|
|
" }",
|
|
"",
|
|
" @InjectedFieldSignature(\"test.B.valueB\")",
|
|
" public static void injectValueB(Object instance, String valueB) {",
|
|
" ((B) instance).valueB = valueB;",
|
|
" }",
|
|
"}");
|
|
|
|
|
|
Compilation compilation =
|
|
compilerWithOptions(compilerMode.javacopts())
|
|
.compile(classA, classB);
|
|
assertThat(compilation).succeeded();
|
|
assertThat(compilation)
|
|
.generatedSourceFile("test.A_MembersInjector")
|
|
.hasSourceEquivalentTo(expectedAMembersInjector);
|
|
assertThat(compilation)
|
|
.generatedSourceFile("test.B_MembersInjector")
|
|
.hasSourceEquivalentTo(expectedBMembersInjector);
|
|
}
|
|
}
|