1 /* 2 * Copyright (C) 2022 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.javapoet; 18 19 import static com.google.common.base.Preconditions.checkState; 20 21 import androidx.room.compiler.processing.XProcessingEnv; 22 import androidx.room.compiler.processing.XRawType; 23 import androidx.room.compiler.processing.XType; 24 import androidx.room.compiler.processing.compat.XConverters; 25 import com.squareup.javapoet.ClassName; 26 import com.squareup.javapoet.TypeName; 27 import dagger.internal.codegen.xprocessing.XProcessingEnvs; 28 import dagger.internal.codegen.xprocessing.XTypes; 29 import java.util.Optional; 30 31 /** 32 * The type of an {@link Expression} that can represent both {@link XType} or {@link XRawType}. 33 */ 34 // TODO(bcorso): It would be nice if XType and XRawType shared some basic interface with some of 35 // the common methods so that we wouldn't need to create this ExpressionType to make things work. 36 public final class ExpressionType { create(XType type)37 public static ExpressionType create(XType type) { 38 return new ExpressionType( 39 Optional.of(type), Optional.empty(), XConverters.getProcessingEnv(type)); 40 } 41 create(XRawType type, XProcessingEnv processingEnv)42 static ExpressionType create(XRawType type, XProcessingEnv processingEnv) { 43 return new ExpressionType(Optional.empty(), Optional.of(type), processingEnv); 44 } 45 createRawType(XType type)46 public static ExpressionType createRawType(XType type) { 47 return create(type.getRawType(), XConverters.getProcessingEnv(type)); 48 } 49 50 private final Optional<XType> optionalType; 51 private final Optional<XRawType> optionalRawType; 52 private final XProcessingEnv processingEnv; 53 ExpressionType( Optional<XType> optionalType, Optional<XRawType> optionalRawType, XProcessingEnv processingEnv)54 private ExpressionType( 55 Optional<XType> optionalType, 56 Optional<XRawType> optionalRawType, 57 XProcessingEnv processingEnv) { 58 this.optionalType = optionalType; 59 this.optionalRawType = optionalRawType; 60 this.processingEnv = processingEnv; 61 checkState(optionalType.isPresent() || optionalRawType.isPresent()); 62 } 63 unwrapType()64 public ExpressionType unwrapType() { 65 return optionalType.isPresent() && !XTypes.isRawParameterizedType(optionalType.get()) 66 ? ExpressionType.create(XProcessingEnvs.unwrapType(optionalType.get())) 67 : ExpressionType.create(processingEnv.requireType(TypeName.OBJECT)); 68 } 69 wrapType(ClassName wrapper)70 public ExpressionType wrapType(ClassName wrapper) { 71 return optionalType.isPresent() 72 ? ExpressionType.create( 73 XProcessingEnvs.wrapType(wrapper, optionalType.get(), processingEnv)) 74 // If the current type is a raw type then we just return the wrapper type as a raw type too. 75 // This isn't really accurate, but it's the best we can do with XProcessing's type system. 76 // For example, if the current type is a raw type, Foo, then Provider<Foo> is not allowed so 77 // we return the raw Provider type. 78 : ExpressionType.createRawType(processingEnv.requireType(wrapper)); 79 } 80 rewrapType(ClassName wrapper)81 public ExpressionType rewrapType(ClassName wrapper) { 82 return optionalType.isPresent() 83 ? ExpressionType.create(XTypes.rewrapType(optionalType.get(), wrapper)) 84 : ExpressionType.createRawType(processingEnv.requireType(wrapper)); 85 } 86 getTypeName()87 public TypeName getTypeName() { 88 return optionalType.isPresent() 89 ? optionalType.get().getTypeName() 90 : optionalRawType.get().getTypeName(); 91 } 92 isSameType(XType type)93 public boolean isSameType(XType type) { 94 return optionalType.isPresent() 95 ? optionalType.get().isSameType(type) 96 : XTypes.isRawParameterizedType(type) 97 && getTypeName().equals(type.getTypeName()); 98 } 99 isSameType(XRawType type)100 public boolean isSameType(XRawType type) { 101 return getTypeName().equals(type.getTypeName()); 102 } 103 isAssignableTo(XType type)104 public boolean isAssignableTo(XType type) { 105 return optionalType.isPresent() 106 ? type.isAssignableFrom(optionalType.get()) 107 : type.getRawType().isAssignableFrom(optionalRawType.get()); 108 } 109 isAssignableTo(XRawType rawType)110 public boolean isAssignableTo(XRawType rawType) { 111 return optionalType.isPresent() 112 ? rawType.isAssignableFrom(optionalType.get()) 113 : rawType.isAssignableFrom(optionalRawType.get()); 114 } 115 asType()116 Optional<XType> asType() { 117 return optionalType; 118 } 119 asRawType()120 Optional<XRawType> asRawType() { 121 return optionalRawType; 122 } 123 getProcessingEnv()124 XProcessingEnv getProcessingEnv() { 125 return processingEnv; 126 } 127 } 128