• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.binding;
18 
19 import static dagger.internal.codegen.extension.Optionals.emptiesLast;
20 import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
21 import static java.util.Comparator.comparing;
22 
23 import androidx.room.compiler.processing.XElement;
24 import androidx.room.compiler.processing.XTypeElement;
25 import dagger.internal.codegen.model.BindingKind;
26 import dagger.internal.codegen.model.Key;
27 import dagger.internal.codegen.xprocessing.XElements;
28 import java.util.Comparator;
29 import java.util.Optional;
30 
31 /** An object that declares or specifies a binding. */
32 public abstract class Declaration {
33   /**
34    * A comparator that compares binding declarations with elements.
35    *
36    * <p>Compares, in order:
37    *
38    * <ol>
39    *   <li>Contributing module or enclosing type name
40    *   <li>Binding element's simple name
41    *   <li>Binding element's type
42    * </ol>
43    *
44    * Any binding declarations without elements are last.
45    */
46   public static final Comparator<Declaration> COMPARATOR =
47       comparing(
48               (Declaration declaration) ->
49                   declaration.contributingModule().isPresent()
50                       ? declaration.contributingModule()
51                       : declaration.bindingTypeElement(),
52               emptiesLast(comparing(XTypeElement::getQualifiedName)))
53           .thenComparing(
54               Declaration::bindingElement,
55               emptiesLast(
56                   comparing((XElement element) -> getSimpleName(element))
57                       .thenComparing(XElements::toStableString)));
58 
59   /** The {@link Key} of this declaration. */
key()60   public abstract Key key();
61 
62   /**
63    * The {@link XElement} that declares this binding. Absent for {@linkplain BindingKind binding
64    * kinds} that are not always declared by exactly one element.
65    *
66    * <p>For example, consider {@link BindingKind#MULTIBOUND_SET}. A component with many
67    * {@code @IntoSet} bindings for the same key will have a synthetic binding that depends on all
68    * contributions, but with no identifying binding element. A {@code @Multibinds} method will also
69    * contribute a synthetic binding, but since multiple {@code @Multibinds} methods can coexist in
70    * the same component (and contribute to one single binding), it has no binding element.
71    */
bindingElement()72   public abstract Optional<XElement> bindingElement();
73 
74   /**
75    * The type enclosing the {@link #bindingElement()}, or {@link Optional#empty()} if {@link
76    * #bindingElement()} is empty.
77    */
bindingTypeElement()78   public final Optional<XTypeElement> bindingTypeElement() {
79     return bindingElement().map(XElements::closestEnclosingTypeElement);
80   }
81 
82   /**
83    * The installed module class that contributed the {@link #bindingElement()}. May be a subclass of
84    * the class that contains {@link #bindingElement()}. Absent if {@link #bindingElement()} is
85    * empty.
86    */
contributingModule()87   public abstract Optional<XTypeElement> contributingModule();
88 }
89