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