1 /* 2 * Copyright (C) 2015 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 dagger.internal.codegen.base.ComponentCreatorAnnotation.COMPONENT_BUILDER; 20 import static dagger.internal.codegen.binding.ErrorMessages.creatorMessagesFor; 21 22 import androidx.room.compiler.processing.util.Source; 23 import dagger.internal.codegen.binding.ErrorMessages; 24 import dagger.testing.compile.CompilerTests; 25 import dagger.testing.golden.GoldenFileRule; 26 import java.util.Collection; 27 import org.junit.Rule; 28 import org.junit.Test; 29 import org.junit.runner.RunWith; 30 import org.junit.runners.Parameterized; 31 import org.junit.runners.Parameterized.Parameters; 32 33 /** Tests for {@link dagger.Component.Builder} */ 34 @RunWith(Parameterized.class) 35 public class ComponentBuilderTest { 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 ComponentBuilderTest(CompilerMode compilerMode)45 public ComponentBuilderTest(CompilerMode compilerMode) { 46 this.compilerMode = compilerMode; 47 } 48 49 private static final ErrorMessages.ComponentCreatorMessages MSGS = 50 creatorMessagesFor(COMPONENT_BUILDER); 51 52 @Test testUsesBuildAndSetterNames()53 public void testUsesBuildAndSetterNames() throws Exception { 54 Source moduleFile = 55 CompilerTests.javaSource( 56 "test.TestModule", 57 "package test;", 58 "", 59 "import dagger.Module;", 60 "import dagger.Provides;", 61 "", 62 "@Module", 63 "final class TestModule {", 64 " @Provides String string() { return null; }", 65 "}"); 66 67 Source componentFile = 68 CompilerTests.javaSource( 69 "test.TestComponent", 70 "package test;", 71 "", 72 "import dagger.Component;", 73 "", 74 "@Component(modules = TestModule.class)", 75 "interface TestComponent {", 76 " String string();", 77 "", 78 " @Component.Builder", 79 " interface Builder {", 80 " Builder setTestModule(TestModule testModule);", 81 " TestComponent create();", 82 " }", 83 "}"); 84 85 CompilerTests.daggerCompiler(moduleFile, componentFile) 86 .withProcessingOptions(compilerMode.processorOptions()) 87 .compile( 88 subject -> { 89 subject.hasErrorCount(0); 90 subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent")); 91 }); 92 } 93 94 @Test testSetterMethodWithMoreThanOneArgFails()95 public void testSetterMethodWithMoreThanOneArgFails() { 96 Source componentFile = 97 CompilerTests.javaSource( 98 "test.SimpleComponent", 99 "package test;", 100 "", 101 "import dagger.Component;", 102 "import javax.inject.Provider;", 103 "", 104 "@Component", 105 "abstract class SimpleComponent {", 106 " @Component.Builder", 107 " interface Builder {", 108 " SimpleComponent build();", 109 " Builder set(String s, Integer i);", 110 " Builder set(Number n, Double d);", 111 " }", 112 "}"); 113 114 CompilerTests.daggerCompiler(componentFile) 115 .withProcessingOptions(compilerMode.processorOptions()) 116 .compile( 117 subject -> { 118 subject.hasErrorCount(2); 119 subject 120 .hasErrorContaining(MSGS.setterMethodsMustTakeOneArg()) 121 .onSource(componentFile) 122 .onLineContaining("Builder set(String s, Integer i);"); 123 subject 124 .hasErrorContaining(MSGS.setterMethodsMustTakeOneArg()) 125 .onSource(componentFile) 126 .onLineContaining("Builder set(Number n, Double d);"); 127 }); 128 } 129 130 @Test testInheritedSetterMethodWithMoreThanOneArgFails()131 public void testInheritedSetterMethodWithMoreThanOneArgFails() { 132 Source componentFile = 133 CompilerTests.javaSource( 134 "test.SimpleComponent", 135 "package test;", 136 "", 137 "import dagger.Component;", 138 "import javax.inject.Provider;", 139 "", 140 "@Component", 141 "abstract class SimpleComponent {", 142 " interface Parent {", 143 " SimpleComponent build();", 144 " Builder set1(String s, Integer i);", 145 " }", 146 "", 147 " @Component.Builder", 148 " interface Builder extends Parent {}", 149 "}"); 150 151 CompilerTests.daggerCompiler(componentFile) 152 .withProcessingOptions(compilerMode.processorOptions()) 153 .compile( 154 subject -> { 155 subject.hasErrorCount(1); 156 subject 157 .hasErrorContaining( 158 String.format( 159 MSGS.inheritedSetterMethodsMustTakeOneArg(), 160 "test.SimpleComponent.Builder test.SimpleComponent.Parent.set1(" 161 + "String, Integer)")) 162 .onSource(componentFile) 163 .onLineContaining("interface Builder"); 164 }); 165 } 166 167 @Test testSetterReturningNonVoidOrBuilderFails()168 public void testSetterReturningNonVoidOrBuilderFails() { 169 Source componentFile = 170 CompilerTests.javaSource( 171 "test.SimpleComponent", 172 "package test;", 173 "", 174 "import dagger.Component;", 175 "import javax.inject.Provider;", 176 "", 177 "@Component", 178 "abstract class SimpleComponent {", 179 " @Component.Builder", 180 " interface Builder {", 181 " SimpleComponent build();", 182 " String set(Integer i);", 183 " }", 184 "}"); 185 186 CompilerTests.daggerCompiler(componentFile) 187 .withProcessingOptions(compilerMode.processorOptions()) 188 .compile( 189 subject -> { 190 subject.hasErrorCount(1); 191 subject 192 .hasErrorContaining(MSGS.setterMethodsMustReturnVoidOrBuilder()) 193 .onSource(componentFile) 194 .onLineContaining("String set(Integer i);"); 195 }); 196 } 197 198 @Test testInheritedSetterReturningNonVoidOrBuilderFails()199 public void testInheritedSetterReturningNonVoidOrBuilderFails() { 200 Source componentFile = 201 CompilerTests.javaSource( 202 "test.SimpleComponent", 203 "package test;", 204 "", 205 "import dagger.Component;", 206 "import javax.inject.Provider;", 207 "", 208 "@Component", 209 "abstract class SimpleComponent {", 210 " interface Parent {", 211 " SimpleComponent build();", 212 " String set(Integer i);", 213 " }", 214 "", 215 " @Component.Builder", 216 " interface Builder extends Parent {}", 217 "}"); 218 219 CompilerTests.daggerCompiler(componentFile) 220 .withProcessingOptions(compilerMode.processorOptions()) 221 .compile( 222 subject -> { 223 subject.hasErrorCount(1); 224 subject 225 .hasErrorContaining( 226 String.format( 227 MSGS.inheritedSetterMethodsMustReturnVoidOrBuilder(), 228 "String test.SimpleComponent.Parent.set(Integer)")) 229 .onSource(componentFile) 230 .onLineContaining("interface Builder"); 231 }); 232 } 233 234 @Test testGenericsOnSetterMethodFails()235 public void testGenericsOnSetterMethodFails() { 236 Source componentFile = 237 CompilerTests.javaSource( 238 "test.SimpleComponent", 239 "package test;", 240 "", 241 "import dagger.Component;", 242 "import javax.inject.Provider;", 243 "", 244 "@Component", 245 "abstract class SimpleComponent {", 246 " @Component.Builder", 247 " interface Builder {", 248 " SimpleComponent build();", 249 " <T> Builder set(T t);", 250 " }", 251 "}"); 252 253 CompilerTests.daggerCompiler(componentFile) 254 .withProcessingOptions(compilerMode.processorOptions()) 255 .compile( 256 subject -> { 257 subject.hasErrorCount(1); 258 subject 259 .hasErrorContaining(MSGS.methodsMayNotHaveTypeParameters()) 260 .onSource(componentFile) 261 .onLineContaining("<T> Builder set(T t);"); 262 }); 263 } 264 265 @Test testGenericsOnInheritedSetterMethodFails()266 public void testGenericsOnInheritedSetterMethodFails() { 267 Source componentFile = 268 CompilerTests.javaSource( 269 "test.SimpleComponent", 270 "package test;", 271 "", 272 "import dagger.Component;", 273 "import javax.inject.Provider;", 274 "", 275 "@Component", 276 "abstract class SimpleComponent {", 277 " interface Parent {", 278 " SimpleComponent build();", 279 " <T> Builder set(T t);", 280 " }", 281 "", 282 " @Component.Builder", 283 " interface Builder extends Parent {}", 284 "}"); 285 286 CompilerTests.daggerCompiler(componentFile) 287 .withProcessingOptions(compilerMode.processorOptions()) 288 .compile( 289 subject -> { 290 subject.hasErrorCount(1); 291 subject 292 .hasErrorContaining( 293 String.format( 294 MSGS.inheritedMethodsMayNotHaveTypeParameters(), 295 "test.SimpleComponent.Builder test.SimpleComponent.Parent.set(T)")) 296 .onSource(componentFile) 297 .onLineContaining("interface Builder"); 298 }); 299 } 300 301 @Test testBindsInstanceNotAllowedOnBothSetterAndParameter()302 public void testBindsInstanceNotAllowedOnBothSetterAndParameter() { 303 Source componentFile = 304 CompilerTests.javaSource( 305 "test.SimpleComponent", 306 "package test;", 307 "", 308 "import dagger.BindsInstance;", 309 "import dagger.Component;", 310 "", 311 "@Component", 312 "abstract class SimpleComponent {", 313 " abstract String s();", 314 "", 315 " @Component.Builder", 316 " interface Builder {", 317 " @BindsInstance", 318 " Builder s(@BindsInstance String s);", 319 "", 320 " SimpleComponent build();", 321 " }", 322 "}"); 323 324 CompilerTests.daggerCompiler(componentFile) 325 .withProcessingOptions(compilerMode.processorOptions()) 326 .compile( 327 subject -> { 328 subject.hasErrorCount(1); 329 subject 330 .hasErrorContaining(MSGS.bindsInstanceNotAllowedOnBothSetterMethodAndParameter()) 331 .onSource(componentFile) 332 .onLineContaining("Builder s("); 333 }); 334 } 335 336 @Test testBindsInstanceNotAllowedOnBothSetterAndParameter_inherited()337 public void testBindsInstanceNotAllowedOnBothSetterAndParameter_inherited() { 338 Source componentFile = 339 CompilerTests.javaSource( 340 "test.SimpleComponent", 341 "package test;", 342 "", 343 "import dagger.BindsInstance;", 344 "import dagger.Component;", 345 "", 346 "@Component", 347 "abstract class SimpleComponent {", 348 " abstract String s();", 349 "", 350 " interface BuilderParent<B extends BuilderParent> {", 351 " @BindsInstance", 352 " B s(@BindsInstance String s);", 353 " }", 354 "", 355 " @Component.Builder", 356 " interface Builder extends BuilderParent<Builder> {", 357 " SimpleComponent build();", 358 " }", 359 "}"); 360 361 CompilerTests.daggerCompiler(componentFile) 362 .withProcessingOptions(compilerMode.processorOptions()) 363 .compile( 364 subject -> { 365 subject.hasErrorCount(1); 366 subject 367 .hasErrorContaining( 368 String.format( 369 MSGS.inheritedBindsInstanceNotAllowedOnBothSetterMethodAndParameter(), 370 "@BindsInstance B test.SimpleComponent.BuilderParent.s(String)")) 371 .onSource(componentFile) 372 .onLineContaining("Builder extends BuilderParent<Builder>"); 373 }); 374 } 375 } 376