Add docs for XProcessing
Bug: 160323720
Test: n/a
Change-Id: I0754a0f63cccba7e13181dbbb564e4ffce183a21
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/JavaPoetExt.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/JavaPoetExt.kt
index 1ce505e..179e8ba 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/JavaPoetExt.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/JavaPoetExt.kt
@@ -43,16 +43,27 @@
TypeName.get(this)
}
+/**
+ * Adds the given element as the originating element for compilation.
+ * see [TypeSpec.Builder.addOriginatingElement].
+ */
fun TypeSpec.Builder.addOriginatingElement(element: XElement) {
if (element is JavacElement) {
this.addOriginatingElement(element.element)
}
}
+/**
+ * Helper class to create overrides for XExecutableElements with final parameters and correct
+ * parameter names read from Kotlin Metadata.
+ */
object MethodSpecHelper {
/**
- * Custom override where we mark parameters as final, overidden method as public and also
- * preserve method names from kotlin metadata.
+ * Creates an overriding [MethodSpec] for the given [XExecutableElement] where:
+ * * all parameters are marked as final
+ * * parameter names are copied from KotlinMetadata when available
+ * * [Override] annotation is added and other annotations are dropped
+ * * thrown types are copied if the backing element is from java
*/
fun overridingWithFinalParams(
elm: XMethodElement,
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/JavacTestProcessor.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/JavacTestProcessor.kt
index 89d6d13..86bbde9 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/JavacTestProcessor.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/JavacTestProcessor.kt
@@ -26,11 +26,12 @@
* Javac processor implementation that provides access to the round environment.
*
* This is only used in tests, the main processor uses an API similar to the processing step
- * in Auto.
+ * in Auto Common.
*/
@VisibleForTesting
abstract class JavacTestProcessor : AbstractProcessor() {
val xProcessingEnv by lazy {
+ // lazily create this as it is not available on construction time
XProcessingEnv.create(super.processingEnv)
}
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XArrayType.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XArrayType.kt
index dd39007..eea3a09 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XArrayType.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XArrayType.kt
@@ -16,6 +16,14 @@
package androidx.room.processing
+/**
+ * Represents an Array type including Kotlin's [Array] type.
+ *
+ * @see [javax.lang.model.type.ArrayType]
+ */
interface XArrayType : XType {
+ /**
+ * The type of elements in the Array
+ */
val componentType: XType
}
\ No newline at end of file
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XConstructorElement.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XConstructorElement.kt
index e805214..37d179a 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XConstructorElement.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XConstructorElement.kt
@@ -20,5 +20,6 @@
* Represents a constructor of a class.
*
* @see XMethodElement
+ * @see XExecutableElement
*/
interface XConstructorElement : XExecutableElement
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XDeclaredType.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XDeclaredType.kt
index dc1196d..b9928fc 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XDeclaredType.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XDeclaredType.kt
@@ -16,6 +16,17 @@
package androidx.room.processing
+/**
+ * Represents a Declared type that is either an interface or class.
+ *
+ * @see [javax.lang.model.type.DeclaredType]
+ */
interface XDeclaredType : XType {
+ /**
+ * Type arguments for the element. Note that they might be either placeholders or real
+ * resolvable types depending on the usage.
+ *
+ * @see [javax.lang.model.type.DeclaredType.getTypeArguments]
+ */
val typeArguments: List<XType>
}
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XElement.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XElement.kt
index 9898845..b20621f 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XElement.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XElement.kt
@@ -19,12 +19,32 @@
import kotlin.contracts.contract
import kotlin.reflect.KClass
+/**
+ * Represents an element declared in code.
+ *
+ * @see [javax.lang.model.element.Element]
+ * @see XExecutableElement
+ * @see XVariableElement
+ * @see XTypeElement
+ */
interface XElement {
+ /**
+ * SimpleName of the element converted to a String.
+ *
+ * @see [javax.lang.model.element.Element.getSimpleName]
+ */
val name: String
+ /**
+ * The qualified name of the package that contains this element.
+ */
val packageName: String
/**
+ * Nullability of an Element as declared in code via its type or annotations (e.g.
+ * [androidx.annotation.Nullable].
+ * This will be moved into [XType].
+ *
* TODO:
* Nullability is normally a property of Type not Element but currently Room relies on
* Annotations to resolve nullability which exists only on Elements, not Types.
@@ -34,46 +54,121 @@
*/
val nullability: XNullability
+ /**
+ * The [XElement] that contains this element.
+ *
+ * For inner classes, this will be another [XTypeElement].
+ * For top level classes, it will be null as x-processing does not model packages or modules.
+ *
+ * For [XExecutableElement], it will be the [XTypeElement] where the method is declared.
+ */
val enclosingElement: XElement?
+ /**
+ * Returns `true` if this element is public (has public modifier in Java or not marked as
+ * private / internal in Kotlin).
+ */
fun isPublic(): Boolean
+ /**
+ * Returns `true` if this element has protected modifier.
+ */
fun isProtected(): Boolean
+ /**
+ * Returns `true` if this element is declared as abstract.
+ */
fun isAbstract(): Boolean
+ /**
+ * Returns `true` if this element has private modifier.
+ */
fun isPrivate(): Boolean
+ /**
+ * Returns `true` if this element has static modifier.
+ */
fun isStatic(): Boolean
+ /**
+ * Returns `true` if this element has transient modifier.
+ */
fun isTransient(): Boolean
+ /**
+ * Returns `true` if this element is final and cannot be overridden.
+ */
fun isFinal(): Boolean
+ /**
+ * Returns the string representation of the Element's kind.
+ */
fun kindName(): String
+ /**
+ * If the current element has an annotation with the given [annotation] class, a boxed instance
+ * of it will be returned where fields can be read. Otherwise, `null` value is returned.
+ *
+ * @see [hasAnnotation]
+ * @see [hasAnnotationInPackage]
+ */
fun <T : Annotation> toAnnotationBox(annotation: KClass<T>): XAnnotationBox<T>?
+ /**
+ * Returns `true` if this element has an annotation that is declared in the given package.
+ */
// a very sad method but helps avoid abstraction annotation
fun hasAnnotationInPackage(pkg: String): Boolean
+ /**
+ * Returns `true` if this element is annotated with the given [annotation].
+ *
+ * @see [toAnnotationBox]
+ * @see [hasAnyOf]
+ */
fun hasAnnotation(annotation: KClass<out Annotation>): Boolean
+ /**
+ * Returns `true` if this element has one of the [annotations].
+ */
fun hasAnyOf(vararg annotations: KClass<out Annotation>) = annotations.any(this::hasAnnotation)
+ /**
+ * Returns `true` if and only if this element can never be null.
+ * For Java source code, this means the element is either primitive or annotated with one of
+ * the non-nullability annotations.
+ * For Kotlin source code, this means element's type is specified as non-null.
+ */
fun isNonNull() = nullability == XNullability.NONNULL
+ /**
+ * Casts current element to [XTypeElement].
+ */
fun asTypeElement() = this as XTypeElement
+ /**
+ * Casts current element to [XVariableElement].
+ */
fun asVariableElement() = this as XVariableElement
+ /**
+ * Casts current element to [XMethodElement].
+ */
fun asMethodElement() = this as XMethodElement
+ /**
+ * Returns the [XDeclaredType] type of the current element, assuming it is an [XTypeElement].
+ * It is a shortcut for `asTypeElement().type`.
+ */
fun asDeclaredType(): XDeclaredType {
return asTypeElement().type
}
}
+/**
+ * Checks whether this element represents an [XTypeElement].
+ * @see [XElement.asTypeElement]
+ */
// we keep these as extension methods to be able to use contracts
fun XElement.isType(): Boolean {
contract {
@@ -82,13 +177,21 @@
return this is XTypeElement
}
-fun XElement.isField(): Boolean {
+/**
+ * Checks whether this element represents an [XVariableElement].
+ * @see [XElement.asVariableElement]
+ */
+fun XElement.isVariableElement(): Boolean {
contract {
- returns(true) implies (this@isField is XVariableElement)
+ returns(true) implies (this@isVariableElement is XVariableElement)
}
return this is XVariableElement
}
+/**
+ * Checks whether this element represents an [XMethodElement].
+ * @see [XElement.asMethodElement]
+ */
fun XElement.isMethod(): Boolean {
contract {
returns(true) implies (this@isMethod is XMethodElement)
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XEquality.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XEquality.kt
index fc3af21..b0189d54 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XEquality.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XEquality.kt
@@ -23,6 +23,9 @@
* Enforcement is done in JavacType and JavacElement
*/
internal interface XEquality {
+ /**
+ * The list of items that should participate in equality checks.
+ */
val equalityItems: Array<out Any?>
companion object {
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XExecutableElement.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XExecutableElement.kt
index 75749fa..1bb53ea 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XExecutableElement.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XExecutableElement.kt
@@ -16,8 +16,25 @@
package androidx.room.processing
+/**
+ * Represents a method, constructor or initializer.
+ *
+ * @see [javax.lang.model.element.ExecutableElement]
+ */
interface XExecutableElement : XElement {
- override val enclosingElement: XElement
+ /**
+ * The [XTypeElement] that contains this method.
+ */
+ override val enclosingElement: XTypeElement
+
+ /**
+ * The list of parameters that should be passed into this method.
+ *
+ * @see [isVarArgs]
+ */
val parameters: List<XVariableElement>
+ /**
+ * Returns true if this method receives a vararg parameter.
+ */
fun isVarArgs(): Boolean
}
\ No newline at end of file
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XMessager.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XMessager.kt
index 0df763c..3962338 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XMessager.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XMessager.kt
@@ -18,6 +18,16 @@
import javax.tools.Diagnostic
+/**
+ * Logging interface for the processor
+ */
interface XMessager {
+ /**
+ * Prints the given [msg] to the logs while also associating it with the given [element].
+ *
+ * @param kind Kind of the message
+ * @param msg The actual message to report to the compiler
+ * @param element The element with whom the message should be associated with
+ */
fun printMessage(kind: Diagnostic.Kind, msg: String, element: XElement? = null)
}
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XMethodElement.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XMethodElement.kt
index 2b7a17d..357fe16 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XMethodElement.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XMethodElement.kt
@@ -20,15 +20,53 @@
* Represents a method in a class / interface.
*
* @see XConstructorElement
+ * @see XMethodElement
*/
interface XMethodElement : XExecutableElement {
+ /**
+ * The return type for the method. Note that it might be [XType.isNone] if it does not return or
+ * [XType.isError] if the return type cannot be resolved.
+ */
val returnType: XType
+
+ /**
+ * The type representation of the method where more type parameters might be resolved.
+ */
val executableType: XMethodType
+ /**
+ * Returns true if this method has the default modifier.
+ *
+ * @see [findKotlinDefaultImpl]
+ */
fun isJavaDefault(): Boolean
- fun findKotlinDefaultImpl(): XMethodElement?
- fun isSuspendFunction(): Boolean
+
+ /**
+ * Returns the method as if it is declared in [other].
+ *
+ * This is specifically useful if you have a method that has type arguments and there is a
+ * subclass ([other]) where type arguments are specified to actual types.
+ */
fun asMemberOf(other: XDeclaredType): XMethodType
+
+ /**
+ * Returns the default implementation generated by the Kotlin compiler for interfaces.
+ *
+ * To support default methods in interfaces, Kotlin generates a delegate implementation and this
+ * function returns that default implementation if it exists.
+ */
+ fun findKotlinDefaultImpl(): XMethodElement?
+
+ /**
+ * Returns true if this is a suspend function.
+ *
+ * @see XMethodType.getSuspendFunctionReturnType
+ */
+ fun isSuspendFunction(): Boolean
+
+ /**
+ * Returns true if this method can be overridden without checking its enclosing [XElement].
+ */
fun isOverrideableIgnoringContainer(): Boolean {
return !isFinal() && !isPrivate() && !isStatic()
}
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XMethodType.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XMethodType.kt
index c3afe50..8d5ede4 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XMethodType.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XMethodType.kt
@@ -19,16 +19,30 @@
import com.squareup.javapoet.TypeVariableName
/**
- * Represents a type information for an executable.
+ * Represents a type information for a method.
*
* It is not an XType as it does not represent a class or primitive.
*/
interface XMethodType {
+ /**
+ * The return type of the method
+ */
val returnType: XType
+ /**
+ * Parameter types of the method.
+ */
val parameterTypes: List<XType>
+ /**
+ * Returns the names of [TypeVariableName]s for this executable.
+ */
val typeVariableNames: List<TypeVariableName>
+ /**
+ * If this is a suspend function, returns the real return type as seen by Kotlin.
+ *
+ * Calling this function in a method that is not a suspend method is an error.
+ */
fun getSuspendFunctionReturnType(): XType
}
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XNullability.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XNullability.kt
index 0cdee82..15f2f0c 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XNullability.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XNullability.kt
@@ -16,8 +16,26 @@
package androidx.room.processing
+/**
+ * Declares the nullability of a type or element.
+ */
enum class XNullability {
+ /**
+ * The type is guaranteed to be nullable. This means it is either a Kotlin Type declared with a
+ * `?` at the end or it is a Java type that has one of the `nullable` annotations (e.g.
+ * [androidx.annotation.Nullable].
+ */
NULLABLE,
+ /**
+ * The type is guaranteed to be nonnull. This means it is either a Kotlin Type declared
+ * without a `?` at the end or it is a Java type that has one of the `non-null` annotations
+ * (e.g. [androidx.annotation.NonNull].
+ */
NONNULL,
+ /**
+ * The nullability of the type is unknown. This happens if this is a non-primitive Java type
+ * that does not have a nullability annotation or a Type in Kotlin where it is inferred from
+ * the platform.
+ */
UNKNOWN
}
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XProcessingEnv.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XProcessingEnv.kt
index f4ed124..95a75f4 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XProcessingEnv.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XProcessingEnv.kt
@@ -22,28 +22,65 @@
import javax.annotation.processing.ProcessingEnvironment
import kotlin.reflect.KClass
+/**
+ * API for a Processor that is either backed by Java's Annotation Processing API or KSP.
+ */
interface XProcessingEnv {
+ /**
+ * The logger interface to log messages
+ */
val messager: XMessager
+ /**
+ * List of options passed into the annotation processor
+ */
val options: Map<String, String>
+ /**
+ * The API to generate files
+ */
val filer: Filer
+ /**
+ * Looks for the [XTypeElement] with the given qualified name and returns `null` if it does not
+ * exist.
+ */
fun findTypeElement(qName: String): XTypeElement?
+ /**
+ * Looks for the [XType] with the given qualified name and returns `null` if it does not exist.
+ */
fun findType(qName: String): XType?
+ /**
+ * Returns the [XType] with the given qualified name or throws an exception if it does not
+ * exist.
+ */
fun requireType(qName: String): XType = checkNotNull(findType(qName)) {
"cannot find required type $qName"
}
+ /**
+ * Returns the [XTypeElement] for the annotation that should be added to the generated code.
+ */
fun findGeneratedAnnotation(): XTypeElement?
+ /**
+ * Returns an [XDeclaredType] for the given [type] element with the type arguments specified
+ * as in [types].
+ */
fun getDeclaredType(type: XTypeElement, vararg types: XType): XDeclaredType
+ /**
+ * Return an [XArrayType] that has [type] as the [XArrayType.componentType].
+ */
fun getArrayType(type: XType): XArrayType
+ /**
+ * Returns the [XTypeElement] with the given qualified name or throws an exception if it does
+ * not exist.
+ */
fun requireTypeElement(qName: String): XTypeElement {
return checkNotNull(findTypeElement(qName)) {
"Cannot find required type element $qName"
@@ -67,11 +104,12 @@
fun findTypeElement(klass: KClass<*>) = findTypeElement(klass.java.canonicalName!!)
- fun getArrayType(typeName: TypeName) = getArrayType(
- requireType(typeName)
- )
+ fun getArrayType(typeName: TypeName) = getArrayType(requireType(typeName))
companion object {
+ /**
+ * Creates a new [XProcessingEnv] implementation derived from the given Java [env].
+ */
fun create(env: ProcessingEnvironment): XProcessingEnv = JavacProcessingEnv(env)
}
}
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XProcessingStep.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XProcessingStep.kt
index 3cbca26..5a00fca 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XProcessingStep.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XProcessingStep.kt
@@ -32,13 +32,28 @@
* processing.
*/
interface XProcessingStep {
+ /**
+ * The implementation of processing logic for the step. It is guaranteed that the keys in
+ * [elementsByAnnotation] will be a subset of the set returned by [annotations].
+ *
+ * @return the elements (a subset of the values of [elementsByAnnotation]) that this step
+ * is unable to process, possibly until a later processing round. These elements will be
+ * passed back to this step at the next round of processing.
+ */
fun process(
env: XProcessingEnv,
elementsByAnnotation: Map<KClass<out Annotation>, List<XTypeElement>>
): Set<XTypeElement>
+ /**
+ * The set of annotations processed by this step.
+ */
fun annotations(): Set<KClass<out Annotation>>
+ /**
+ * Wraps current [XProcessingStep] into an Auto Common
+ * [BasicAnnotationProcessor.ProcessingStep].
+ */
fun asAutoCommonProcessor(
env: XProcessingEnv
): BasicAnnotationProcessor.ProcessingStep {
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XRoundEnv.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XRoundEnv.kt
index 2e3c0fe..e74b02b1 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XRoundEnv.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XRoundEnv.kt
@@ -21,15 +21,27 @@
import androidx.room.processing.javac.JavacRoundEnv
import javax.annotation.processing.RoundEnvironment
-// only used in tests of Room
+/**
+ * Representation of an annotation processing round.
+ *
+ * @see javax.annotation.processing.RoundEnvironment
+ */
@VisibleForTesting
interface XRoundEnv {
-
+ /**
+ * The root elements in the round.
+ */
val rootElements: Set<XElement>
+ /**
+ * Returns the set of [XElement]s that are annotated with the given [klass].
+ */
fun getElementsAnnotatedWith(klass: Class<out Annotation>): Set<XElement>
companion object {
+ /**
+ * Creates an [XRoundEnv] from the given Java processing parameters.
+ */
fun create(
processingEnv: XProcessingEnv,
roundEnvironment: RoundEnvironment
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XType.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XType.kt
index 24b1499..2fb1179 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XType.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XType.kt
@@ -20,80 +20,193 @@
import kotlin.contracts.contract
import kotlin.reflect.KClass
+/**
+ * Represents a type reference
+ *
+ * @see javax.lang.model.type.TypeMirror
+ * @see [XArrayType]
+ * @see [XDeclaredType]
+ */
interface XType {
+ /**
+ * The Javapoet [TypeName] representation of the type
+ */
val typeName: TypeName
+ /**
+ * Casts the current type to [XTypeElement].
+ *
+ * @see isType
+ */
fun asTypeElement(): XTypeElement
+ /**
+ * Returns `true` if this type can be assigned from [other]
+ */
fun isAssignableFrom(other: XType): Boolean
+ /**
+ * Returns `true` if this type can be assigned from [other] while ignoring the type variance.
+ */
fun isAssignableFromWithoutVariance(other: XType): Boolean {
return isAssignableWithoutVariance(other, this)
}
// TODO these is<Type> checks may need to be moved into the implementation.
// It is not yet clear how we will model some types in Kotlin (e.g. primitives)
+ /**
+ * Returns `true` if this is not `byte` type.
+ */
fun isNotByte() = !isByte()
+ /**
+ * Returns `true` if this is an error type.
+ */
fun isError(): Boolean
+ /**
+ * Returns the string representation of a possible default value for this type.
+ * (e.g. `0` for `int`, `null` for `String`)
+ */
fun defaultValue(): String
+ /**
+ * Returns boxed version of this type if it is a primitive or itself if it is not a primitive
+ * type.
+ *
+ * @see isPrimitive
+ */
fun boxed(): XType
+ /**
+ * Returns this type as an instance of [XArrayType] or fails if it is not an array.
+ */
fun asArray(): XArrayType = this as XArrayType
+ /**
+ * Returns `true` if this is an `int`
+ */
fun isPrimitiveInt(): Boolean {
return typeName == TypeName.INT
}
+ /**
+ * Returns `true` if this type represents a boxed int (java.lang.Integer)
+ */
fun isBoxedInt() = typeName == TypeName.INT.box()
+ /**
+ * Returns `true` if this is a primitive or boxed it
+ */
fun isInt() = isPrimitiveInt() || isBoxedInt()
+ /**
+ * Returns `true` if this is `long`
+ */
fun isPrimitiveLong() = typeName == TypeName.LONG
+ /**
+ * Returns `true` if this is a boxed long (java.lang.Long)
+ */
fun isBoxedLong() = typeName == TypeName.LONG.box()
+ /**
+ * Returns `true` if this is a primitive or boxed long
+ */
fun isLong() = isPrimitiveLong() || isBoxedLong()
+ /**
+ * Returns `true` if this is a [List]
+ */
fun isList(): Boolean = isType() && isTypeOf(List::class)
+ /**
+ * Returns `true` if this is `void`
+ */
fun isVoid() = typeName == TypeName.VOID
+ /**
+ * Returns `true` if this is a [Void]
+ */
fun isVoidObject(): Boolean = isType() && isTypeOf(Void::class)
+ /**
+ * Returns `true` if this represents a primitive type
+ */
fun isPrimitive() = typeName.isPrimitive
+ /**
+ * Returns `true` if this is the kotlin [Unit] type.
+ */
fun isKotlinUnit(): Boolean = isType() && isTypeOf(Unit::class)
+ /**
+ * Returns `true` if this is not `void`.
+ */
fun isNotVoid() = !isVoid()
+ /**
+ * Returns `true` if this type represents a valid resolvable type.
+ */
fun isNotError() = !isError()
+ /**
+ * Returns `true` if this represents a `byte`.
+ */
fun isByte() = typeName == TypeName.BYTE
+ /**
+ * Returns `true` if this is the None type.
+ */
fun isNone(): Boolean
+ /**
+ * Returns `true` if this is not the None type.
+ */
fun isNotNone() = !isNone()
+ /**
+ * Returns true if this represented by a [XTypeElement].
+ */
fun isType(): Boolean
+ /**
+ * Returns `true` if this is the same raw type as [other]
+ */
fun isTypeOf(other: KClass<*>): Boolean
+ /**
+ * Returns `true` if this represents the same type as [other]
+ */
fun isSameType(other: XType): Boolean
+ /**
+ * Returns the extends bound if this is a wildcard or self.
+ */
fun extendsBoundOrSelf(): XType = extendsBound() ?: this
+ /**
+ * Returns `true` if this can be assigned from an instance of [other] without checking for
+ * variance.
+ */
fun isAssignableWithoutVariance(other: XType): Boolean {
return isAssignableWithoutVariance(other, this)
}
+ /**
+ * Returns the erasure of this type. (e.g. `List<String>` to `List`.
+ */
fun erasure(): XType
+ /**
+ * If this is a wildcard with an extends bound, returns that bounded typed.
+ */
fun extendsBound(): XType?
}
+/**
+ * Returns true if this is an [XDeclaredType].
+ */
fun XType.isDeclared(): Boolean {
contract {
returns(true) implies (this@isDeclared is XDeclaredType)
@@ -101,6 +214,9 @@
return this is XDeclaredType
}
+/**
+ * Returns true if this is an [XArrayType].
+ */
fun XType.isArray(): Boolean {
contract {
returns(true) implies (this@isArray is XArrayType)
@@ -108,6 +224,9 @@
return this is XArrayType
}
+/**
+ * Returns true if this is a [List] or [Set].
+ */
fun XType.isCollection(): Boolean {
contract {
returns(true) implies (this@isCollection is XDeclaredType)
@@ -115,6 +234,9 @@
return isType() && (isTypeOf(List::class) || isTypeOf(Set::class))
}
+/**
+ * Returns `this` as an [XDeclaredType].
+ */
fun XType.asDeclaredType() = this as XDeclaredType
private fun isAssignableWithoutVariance(from: XType, to: XType): Boolean {
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XTypeElement.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XTypeElement.kt
index aabe603..230787d 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XTypeElement.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XTypeElement.kt
@@ -19,16 +19,34 @@
import com.squareup.javapoet.ClassName
interface XTypeElement : XElement {
+ /**
+ * The qualified name of the Class/Interface.
+ */
val qualifiedName: String
+ /**
+ * The type represented by this [XTypeElement].
+ */
val type: XDeclaredType
+ /**
+ * The super type of this element if it represents a class.
+ */
val superType: XType?
+ /**
+ * Javapoet [ClassName] of the type.
+ */
val className: ClassName
+ /**
+ * Returns `true` if this [XTypeElement] represents an interface
+ */
fun isInterface(): Boolean
+ /**
+ * Returns `true` if this [XTypeElement] is declared as a Kotlin `object`
+ */
fun isKotlinObject(): Boolean
/**
@@ -37,7 +55,11 @@
*/
fun getAllFieldsIncludingPrivateSupers(): List<XVariableElement>
- // only in kotlin
+ /**
+ * Returns the primary constructor for the type, if it exists.
+ *
+ * Note that this only exists for classes declared in Kotlin.
+ */
fun findPrimaryConstructor(): XConstructorElement?
/**
@@ -62,5 +84,8 @@
*/
fun getAllNonPrivateInstanceMethods(): List<XMethodElement>
+ /**
+ * Returns the list of constructors in this type element
+ */
fun getConstructors(): List<XConstructorElement>
}
diff --git a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XVariableElement.kt b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XVariableElement.kt
index 84cc29d..5e423a5 100644
--- a/room/compiler-xprocessing/src/main/java/androidx/room/processing/XVariableElement.kt
+++ b/room/compiler-xprocessing/src/main/java/androidx/room/processing/XVariableElement.kt
@@ -16,8 +16,19 @@
package androidx.room.processing
+/**
+ * Represents a variable element, that is either a method parameter or a field.
+ */
interface XVariableElement : XElement {
+ /**
+ * Returns the type of this field or parameter
+ */
val type: XType
+ /**
+ * Returns this type as a member of the [other] type.
+ * It is useful when this [XVariableElement] has a generic type declaration and its type is
+ * specified in [other]. (e.g. Bar<T> vs Foo : Bar<String>)
+ */
fun asMemberOf(other: XDeclaredType): XType
}
\ No newline at end of file
diff --git a/room/compiler-xprocessing/src/test/java/androidx/room/processing/XElementTest.kt b/room/compiler-xprocessing/src/test/java/androidx/room/processing/XElementTest.kt
index 6cf6f2e..b792401 100644
--- a/room/compiler-xprocessing/src/test/java/androidx/room/processing/XElementTest.kt
+++ b/room/compiler-xprocessing/src/test/java/androidx/room/processing/XElementTest.kt
@@ -281,13 +281,13 @@
element.getField("field").let { field ->
assertThat(field.isType()).isFalse()
assertThat(field.isAbstract()).isFalse()
- assertThat(field.isField()).isTrue()
+ assertThat(field.isVariableElement()).isTrue()
assertThat(field.isMethod()).isFalse()
}
element.getMethod("method").let { method ->
assertThat(method.isType()).isFalse()
assertThat(method.isAbstract()).isFalse()
- assertThat(method.isField()).isFalse()
+ assertThat(method.isVariableElement()).isFalse()
assertThat(method.isMethod()).isTrue()
}
}