• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.isMapValueFrameworkType;
20 import static dagger.internal.codegen.base.FrameworkTypes.isSetValueFrameworkType;
21 import static dagger.internal.codegen.validation.BindingElementValidator.AllowsMultibindings.NO_MULTIBINDINGS;
22 import static dagger.internal.codegen.validation.BindingElementValidator.AllowsScoping.NO_SCOPING;
23 import static dagger.internal.codegen.validation.BindingMethodValidator.Abstractness.MUST_BE_ABSTRACT;
24 import static dagger.internal.codegen.validation.BindingMethodValidator.ExceptionSuperclass.NO_EXCEPTIONS;
25 import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
26 import static dagger.internal.codegen.xprocessing.XTypes.isWildcard;
27 
28 import androidx.room.compiler.processing.XMethodElement;
29 import androidx.room.compiler.processing.XProcessingEnv;
30 import com.google.common.collect.ImmutableSet;
31 import dagger.internal.codegen.base.MapType;
32 import dagger.internal.codegen.base.SetType;
33 import dagger.internal.codegen.binding.InjectionAnnotations;
34 import dagger.internal.codegen.javapoet.TypeNames;
35 import javax.inject.Inject;
36 
37 /** A validator for {@link dagger.multibindings.Multibinds} methods. */
38 class MultibindsMethodValidator extends BindingMethodValidator {
39 
40   /** Creates a validator for {@link dagger.multibindings.Multibinds @Multibinds} methods. */
41   @Inject
MultibindsMethodValidator( XProcessingEnv processingEnv, DependencyRequestValidator dependencyRequestValidator, InjectionAnnotations injectionAnnotations)42   MultibindsMethodValidator(
43       XProcessingEnv processingEnv,
44       DependencyRequestValidator dependencyRequestValidator,
45       InjectionAnnotations injectionAnnotations) {
46     super(
47         TypeNames.MULTIBINDS,
48         ImmutableSet.of(TypeNames.MODULE, TypeNames.PRODUCER_MODULE),
49         MUST_BE_ABSTRACT,
50         NO_EXCEPTIONS,
51         NO_MULTIBINDINGS,
52         NO_SCOPING,
53         processingEnv,
54         dependencyRequestValidator,
55         injectionAnnotations);
56   }
57 
58   @Override
elementValidator(XMethodElement method)59   protected ElementValidator elementValidator(XMethodElement method) {
60     return new Validator(method);
61   }
62 
63   private class Validator extends MethodValidator {
64     private final XMethodElement method;
65 
Validator(XMethodElement method)66     Validator(XMethodElement method) {
67       super(method);
68       this.method = method;
69     }
70 
71     @Override
checkParameters()72     protected void checkParameters() {
73       if (!method.getParameters().isEmpty()) {
74         report.addError(bindingMethods("cannot have parameters"));
75       }
76     }
77 
78     /** Adds an error unless the method returns a {@code Map<K, V>} or {@code Set<T>}. */
79     @Override
checkType()80     protected void checkType() {
81       if (MapType.isMap(method.getReturnType())) {
82         checkMapType(MapType.from(method.getReturnType()));
83       } else if (SetType.isSet(method.getReturnType())) {
84         checkSetType(SetType.from(method.getReturnType()));
85       } else {
86         report.addError(bindingMethods("return type must be either a Set or Map type."));
87       }
88     }
89 
checkMapType(MapType mapType)90     private void checkMapType(MapType mapType) {
91       if (mapType.isRawType()) {
92         report.addError(bindingMethods("return type cannot be a raw Map type"));
93       } else if (isWildcard(mapType.keyType())) {
94         report.addError(
95             bindingMethods("return type cannot use a wildcard as the Map key type."));
96       } else if (isWildcard(mapType.valueType())) {
97         report.addError(
98             bindingMethods("return type cannot use a wildcard as the Map value type."));
99       } else if (isMapValueFrameworkType(mapType.valueType())) {
100         String frameworkTypeName = getSimpleName(mapType.valueType().getTypeElement());
101         report.addError(
102             bindingMethods(
103                 "return type cannot use '%s' in the Map value type.", frameworkTypeName));
104       }
105     }
106 
checkSetType(SetType setType)107     private void checkSetType(SetType setType) {
108       if (setType.isRawType()) {
109         report.addError(bindingMethods("return type cannot be a raw Set type"));
110       } else if (isWildcard(setType.elementType())) {
111         report.addError(bindingMethods("return type cannot use a wildcard as the Set value type."));
112       } else if (isSetValueFrameworkType(setType.elementType())) {
113         String frameworkTypeName = getSimpleName(setType.elementType().getTypeElement());
114         report.addError(
115             bindingMethods(
116                 "return type cannot use '%s' in the Set value type.", frameworkTypeName));
117       }
118     }
119   }
120 }
121