• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.hilt.processor.internal;
18 
19 import com.google.auto.common.MoreTypes;
20 import com.google.common.base.Preconditions;
21 import com.google.common.collect.ImmutableList;
22 import com.google.errorprone.annotations.FormatMethod;
23 import com.google.errorprone.annotations.FormatString;
24 import java.util.Collection;
25 import java.util.stream.Collectors;
26 import javax.annotation.Nullable;
27 import javax.lang.model.element.Element;
28 import javax.lang.model.element.TypeElement;
29 import javax.lang.model.type.TypeKind;
30 import javax.lang.model.type.TypeMirror;
31 
32 /** Static helper methods for throwing errors during code generation. */
33 public final class ProcessorErrors {
34   /**
35    * Ensures the truth of an expression involving the state of the calling instance, but not
36    * involving any parameters to the calling method.
37    *
38    * @param expression a boolean expression
39    * @param badElement the element that was at fault
40    * @param errorMessage the exception message to use if the check fails; will be converted to a
41    *     string using {@link String#valueOf(Object)}
42    * @throws BadInputException if {@code expression} is false
43    */
checkState( boolean expression, Element badElement, @Nullable Object errorMessage)44   public static void checkState(
45       boolean expression,
46       Element badElement,
47       @Nullable Object errorMessage) {
48     Preconditions.checkNotNull(badElement);
49     if (!expression) {
50       throw new BadInputException(String.valueOf(errorMessage), badElement);
51     }
52   }
53 
54   /**
55    * Ensures the truth of an expression involving the state of the calling instance, but not
56    * involving any parameters to the calling method.
57    *
58    * <p>e.g. checkState(foo.isABar(), "Failed because of %s is not a bar", foo);
59    *
60    * @param expression a boolean expression
61    * @param badElement the element that was at fault
62    * @param errorMessageTemplate a template for the exception message should the check fail. The
63    *     message is formed by replacing each {@code %s} placeholder in the template with an
64    *     argument. These are matched by position - the first {@code %s} gets {@code
65    *     errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message in
66    *     square braces. Unmatched placeholders will be left as-is.
67    * @param errorMessageArgs the arguments to be substituted into the message template. Arguments
68    *     are converted to strings using {@link String#valueOf(Object)}.
69    * @throws BadInputException if {@code expression} is false
70    * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or
71    *     {@code errorMessageArgs} is null (don't let this happen)
72    */
73   @FormatMethod
checkState( boolean expression, Element badElement, @Nullable @FormatString String errorMessageTemplate, @Nullable Object... errorMessageArgs)74   public static void checkState(
75       boolean expression,
76       Element badElement,
77       @Nullable @FormatString String errorMessageTemplate,
78       @Nullable Object... errorMessageArgs) {
79     Preconditions.checkNotNull(badElement);
80     if (!expression) {
81       throw new BadInputException(
82           String.format(errorMessageTemplate, errorMessageArgs), badElement);
83     }
84   }
85 
86   /**
87    * Ensures the truth of an expression involving the state of the calling instance, but not
88    * involving any parameters to the calling method.
89    *
90    * @param expression a boolean expression
91    * @param badElements the element that were at fault
92    * @param errorMessage the exception message to use if the check fails; will be converted to a
93    *     string using {@link String#valueOf(Object)}
94    * @throws BadInputException if {@code expression} is false
95    */
checkState( boolean expression, Collection<? extends Element> badElements, @Nullable Object errorMessage)96   public static void checkState(
97       boolean expression,
98       Collection<? extends Element> badElements,
99       @Nullable Object errorMessage) {
100     Preconditions.checkNotNull(badElements);
101     if (!expression) {
102       Preconditions.checkState(!badElements.isEmpty());
103       throw new BadInputException(String.valueOf(errorMessage), badElements);
104     }
105   }
106 
107   /**
108    * Ensures the truth of an expression involving the state of the calling instance, but not
109    * involving any parameters to the calling method.
110    *
111    * @param expression a boolean expression
112    * @param badElements the elements that were at fault
113    * @param errorMessageTemplate a template for the exception message should the check fail. The
114    *     message is formed by replacing each {@code %s} placeholder in the template with an
115    *     argument. These are matched by position - the first {@code %s} gets {@code
116    *     errorMessageArgs[0]}, etc. Unmatched arguments will be appended to the formatted message in
117    *     square braces. Unmatched placeholders will be left as-is.
118    * @param errorMessageArgs the arguments to be substituted into the message template. Arguments
119    *     are converted to strings using {@link String#valueOf(Object)}.
120    * @throws BadInputException if {@code expression} is false
121    * @throws NullPointerException if the check fails and either {@code errorMessageTemplate} or
122    *     {@code errorMessageArgs} is null (don't let this happen)
123    */
124   @FormatMethod
checkState( boolean expression, Collection<? extends Element> badElements, @Nullable @FormatString String errorMessageTemplate, @Nullable Object... errorMessageArgs)125   public static void checkState(
126       boolean expression,
127       Collection<? extends Element> badElements,
128       @Nullable @FormatString String errorMessageTemplate,
129       @Nullable Object... errorMessageArgs) {
130     Preconditions.checkNotNull(badElements);
131     if (!expression) {
132       Preconditions.checkState(!badElements.isEmpty());
133       throw new BadInputException(
134           String.format(errorMessageTemplate, errorMessageArgs), badElements);
135     }
136   }
137 
138   /**
139    * Ensures that the given element is not an error kind and does not inherit from an error kind.
140    *
141    * @param element the element to check
142    * @throws ErrorTypeException if {@code element} inherits from an error kind.
143    */
checkNotErrorKind(TypeElement element)144   public static void checkNotErrorKind(TypeElement element) {
145     TypeMirror currType = element.asType();
146     ImmutableList.Builder<String> typeHierarchy = ImmutableList.builder();
147     while (currType.getKind() != TypeKind.NONE) {
148       typeHierarchy.add(currType.toString());
149       if (currType.getKind() == TypeKind.ERROR) {
150         throw new ErrorTypeException(
151             String.format(
152                 "%s, type hierarchy contains error kind, %s."
153                 + "\n\tThe partially resolved hierarchy is:\n\t\t%s",
154                 element,
155                 currType,
156                 typeHierarchy.build().stream().collect(Collectors.joining(" -> "))),
157             element);
158       }
159       currType = MoreTypes.asTypeElement(currType).getSuperclass();
160     }
161   }
162 
ProcessorErrors()163   private ProcessorErrors() {}
164 }
165