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