1 /* 2 * Copyright (C) 2017 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 import static dagger.internal.codegen.CompilerMode.DEFAULT_MODE; 21 import static dagger.internal.codegen.CompilerMode.FAST_INIT_MODE; 22 import static dagger.internal.codegen.Compilers.compilerWithOptions; 23 import static dagger.internal.codegen.GeneratedLines.GENERATED_CODE_ANNOTATIONS; 24 25 import com.google.testing.compile.Compilation; 26 import com.google.testing.compile.JavaFileObjects; 27 import java.util.Collection; 28 import javax.tools.JavaFileObject; 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 OptionalBindingRequestFulfillmentTest { 36 @Parameters(name = "{0}") parameters()37 public static Collection<Object[]> parameters() { 38 return CompilerMode.TEST_PARAMETERS; 39 } 40 41 private final CompilerMode compilerMode; 42 OptionalBindingRequestFulfillmentTest(CompilerMode compilerMode)43 public OptionalBindingRequestFulfillmentTest(CompilerMode compilerMode) { 44 this.compilerMode = compilerMode; 45 } 46 47 @Test inlinedOptionalBindings()48 public void inlinedOptionalBindings() { 49 JavaFileObject module = 50 JavaFileObjects.forSourceLines( 51 "test.TestModule", 52 "package test;", 53 "", 54 "import dagger.Module;", 55 "import dagger.BindsOptionalOf;", 56 "import other.Maybe;", 57 "import other.DefinitelyNot;", 58 "", 59 "@Module", 60 "interface TestModule {", 61 " @BindsOptionalOf Maybe maybe();", 62 " @BindsOptionalOf DefinitelyNot definitelyNot();", 63 "}"); 64 JavaFileObject maybe = 65 JavaFileObjects.forSourceLines( 66 "other.Maybe", 67 "package other;", 68 "", 69 "import dagger.Module;", 70 "import dagger.Provides;", 71 "", 72 "public class Maybe {", 73 " @Module", 74 " public static class MaybeModule {", 75 " @Provides static Maybe provideMaybe() { return new Maybe(); }", 76 " }", 77 "}"); 78 JavaFileObject definitelyNot = 79 JavaFileObjects.forSourceLines( 80 "other.DefinitelyNot", 81 "package other;", 82 "", 83 "public class DefinitelyNot {}"); 84 85 JavaFileObject component = 86 JavaFileObjects.forSourceLines( 87 "test.TestComponent", 88 "package test;", 89 "", 90 "import com.google.common.base.Optional;", 91 "import dagger.Component;", 92 "import dagger.Lazy;", 93 "import javax.inject.Provider;", 94 "import other.Maybe;", 95 "import other.DefinitelyNot;", 96 "", 97 "@Component(modules = {TestModule.class, Maybe.MaybeModule.class})", 98 "interface TestComponent {", 99 " Optional<Maybe> maybe();", 100 " Optional<Provider<Lazy<Maybe>>> providerOfLazyOfMaybe();", 101 " Optional<DefinitelyNot> definitelyNot();", 102 " Optional<Provider<Lazy<DefinitelyNot>>> providerOfLazyOfDefinitelyNot();", 103 "}"); 104 105 JavaFileObject generatedComponent = 106 compilerMode 107 .javaFileBuilder("test.DaggerTestComponent") 108 .addLines( 109 "package test;", 110 "", 111 "import com.google.common.base.Optional;", 112 "", 113 GENERATED_CODE_ANNOTATIONS, 114 "final class DaggerTestComponent implements TestComponent {") 115 .addLinesIn( 116 FAST_INIT_MODE, 117 " private volatile Provider<Maybe> provideMaybeProvider;", 118 "", 119 " private Provider<Maybe> maybeProvider() {", 120 " Object local = provideMaybeProvider;", 121 " if (local == null) {", 122 " local = new SwitchingProvider<>(0);", 123 " provideMaybeProvider = (Provider<Maybe>) local;", 124 " }", 125 " return (Provider<Maybe>) local;", 126 " }") 127 .addLines( 128 " @Override", 129 " public Optional<Maybe> maybe() {", 130 " return Optional.of(", 131 " Maybe_MaybeModule_ProvideMaybeFactory.provideMaybe());", 132 " }", 133 "", 134 " @Override", 135 " public Optional<Provider<Lazy<Maybe>>> providerOfLazyOfMaybe() {", 136 " return Optional.of(ProviderOfLazy.create(") 137 .addLinesIn( 138 DEFAULT_MODE, // 139 " Maybe_MaybeModule_ProvideMaybeFactory.create()));") 140 .addLinesIn( 141 FAST_INIT_MODE, // 142 " maybeProvider()));") 143 .addLines( 144 " }", 145 "", 146 " @Override", 147 " public Optional<DefinitelyNot> definitelyNot() {", 148 " return Optional.<DefinitelyNot>absent();", 149 " }", 150 "", 151 " @Override", 152 " public Optional<Provider<Lazy<DefinitelyNot>>>", 153 " providerOfLazyOfDefinitelyNot() {", 154 " return Optional.<Provider<Lazy<DefinitelyNot>>>absent();", 155 " }") 156 .addLinesIn( 157 FAST_INIT_MODE, 158 " private final class SwitchingProvider<T> implements Provider<T> {", 159 " private final int id;", 160 "", 161 " SwitchingProvider(int id) {", 162 " this.id = id;", 163 " }", 164 "", 165 " @SuppressWarnings(\"unchecked\")", 166 " @Override", 167 " public T get() {", 168 " switch (id) {", 169 " case 0:", 170 " return (T) Maybe_MaybeModule_ProvideMaybeFactory.provideMaybe();", 171 " default:", 172 " throw new AssertionError(id);", 173 " }", 174 " }", 175 " }", 176 "}") 177 .build(); 178 Compilation compilation = 179 compilerWithOptions( 180 compilerMode 181 , CompilerMode.JAVA7 182 ) 183 .compile(module, maybe, definitelyNot, component); 184 assertThat(compilation).succeeded(); 185 assertThat(compilation) 186 .generatedSourceFile("test.DaggerTestComponent") 187 .containsElementsIn(generatedComponent); 188 } 189 190 @Test requestForFuture()191 public void requestForFuture() { 192 JavaFileObject module = 193 JavaFileObjects.forSourceLines( 194 "test.TestModule", 195 "package test;", 196 "", 197 "import dagger.Module;", 198 "import dagger.BindsOptionalOf;", 199 "import other.Maybe;", 200 "import other.DefinitelyNot;", 201 "", 202 "@Module", 203 "interface TestModule {", 204 " @BindsOptionalOf Maybe maybe();", 205 " @BindsOptionalOf DefinitelyNot definitelyNot();", 206 "}"); 207 JavaFileObject maybe = 208 JavaFileObjects.forSourceLines( 209 "other.Maybe", 210 "package other;", 211 "", 212 "import dagger.Module;", 213 "import dagger.Provides;", 214 "", 215 "public class Maybe {", 216 " @Module", 217 " public static class MaybeModule {", 218 " @Provides static Maybe provideMaybe() { return new Maybe(); }", 219 " }", 220 "}"); 221 JavaFileObject definitelyNot = 222 JavaFileObjects.forSourceLines( 223 "other.DefinitelyNot", 224 "package other;", 225 "", 226 "public class DefinitelyNot {}"); 227 228 JavaFileObject component = 229 JavaFileObjects.forSourceLines( 230 "test.TestComponent", 231 "package test;", 232 "", 233 "import com.google.common.base.Optional;", 234 "import com.google.common.util.concurrent.ListenableFuture;", 235 "import dagger.producers.ProductionComponent;", 236 "import javax.inject.Provider;", 237 "import other.Maybe;", 238 "import other.DefinitelyNot;", 239 "", 240 "@ProductionComponent(modules = {TestModule.class, Maybe.MaybeModule.class})", 241 "interface TestComponent {", 242 " ListenableFuture<Optional<Maybe>> maybe();", 243 " ListenableFuture<Optional<DefinitelyNot>> definitelyNot();", 244 "}"); 245 JavaFileObject generatedComponent = 246 JavaFileObjects.forSourceLines( 247 "test.DaggerTestComponent", 248 "package test;", 249 "", 250 "import com.google.common.base.Optional;", 251 "import dagger.producers.internal.CancellationListener;", 252 "", 253 GENERATED_CODE_ANNOTATIONS, 254 "final class DaggerTestComponent implements TestComponent, CancellationListener {", 255 " @Override", 256 " public ListenableFuture<Optional<Maybe>> maybe() {", 257 " return Futures.immediateFuture(", 258 " Optional.of(Maybe_MaybeModule_ProvideMaybeFactory.provideMaybe()));", 259 " }", 260 "", 261 " @Override", 262 " public ListenableFuture<Optional<DefinitelyNot>> definitelyNot() {", 263 " return Futures.immediateFuture(Optional.<DefinitelyNot>absent());", 264 " }", 265 "", 266 " @Override", 267 " public void onProducerFutureCancelled(boolean mayInterruptIfRunning) {}", 268 "}"); 269 270 Compilation compilation = 271 compilerWithOptions( 272 compilerMode 273 , CompilerMode.JAVA7 274 ) 275 .compile(module, maybe, definitelyNot, component); 276 assertThat(compilation).succeeded(); 277 assertThat(compilation) 278 .generatedSourceFile("test.DaggerTestComponent") 279 .containsElementsIn(generatedComponent); 280 } 281 } 282