1 /* 2 * Copyright (C) 2016 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.BindingElementValidator.AllowsMultibindings.NO_MULTIBINDINGS; 20 import static dagger.internal.codegen.BindingElementValidator.AllowsScoping.NO_SCOPING; 21 import static dagger.internal.codegen.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT; 22 import static dagger.internal.codegen.BindingMethodValidator.ExceptionSuperclass.NO_EXCEPTIONS; 23 import static dagger.internal.codegen.FrameworkTypes.isFrameworkType; 24 25 import com.google.auto.common.MoreTypes; 26 import com.google.common.collect.ImmutableSet; 27 import dagger.Module; 28 import dagger.internal.codegen.langmodel.DaggerElements; 29 import dagger.internal.codegen.langmodel.DaggerTypes; 30 import dagger.multibindings.Multibinds; 31 import dagger.producers.ProducerModule; 32 import javax.inject.Inject; 33 import javax.lang.model.element.ExecutableElement; 34 import javax.lang.model.type.TypeMirror; 35 36 /** A validator for {@link Multibinds} methods. */ 37 class MultibindsMethodValidator extends BindingMethodValidator { 38 39 /** Creates a validator for {@link Multibinds @Multibinds} methods. */ 40 @Inject MultibindsMethodValidator( DaggerElements elements, DaggerTypes types, DependencyRequestValidator dependencyRequestValidator)41 MultibindsMethodValidator( 42 DaggerElements elements, 43 DaggerTypes types, 44 DependencyRequestValidator dependencyRequestValidator) { 45 super( 46 elements, 47 types, 48 Multibinds.class, 49 ImmutableSet.of(Module.class, ProducerModule.class), 50 dependencyRequestValidator, 51 MUST_BE_ABSTRACT, 52 NO_EXCEPTIONS, 53 NO_MULTIBINDINGS, 54 NO_SCOPING); 55 } 56 57 @Override elementValidator(ExecutableElement element)58 protected ElementValidator elementValidator(ExecutableElement element) { 59 return new Validator(element); 60 } 61 62 private class Validator extends MethodValidator { Validator(ExecutableElement element)63 Validator(ExecutableElement element) { 64 super(element); 65 } 66 67 @Override checkParameters()68 protected void checkParameters() { 69 if (!element.getParameters().isEmpty()) { 70 report.addError(bindingMethods("cannot have parameters")); 71 } 72 } 73 74 /** Adds an error unless the method returns a {@code Map<K, V>} or {@code Set<T>}. */ 75 @Override checkType()76 protected void checkType() { 77 if (!isPlainMap(element.getReturnType()) 78 && !isPlainSet(element.getReturnType())) { 79 report.addError(bindingMethods("must return Map<K, V> or Set<T>")); 80 } 81 } 82 isPlainMap(TypeMirror returnType)83 private boolean isPlainMap(TypeMirror returnType) { 84 if (!MapType.isMap(returnType)) { 85 return false; 86 } 87 MapType mapType = MapType.from(returnType); 88 return !mapType.isRawType() 89 && MoreTypes.isType(mapType.valueType()) // No wildcards. 90 && !isFrameworkType(mapType.valueType()); 91 } 92 isPlainSet(TypeMirror returnType)93 private boolean isPlainSet(TypeMirror returnType) { 94 if (!SetType.isSet(returnType)) { 95 return false; 96 } 97 SetType setType = SetType.from(returnType); 98 return !setType.isRawType() 99 && MoreTypes.isType(setType.elementType()) // No wildcards. 100 && !isFrameworkType(setType.elementType()); 101 } 102 } 103 } 104