| /* |
| * Copyright 2020 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package androidx.room.compiler.processing.ksp |
| |
| import androidx.room.compiler.processing.XDeclaredType |
| import androidx.room.compiler.processing.XEquality |
| import androidx.room.compiler.processing.XNullability |
| import androidx.room.compiler.processing.XType |
| import androidx.room.compiler.processing.XTypeElement |
| import com.squareup.javapoet.TypeName |
| import org.jetbrains.kotlin.ksp.symbol.KSClassDeclaration |
| import org.jetbrains.kotlin.ksp.symbol.KSType |
| import org.jetbrains.kotlin.ksp.symbol.KSTypeReference |
| import org.jetbrains.kotlin.ksp.symbol.Nullability |
| import kotlin.reflect.KClass |
| |
| /** |
| * XType implementation for KSP type. |
| * |
| * It might be initialized with a [KSTypeReference] or [KSType] depending on the call point. |
| * |
| * We don't necessarily have a [KSTypeReference] (e.g. if we are getting it from an element). |
| * Similarly, we may not be able to get a [KSType] (e.g. if it resolves to error). |
| */ |
| internal open class KspType( |
| private val env: KspProcessingEnv, |
| val ksType: KSType |
| ) : XDeclaredType, XEquality { |
| override val rawType by lazy { |
| KspRawType(this) |
| } |
| |
| override val typeArguments: List<XType> by lazy { |
| ksType.arguments.map { |
| env.wrap(it.type!!) |
| } |
| } |
| override val typeName: TypeName by lazy { |
| ksType.typeName() |
| } |
| |
| override val nullability by lazy { |
| when (ksType.nullability) { |
| Nullability.NULLABLE -> XNullability.NULLABLE |
| Nullability.NOT_NULL -> XNullability.NONNULL |
| else -> XNullability.UNKNOWN |
| } |
| } |
| |
| private val _typeElement by lazy { |
| check(ksType.declaration is KSClassDeclaration) { """ |
| Unexpected case where ksType's declaration is not a KSClassDeclaration. |
| Please file a bug. |
| """.trimIndent() |
| } |
| env.wrapClassDeclaration(ksType.declaration as KSClassDeclaration) |
| } |
| |
| override fun asTypeElement(): XTypeElement { |
| return _typeElement |
| } |
| |
| override fun isAssignableFrom(other: XType): Boolean { |
| check(other is KspType) |
| return ksType.isAssignableFrom(other.ksType) |
| } |
| |
| override fun isError(): Boolean { |
| return ksType.isError |
| } |
| |
| override fun defaultValue(): String { |
| // NOTE: this does not match the java implementation though it is probably more correct for |
| // kotlin. |
| if (ksType.nullability == Nullability.NULLABLE) { |
| return "null" |
| } |
| val builtIns = env.resolver.builtIns |
| return when (ksType) { |
| builtIns.booleanType -> "false" |
| builtIns.byteType, builtIns.shortType, builtIns.intType, builtIns.longType, builtIns |
| .charType -> "0" |
| builtIns.floatType -> "0f" |
| builtIns.doubleType -> "0.0" |
| else -> "null" |
| } |
| } |
| |
| override fun boxed(): XType { |
| return this |
| } |
| |
| override fun isInt(): Boolean { |
| return env.commonTypes.nullableInt.isAssignableFrom(ksType) |
| } |
| |
| override fun isLong(): Boolean { |
| return env.commonTypes.nullableLong.isAssignableFrom(ksType) |
| } |
| |
| override fun isByte(): Boolean { |
| return env.commonTypes.nullableByte.isAssignableFrom(ksType) |
| } |
| |
| override fun isNone(): Boolean { |
| // even void is converted to Unit so we don't have none type in KSP |
| // see: KspTypeTest.noneType |
| return false |
| } |
| |
| override fun isType(): Boolean { |
| return ksType.declaration is KSClassDeclaration |
| } |
| |
| override fun isTypeOf(other: KClass<*>): Boolean { |
| // closest to what MoreTypes#isTypeOf does. |
| return rawType.typeName.toString() == other.qualifiedName |
| } |
| |
| override fun isSameType(other: XType): Boolean { |
| check(other is KspType) |
| // NOTE: this is inconsistent with java where nullability is ignored. |
| // it is intentional but might be reversed if it happens to break use cases. |
| return ksType == other.ksType |
| } |
| |
| override fun extendsBound(): XType? { |
| // NOTE: wildcard does not fully exist in kotlin and when we resolve, it always seems to |
| // be mapped to the upper bound. Might still need more investigation here |
| // https://kotlinlang.org/docs/reference/generics.html#star-projections |
| return null |
| } |
| |
| override val equalityItems: Array<out Any?> by lazy { |
| arrayOf(ksType) |
| } |
| |
| override fun equals(other: Any?): Boolean { |
| return XEquality.equals(this, other) |
| } |
| |
| override fun hashCode(): Int { |
| return XEquality.hashCode(equalityItems) |
| } |
| |
| override fun toString(): String { |
| return ksType.toString() |
| } |
| } |