1*f585d8a3SJacky Wang /* 2*f585d8a3SJacky Wang * Copyright (C) 2016 The Dagger Authors. 3*f585d8a3SJacky Wang * 4*f585d8a3SJacky Wang * Licensed under the Apache License, Version 2.0 (the "License"); 5*f585d8a3SJacky Wang * you may not use this file except in compliance with the License. 6*f585d8a3SJacky Wang * You may obtain a copy of the License at 7*f585d8a3SJacky Wang * 8*f585d8a3SJacky Wang * http://www.apache.org/licenses/LICENSE-2.0 9*f585d8a3SJacky Wang * 10*f585d8a3SJacky Wang * Unless required by applicable law or agreed to in writing, software 11*f585d8a3SJacky Wang * distributed under the License is distributed on an "AS IS" BASIS, 12*f585d8a3SJacky Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*f585d8a3SJacky Wang * See the License for the specific language governing permissions and 14*f585d8a3SJacky Wang * limitations under the License. 15*f585d8a3SJacky Wang */ 16*f585d8a3SJacky Wang 17*f585d8a3SJacky Wang package dagger.internal.codegen; 18*f585d8a3SJacky Wang 19*f585d8a3SJacky Wang import static dagger.internal.codegen.DaggerModuleMethodSubject.Factory.assertThatMethodInUnannotatedClass; 20*f585d8a3SJacky Wang import static dagger.internal.codegen.DaggerModuleMethodSubject.Factory.assertThatModuleMethod; 21*f585d8a3SJacky Wang 22*f585d8a3SJacky Wang import com.google.common.collect.ImmutableList; 23*f585d8a3SJacky Wang import dagger.Module; 24*f585d8a3SJacky Wang import dagger.producers.ProducerModule; 25*f585d8a3SJacky Wang import java.lang.annotation.Annotation; 26*f585d8a3SJacky Wang import java.util.Collection; 27*f585d8a3SJacky Wang import javax.inject.Qualifier; 28*f585d8a3SJacky Wang import org.junit.Test; 29*f585d8a3SJacky Wang import org.junit.runner.RunWith; 30*f585d8a3SJacky Wang import org.junit.runners.Parameterized; 31*f585d8a3SJacky Wang import org.junit.runners.Parameterized.Parameters; 32*f585d8a3SJacky Wang 33*f585d8a3SJacky Wang @RunWith(Parameterized.class) 34*f585d8a3SJacky Wang public class MultibindsValidationTest { 35*f585d8a3SJacky Wang 36*f585d8a3SJacky Wang @Parameters(name = "{0}") parameters()37*f585d8a3SJacky Wang public static Collection<Object[]> parameters() { 38*f585d8a3SJacky Wang return ImmutableList.copyOf(new Object[][] {{Module.class}, {ProducerModule.class}}); 39*f585d8a3SJacky Wang } 40*f585d8a3SJacky Wang 41*f585d8a3SJacky Wang private final String moduleDeclaration; 42*f585d8a3SJacky Wang MultibindsValidationTest(Class<? extends Annotation> moduleAnnotation)43*f585d8a3SJacky Wang public MultibindsValidationTest(Class<? extends Annotation> moduleAnnotation) { 44*f585d8a3SJacky Wang moduleDeclaration = "@" + moduleAnnotation.getCanonicalName() + " abstract class %s { %s }"; 45*f585d8a3SJacky Wang } 46*f585d8a3SJacky Wang 47*f585d8a3SJacky Wang @Test notWithinModule()48*f585d8a3SJacky Wang public void notWithinModule() { 49*f585d8a3SJacky Wang assertThatMethodInUnannotatedClass("@Multibinds abstract Set<Object> emptySet();") 50*f585d8a3SJacky Wang .hasError("@Multibinds methods can only be present within a @Module or @ProducerModule"); 51*f585d8a3SJacky Wang } 52*f585d8a3SJacky Wang 53*f585d8a3SJacky Wang @Test voidMethod()54*f585d8a3SJacky Wang public void voidMethod() { 55*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract void voidMethod();") 56*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 57*f585d8a3SJacky Wang .hasError("@Multibinds methods return type must be either a Set or Map type."); 58*f585d8a3SJacky Wang } 59*f585d8a3SJacky Wang 60*f585d8a3SJacky Wang @Test primitiveMethod()61*f585d8a3SJacky Wang public void primitiveMethod() { 62*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract int primitive();") 63*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 64*f585d8a3SJacky Wang .hasError("@Multibinds methods return type must be either a Set or Map type."); 65*f585d8a3SJacky Wang } 66*f585d8a3SJacky Wang 67*f585d8a3SJacky Wang @Test rawMap()68*f585d8a3SJacky Wang public void rawMap() { 69*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Map rawMap();") 70*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 71*f585d8a3SJacky Wang .hasError("return type cannot be a raw Map type"); 72*f585d8a3SJacky Wang } 73*f585d8a3SJacky Wang 74*f585d8a3SJacky Wang @Test wildcardMapValue()75*f585d8a3SJacky Wang public void wildcardMapValue() { 76*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Map<String, ?> wildcardMap();") 77*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 78*f585d8a3SJacky Wang .hasError("return type cannot use a wildcard as the Map value type."); 79*f585d8a3SJacky Wang } 80*f585d8a3SJacky Wang 81*f585d8a3SJacky Wang @Test wildcardMapValueWithBounds()82*f585d8a3SJacky Wang public void wildcardMapValueWithBounds() { 83*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Map<String, ? extends Number> wildcardMap();") 84*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 85*f585d8a3SJacky Wang .hasError("return type cannot use a wildcard as the Map value type."); 86*f585d8a3SJacky Wang } 87*f585d8a3SJacky Wang 88*f585d8a3SJacky Wang @Test wildcardMapKey()89*f585d8a3SJacky Wang public void wildcardMapKey() { 90*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Map<?, String> wildcardMap();") 91*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 92*f585d8a3SJacky Wang .hasError("return type cannot use a wildcard as the Map key type."); 93*f585d8a3SJacky Wang } 94*f585d8a3SJacky Wang 95*f585d8a3SJacky Wang @Test wildcardMapKeyWithBounds()96*f585d8a3SJacky Wang public void wildcardMapKeyWithBounds() { 97*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Map<? extends Number, String> wildcardMap();") 98*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 99*f585d8a3SJacky Wang .hasError("return type cannot use a wildcard as the Map key type."); 100*f585d8a3SJacky Wang } 101*f585d8a3SJacky Wang 102*f585d8a3SJacky Wang @Test providerMap()103*f585d8a3SJacky Wang public void providerMap() { 104*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Map<String, Provider<Object>> providerMap();") 105*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 106*f585d8a3SJacky Wang .hasError("return type cannot use 'Provider' in the Map value type."); 107*f585d8a3SJacky Wang } 108*f585d8a3SJacky Wang 109*f585d8a3SJacky Wang @Test producerMap()110*f585d8a3SJacky Wang public void producerMap() { 111*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Map<String, Producer<Object>> producerMap();") 112*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 113*f585d8a3SJacky Wang .hasError("return type cannot use 'Producer' in the Map value type."); 114*f585d8a3SJacky Wang } 115*f585d8a3SJacky Wang 116*f585d8a3SJacky Wang @Test producedMap()117*f585d8a3SJacky Wang public void producedMap() { 118*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Map<String, Produced<Object>> producedMap();") 119*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 120*f585d8a3SJacky Wang .hasError("return type cannot use 'Produced' in the Map value type."); 121*f585d8a3SJacky Wang } 122*f585d8a3SJacky Wang 123*f585d8a3SJacky Wang @Test rawSet()124*f585d8a3SJacky Wang public void rawSet() { 125*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Set rawSet();") 126*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 127*f585d8a3SJacky Wang .hasError("return type cannot be a raw Set type"); 128*f585d8a3SJacky Wang } 129*f585d8a3SJacky Wang 130*f585d8a3SJacky Wang @Test wildcardSet()131*f585d8a3SJacky Wang public void wildcardSet() { 132*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Set<?> wildcardSet();") 133*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 134*f585d8a3SJacky Wang .hasError("return type cannot use a wildcard as the Set value type."); 135*f585d8a3SJacky Wang } 136*f585d8a3SJacky Wang 137*f585d8a3SJacky Wang @Test wildcardSetWithBounds()138*f585d8a3SJacky Wang public void wildcardSetWithBounds() { 139*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Set<? extends Number> wildcardSet();") 140*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 141*f585d8a3SJacky Wang .hasError("return type cannot use a wildcard as the Set value type."); 142*f585d8a3SJacky Wang } 143*f585d8a3SJacky Wang 144*f585d8a3SJacky Wang @Test providerSet()145*f585d8a3SJacky Wang public void providerSet() { 146*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Set<Provider<Object>> providerSet();") 147*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 148*f585d8a3SJacky Wang .hasError("return type cannot use 'Provider' in the Set value type."); 149*f585d8a3SJacky Wang } 150*f585d8a3SJacky Wang 151*f585d8a3SJacky Wang @Test producerSet()152*f585d8a3SJacky Wang public void producerSet() { 153*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Set<Producer<Object>> producerSet();") 154*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 155*f585d8a3SJacky Wang .hasError("return type cannot use 'Producer' in the Set value type."); 156*f585d8a3SJacky Wang } 157*f585d8a3SJacky Wang 158*f585d8a3SJacky Wang @Test producedSet()159*f585d8a3SJacky Wang public void producedSet() { 160*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Set<Produced<Object>> producedSet();") 161*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 162*f585d8a3SJacky Wang .hasError("return type cannot use 'Produced' in the Set value type."); 163*f585d8a3SJacky Wang } 164*f585d8a3SJacky Wang 165*f585d8a3SJacky Wang @Test overqualifiedSet()166*f585d8a3SJacky Wang public void overqualifiedSet() { 167*f585d8a3SJacky Wang assertThatModuleMethod( 168*f585d8a3SJacky Wang "@Multibinds @SomeQualifier @OtherQualifier " 169*f585d8a3SJacky Wang + "abstract Set<Object> tooManyQualifiersSet();") 170*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 171*f585d8a3SJacky Wang .importing(SomeQualifier.class, OtherQualifier.class) 172*f585d8a3SJacky Wang .hasError("may not use more than one @Qualifier"); 173*f585d8a3SJacky Wang } 174*f585d8a3SJacky Wang 175*f585d8a3SJacky Wang @Test overqualifiedMap()176*f585d8a3SJacky Wang public void overqualifiedMap() { 177*f585d8a3SJacky Wang assertThatModuleMethod( 178*f585d8a3SJacky Wang "@Multibinds @SomeQualifier @OtherQualifier " 179*f585d8a3SJacky Wang + "abstract Map<String, Object> tooManyQualifiersMap();") 180*f585d8a3SJacky Wang .withDeclaration(moduleDeclaration) 181*f585d8a3SJacky Wang .importing(SomeQualifier.class, OtherQualifier.class) 182*f585d8a3SJacky Wang .hasError("may not use more than one @Qualifier"); 183*f585d8a3SJacky Wang } 184*f585d8a3SJacky Wang 185*f585d8a3SJacky Wang @Test hasParameters()186*f585d8a3SJacky Wang public void hasParameters() { 187*f585d8a3SJacky Wang assertThatModuleMethod("@Multibinds abstract Set<String> parameters(Object param);") 188*f585d8a3SJacky Wang .hasError("@Multibinds methods cannot have parameters"); 189*f585d8a3SJacky Wang } 190*f585d8a3SJacky Wang 191*f585d8a3SJacky Wang @Qualifier 192*f585d8a3SJacky Wang public @interface SomeQualifier {} 193*f585d8a3SJacky Wang 194*f585d8a3SJacky Wang @Qualifier 195*f585d8a3SJacky Wang public @interface OtherQualifier {} 196*f585d8a3SJacky Wang } 197