• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.processingstep;
18 
19 import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.assistedInjectAssistedParameters;
20 
21 import androidx.room.compiler.processing.XConstructorElement;
22 import androidx.room.compiler.processing.XMessager;
23 import androidx.room.compiler.processing.XType;
24 import com.google.common.collect.ImmutableList;
25 import com.google.common.collect.ImmutableSet;
26 import com.squareup.javapoet.ClassName;
27 import dagger.internal.codegen.binding.AssistedInjectionAnnotations.AssistedParameter;
28 import dagger.internal.codegen.javapoet.TypeNames;
29 import dagger.internal.codegen.validation.InjectValidator;
30 import dagger.internal.codegen.validation.ValidationReport;
31 import java.util.HashSet;
32 import java.util.Set;
33 import javax.inject.Inject;
34 
35 /** An annotation processor for {@link dagger.assisted.AssistedInject}-annotated elements. */
36 final class AssistedInjectProcessingStep extends TypeCheckingProcessingStep<XConstructorElement> {
37   private final XMessager messager;
38   private final InjectValidator injectValidator;
39 
40   @Inject
AssistedInjectProcessingStep(XMessager messager, InjectValidator injectValidator)41   AssistedInjectProcessingStep(XMessager messager, InjectValidator injectValidator) {
42     this.messager = messager;
43     this.injectValidator = injectValidator;
44   }
45 
46   @Override
annotationClassNames()47   public ImmutableSet<ClassName> annotationClassNames() {
48     return ImmutableSet.of(TypeNames.ASSISTED_INJECT);
49   }
50 
51   @Override
process( XConstructorElement assistedInjectElement, ImmutableSet<ClassName> annotations)52   protected void process(
53       XConstructorElement assistedInjectElement, ImmutableSet<ClassName> annotations) {
54     // The InjectValidator has already run and reported its errors in InjectProcessingStep, so no
55     // need to report its errors. However, the AssistedInjectValidator relies on the InjectValidator
56     // returning a clean report, so we check that first before running AssistedInjectValidator. This
57     // shouldn't be expensive since InjectValidator caches its results after validating.
58     if (injectValidator.validate(assistedInjectElement.getEnclosingElement()).isClean()) {
59       new AssistedInjectValidator().validate(assistedInjectElement).printMessagesTo(messager);
60     }
61   }
62 
63   private final class AssistedInjectValidator {
validate(XConstructorElement constructor)64     ValidationReport validate(XConstructorElement constructor) {
65       ValidationReport.Builder report = ValidationReport.about(constructor);
66 
67       XType assistedInjectType = constructor.getEnclosingElement().getType();
68       ImmutableList<AssistedParameter> assistedParameters =
69           assistedInjectAssistedParameters(assistedInjectType);
70 
71       Set<AssistedParameter> uniqueAssistedParameters = new HashSet<>();
72       for (AssistedParameter assistedParameter : assistedParameters) {
73         if (!uniqueAssistedParameters.add(assistedParameter)) {
74           report.addError(
75               String.format(
76                   "@AssistedInject constructor has duplicate @Assisted type: %s. Consider setting"
77                       + " an identifier on the parameter by using @Assisted(\"identifier\") in both"
78                       + " the factory and @AssistedInject constructor",
79                   assistedParameter),
80               assistedParameter.element());
81         }
82       }
83 
84       return report.build();
85     }
86   }
87 }
88