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.aggregateddeps; 18 19 import static com.google.auto.common.Visibility.effectiveVisibilityOfElement; 20 21 import com.google.auto.common.MoreElements; 22 import com.google.auto.common.Visibility; 23 import com.google.auto.value.AutoValue; 24 import com.squareup.javapoet.ClassName; 25 import com.squareup.javapoet.TypeName; 26 import dagger.hilt.processor.internal.ClassNames; 27 import dagger.hilt.processor.internal.KotlinMetadataUtils; 28 import dagger.hilt.processor.internal.Processors; 29 import java.util.Optional; 30 import javax.lang.model.element.AnnotationMirror; 31 import javax.lang.model.element.TypeElement; 32 import javax.lang.model.util.Elements; 33 34 /** PkgPrivateModuleMetadata contains a set of utilities for processing package private modules. */ 35 @AutoValue 36 public abstract class PkgPrivateMetadata { 37 /** Returns the public Hilt wrapped type or the type itself if it is already public. */ publicModule(TypeElement element, Elements elements)38 public static TypeElement publicModule(TypeElement element, Elements elements) { 39 return publicDep(element, elements, ClassNames.MODULE); 40 } 41 42 /** Returns the public Hilt wrapped type or the type itself if it is already public. */ publicEarlyEntryPoint(TypeElement element, Elements elements)43 public static TypeElement publicEarlyEntryPoint(TypeElement element, Elements elements) { 44 return publicDep(element, elements, ClassNames.EARLY_ENTRY_POINT); 45 } 46 47 /** Returns the public Hilt wrapped type or the type itself if it is already public. */ publicEntryPoint(TypeElement element, Elements elements)48 public static TypeElement publicEntryPoint(TypeElement element, Elements elements) { 49 return publicDep(element, elements, ClassNames.ENTRY_POINT); 50 } 51 publicDep( TypeElement element, Elements elements, ClassName annotation)52 private static TypeElement publicDep( 53 TypeElement element, Elements elements, ClassName annotation) { 54 return of(elements, element, annotation) 55 .map(PkgPrivateMetadata::generatedClassName) 56 .map(ClassName::canonicalName) 57 .map(elements::getTypeElement) 58 .orElse(element); 59 } 60 61 private static final String PREFIX = "HiltWrapper_"; 62 63 /** Returns the base class name of the elemenet. */ baseClassName()64 TypeName baseClassName() { 65 return TypeName.get(getTypeElement().asType()); 66 } 67 68 /** Returns TypeElement for the module element the metadata object represents */ getTypeElement()69 abstract TypeElement getTypeElement(); 70 71 /** 72 * Returns an optional @InstallIn AnnotationMirror for the module element the metadata object 73 * represents 74 */ getOptionalInstallInAnnotationMirror()75 abstract Optional<AnnotationMirror> getOptionalInstallInAnnotationMirror(); 76 77 /** Return the Type of this package private element. */ getAnnotation()78 abstract ClassName getAnnotation(); 79 80 /** Returns the expected genenerated classname for the element the metadata object represents */ generatedClassName()81 final ClassName generatedClassName() { 82 return Processors.prepend( 83 Processors.getEnclosedClassName(ClassName.get(getTypeElement())), PREFIX); 84 } 85 86 /** 87 * Returns an Optional PkgPrivateMetadata requiring Hilt processing, otherwise returns an empty 88 * Optional. 89 */ of( Elements elements, TypeElement element, ClassName annotation)90 static Optional<PkgPrivateMetadata> of( 91 Elements elements, TypeElement element, ClassName annotation) { 92 // If this is a public element no wrapping is needed 93 if (effectiveVisibilityOfElement(element) == Visibility.PUBLIC 94 && !KotlinMetadataUtils.getMetadataUtil().isVisibilityInternal(element)) { 95 return Optional.empty(); 96 } 97 98 Optional<AnnotationMirror> installIn; 99 if (Processors.hasAnnotation(element, ClassNames.INSTALL_IN)) { 100 installIn = Optional.of(Processors.getAnnotationMirror(element, ClassNames.INSTALL_IN)); 101 } else if (Processors.hasAnnotation(element, ClassNames.TEST_INSTALL_IN)) { 102 installIn = Optional.of(Processors.getAnnotationMirror(element, ClassNames.TEST_INSTALL_IN)); 103 } else { 104 throw new IllegalStateException( 105 "Expected element to be annotated with @InstallIn: " + element); 106 } 107 108 if (annotation.equals(ClassNames.MODULE) 109 ) { 110 // Skip modules that require a module instance. Otherwise Dagger validation will (correctly) 111 // fail on the wrapper saying a public module can't include a private one, which makes the 112 // error more confusing for users since they probably aren't aware of the wrapper. When 113 // skipped, if the root is in a different package, the error will instead just be on the 114 // generated Hilt component. 115 if (Processors.requiresModuleInstance(elements, MoreElements.asType(element))) { 116 return Optional.empty(); 117 } 118 } 119 return Optional.of( 120 new AutoValue_PkgPrivateMetadata(MoreElements.asType(element), installIn, annotation)); 121 } 122 } 123