• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Dagger Authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dagger.internal.codegen;
18 
19 import static com.google.testing.compile.CompilationSubject.assertThat;
20 
21 import androidx.room.compiler.processing.util.Source;
22 import com.google.testing.compile.Compilation;
23 import com.google.testing.compile.JavaFileObjects;
24 import dagger.testing.compile.CompilerTests;
25 import dagger.testing.golden.GoldenFileRule;
26 import java.util.Collection;
27 import javax.tools.JavaFileObject;
28 import org.junit.Rule;
29 import org.junit.Test;
30 import org.junit.runner.RunWith;
31 import org.junit.runners.Parameterized;
32 import org.junit.runners.Parameterized.Parameters;
33 
34 @RunWith(Parameterized.class)
35 public class LazyClassKeyMapBindingComponentProcessorTest {
36   @Parameters(name = "{0}")
parameters()37   public static Collection<Object[]> parameters() {
38     return CompilerMode.TEST_PARAMETERS;
39   }
40 
41   @Rule public GoldenFileRule goldenFileRule = new GoldenFileRule();
42 
43   private final CompilerMode compilerMode;
44 
LazyClassKeyMapBindingComponentProcessorTest(CompilerMode compilerMode)45   public LazyClassKeyMapBindingComponentProcessorTest(CompilerMode compilerMode) {
46     this.compilerMode = compilerMode;
47   }
48 
49   // Cannot convert to use ksp as this test relies on AutoAnnotationProcessor.
50   @Test
mapBindingsWithInaccessibleKeys()51   public void mapBindingsWithInaccessibleKeys() throws Exception {
52     JavaFileObject mapKeys =
53         JavaFileObjects.forSourceLines(
54             "mapkeys.MapKeys",
55             "package mapkeys;",
56             "",
57             "import dagger.MapKey;",
58             "import dagger.multibindings.LazyClassKey;",
59             "",
60             "public class MapKeys {",
61             "  @MapKey(unwrapValue = false)",
62             "  public @interface ComplexKey {",
63             "    Class<?>[] manyClasses();",
64             "    Class<?> oneClass();",
65             "    LazyClassKey annotation();",
66             "  }",
67             "",
68             "  interface Inaccessible {}",
69             "}");
70     JavaFileObject moduleFile =
71         JavaFileObjects.forSourceLines(
72             "mapkeys.MapModule",
73             "package mapkeys;",
74             "",
75             "import dagger.Binds;",
76             "import dagger.Module;",
77             "import dagger.Provides;",
78             "import dagger.multibindings.LazyClassKey;",
79             "import dagger.multibindings.IntoMap;",
80             "import java.util.Map;",
81             "import javax.inject.Provider;",
82             "",
83             "@Module",
84             "public interface MapModule {",
85             "  @Provides @IntoMap @LazyClassKey(MapKeys.Inaccessible.class)",
86             "  static int classKey() { return 1; }",
87             "",
88             "  @Provides @IntoMap",
89             "  @MapKeys.ComplexKey(",
90             "    manyClasses = {java.lang.Object.class, java.lang.String.class},",
91             "    oneClass = MapKeys.Inaccessible.class,",
92             "    annotation = @LazyClassKey(java.lang.Object.class)",
93             "  )",
94             "  static int complexKeyWithInaccessibleValue() { return 1; }",
95             "",
96             "  @Provides @IntoMap",
97             "  @MapKeys.ComplexKey(",
98             "    manyClasses = {MapKeys.Inaccessible.class, java.lang.String.class},",
99             "    oneClass = java.lang.String.class,",
100             "    annotation = @LazyClassKey(java.lang.Object.class)",
101             "  )",
102             "  static int complexKeyWithInaccessibleArrayValue() { return 1; }",
103             "",
104             "  @Provides @IntoMap",
105             "  @MapKeys.ComplexKey(",
106             "    manyClasses = {java.lang.String.class},",
107             "    oneClass = java.lang.String.class,",
108             "    annotation = @LazyClassKey(MapKeys.Inaccessible.class)",
109             "  )",
110             "  static int complexKeyWithInaccessibleAnnotationValue() { return 1; }",
111             "}");
112     JavaFileObject componentFile =
113         JavaFileObjects.forSourceLines(
114             "test.TestComponent",
115             "package test;",
116             "",
117             "import dagger.Component;",
118             "import java.util.Map;",
119             "import javax.inject.Provider;",
120             "import mapkeys.MapKeys;",
121             "import mapkeys.MapModule;",
122             "",
123             "@Component(modules = MapModule.class)",
124             "interface TestComponent {",
125             "  Map<Class<?>, Integer> classKey();",
126             "  Provider<Map<Class<?>, Integer>> classKeyProvider();",
127             "",
128             "  Map<MapKeys.ComplexKey, Integer> complexKey();",
129             "  Provider<Map<MapKeys.ComplexKey, Integer>> complexKeyProvider();",
130             "}");
131     Compilation compilation =
132         Compilers.compilerWithOptions(compilerMode.javacopts())
133             .compile(mapKeys, moduleFile, componentFile);
134     assertThat(compilation).succeeded();
135     assertThat(compilation)
136         .generatedSourceFile("test.DaggerTestComponent")
137         .hasSourceEquivalentTo(goldenFileRule.goldenFile("test.DaggerTestComponent"));
138     assertThat(compilation)
139         .generatedSourceFile(
140             "mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey")
141         .hasSourceEquivalentTo(
142             goldenFileRule.goldenFile(
143                 "mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey"));
144     assertThat(compilation)
145         .generatedSourceFile("mapkeys.MapModule_ClassKeyMapKey")
146         .hasSourceEquivalentTo(goldenFileRule.goldenFile("mapkeys.MapModule_ClassKeyMapKey"));
147   }
148 
149   @Test
lazyClassKeySimilarQualifiedName_doesNotConflict()150   public void lazyClassKeySimilarQualifiedName_doesNotConflict() throws Exception {
151     Source fooBar =
152         CompilerTests.javaSource("test.Foo_Bar", "package test;", "", "interface Foo_Bar {}");
153     Source fooBar2 =
154         CompilerTests.javaSource(
155             "test.Foo", "package test;", "", "interface Foo { interface Bar {} }");
156     Source mapKeyBindingsModule =
157         CompilerTests.javaSource(
158             "test.MapKeyBindingsModule",
159             "package test;",
160             "",
161             "import dagger.Module;",
162             "import dagger.Provides;",
163             "import dagger.multibindings.LazyClassKey;",
164             "import dagger.multibindings.IntoMap;",
165             "",
166             "@Module",
167             "public interface MapKeyBindingsModule {",
168             " @Provides @IntoMap @LazyClassKey(test.Foo_Bar.class)",
169             " static int classKey() { return 1; }",
170             "",
171             " @Provides @IntoMap @LazyClassKey(test.Foo.Bar.class)",
172             " static int classKey2() { return 1; }",
173             "}");
174 
175     Source componentFile =
176         CompilerTests.javaSource(
177             "test.TestComponent",
178             "package test;",
179             "",
180             "import dagger.Component;",
181             "import java.util.Map;",
182             "",
183             "@Component(modules = MapKeyBindingsModule.class)",
184             "interface TestComponent {",
185             "  Map<Class<?>, Integer> classKey();",
186             "}");
187     CompilerTests.daggerCompiler(fooBar, fooBar2, mapKeyBindingsModule, componentFile)
188         .withProcessingOptions(compilerMode.processorOptions())
189         .compile(subject -> subject.hasErrorCount(0));
190   }
191 }
192