Merge "Document setTargetRotation for ImageAnalysis" into androidx-master-dev
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/SupportedSurfaceCombination.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/SupportedSurfaceCombination.java
index 918b673..c67da97 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/SupportedSurfaceCombination.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/SupportedSurfaceCombination.java
@@ -364,10 +364,10 @@
List<Size> sizesNotMatchAspectRatio = new ArrayList<>();
Rational aspectRatio = null;
- Integer targetAspectRatio = config.getTargetAspectRatio(null);
- if (targetAspectRatio != null) {
+ if (config.hasTargetAspectRatio()) {
// Checks the sensor orientation.
boolean isSensorLandscapeOrientation = isRotationNeeded(Surface.ROTATION_0);
+ @AspectRatio int targetAspectRatio = config.getTargetAspectRatio();
switch (targetAspectRatio) {
case AspectRatio.RATIO_4_3:
aspectRatio =
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisConfig.java
index bd07ef3..55d6114 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageAnalysisConfig.java
@@ -319,17 +319,9 @@
return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM);
}
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Nullable
@Override
- public Integer getTargetAspectRatio(@Nullable Integer valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO, valueIfMissing);
+ public boolean hasTargetAspectRatio() {
+ return containsOption(OPTION_TARGET_ASPECT_RATIO);
}
/**
@@ -736,7 +728,7 @@
}
/**
- * Sets the name of the target object being configured.
+ * Sets the name of the target object being configured, used only for debug logging.
*
* <p>The name should be a value that can uniquely identify an instance of the object being
* configured.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureConfig.java
index d40e832..06a4036 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCaptureConfig.java
@@ -95,18 +95,6 @@
/**
* Returns the {@link FlashMode}.
*
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Nullable
- public Integer getFlashMode(@Nullable Integer valueIfMissing) {
- return retrieveOption(OPTION_FLASH_MODE, valueIfMissing);
- }
-
- /**
- * Returns the {@link FlashMode}.
- *
* @return The stored value, if it exists in this configuration.
* @throws IllegalArgumentException if the option does not exist in this configuration.
*/
@@ -423,17 +411,9 @@
return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM);
}
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Nullable
@Override
- public Integer getTargetAspectRatio(@Nullable Integer valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO, valueIfMissing);
+ public boolean hasTargetAspectRatio() {
+ return containsOption(OPTION_TARGET_ASPECT_RATIO);
}
/**
@@ -768,7 +748,7 @@
*
* @return A {@link ImageCaptureConfig} populated with the current state.
* @throws IllegalArgumentException if attempting to set both target aspect ratio and
- * target resolution.
+ * target resolution.
*/
@Override
@NonNull
@@ -909,7 +889,7 @@
}
/**
- * Sets the name of the target object being configured.
+ * Sets the name of the target object being configured, used only for debug logging.
*
* <p>The name should be a value that can uniquely identify an instance of the object being
* configured.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageOutputConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageOutputConfig.java
index 3951792..68431fa 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageOutputConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageOutputConfig.java
@@ -144,14 +144,12 @@
Rational getTargetAspectRatioCustom();
/**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
+ * Verifies whether the aspect ratio of the target intending to use images from this
+ * configuration is set.
*
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
+ * @return true is the value exists in this configuration, false otherwise.
*/
- @Nullable
- Integer getTargetAspectRatio(@Nullable Integer valueIfMissing);
+ boolean hasTargetAspectRatio();
/**
* Retrieves the aspect ratio of the target intending to use images from this configuration.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/PreviewConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/PreviewConfig.java
index 6c303fe..a03f6cb 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/PreviewConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/PreviewConfig.java
@@ -258,17 +258,9 @@
return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM);
}
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Nullable
@Override
- public Integer getTargetAspectRatio(@Nullable Integer valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO, valueIfMissing);
+ public boolean hasTargetAspectRatio() {
+ return containsOption(OPTION_TARGET_ASPECT_RATIO);
}
/**
@@ -637,7 +629,7 @@
*
* @return A {@link PreviewConfig} populated with the current state.
* @throws IllegalArgumentException if attempting to set both target aspect ratio and
- * target resolution.
+ * target resolution.
*/
@NonNull
@Override
@@ -672,7 +664,7 @@
}
/**
- * Sets the name of the target object being configured.
+ * Sets the name of the target object being configured, used only for debug logging.
*
* <p>The name should be a value that can uniquely identify an instance of the object being
* configured.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/VideoCaptureConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/VideoCaptureConfig.java
index b4fc308..5b309d3 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/VideoCaptureConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/VideoCaptureConfig.java
@@ -462,17 +462,9 @@
return retrieveOption(OPTION_TARGET_ASPECT_RATIO_CUSTOM);
}
- /**
- * Retrieves the aspect ratio of the target intending to use images from this configuration.
- *
- * @param valueIfMissing The value to return if this configuration option has not been set.
- * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
- * configuration.
- */
- @Nullable
@Override
- public Integer getTargetAspectRatio(@Nullable Integer valueIfMissing) {
- return retrieveOption(OPTION_TARGET_ASPECT_RATIO, valueIfMissing);
+ public boolean hasTargetAspectRatio() {
+ return containsOption(OPTION_TARGET_ASPECT_RATIO);
}
/**
@@ -925,7 +917,7 @@
}
/**
- * Sets the name of the target object being configured.
+ * Sets the name of the target object being configured, used only for debug logging.
*
* <p>The name should be a value that can uniquely identify an instance of the object being
* configured.
diff --git a/room/common/api/2.3.0-alpha01.txt b/room/common/api/2.3.0-alpha01.txt
index 238967d..4e032bd 100644
--- a/room/common/api/2.3.0-alpha01.txt
+++ b/room/common/api/2.3.0-alpha01.txt
@@ -167,6 +167,8 @@
field public static final String INDEX_FROM_EMBEDDED_FIELD_IS_DROPPED = "ROOM_EMBEDDED_INDEX_IS_DROPPED";
field public static final String INDEX_FROM_PARENT_FIELD_IS_DROPPED = "ROOM_PARENT_FIELD_INDEX_IS_DROPPED";
field public static final String INDEX_FROM_PARENT_IS_DROPPED = "ROOM_PARENT_INDEX_IS_DROPPED";
+ field public static final String MISMATCHED_GETTER = "ROOM_MISMATCHED_GETTER_TYPE";
+ field public static final String MISMATCHED_SETTER = "ROOM_MISMATCHED_SETTER_TYPE";
field public static final String MISSING_INDEX_ON_FOREIGN_KEY_CHILD = "ROOM_MISSING_FOREIGN_KEY_CHILD_INDEX";
field public static final String MISSING_JAVA_TMP_DIR = "ROOM_MISSING_JAVA_TMP_DIR";
field public static final String MISSING_SCHEMA_LOCATION = "ROOM_MISSING_SCHEMA_LOCATION";
diff --git a/room/common/api/current.txt b/room/common/api/current.txt
index 238967d..4e032bd 100644
--- a/room/common/api/current.txt
+++ b/room/common/api/current.txt
@@ -167,6 +167,8 @@
field public static final String INDEX_FROM_EMBEDDED_FIELD_IS_DROPPED = "ROOM_EMBEDDED_INDEX_IS_DROPPED";
field public static final String INDEX_FROM_PARENT_FIELD_IS_DROPPED = "ROOM_PARENT_FIELD_INDEX_IS_DROPPED";
field public static final String INDEX_FROM_PARENT_IS_DROPPED = "ROOM_PARENT_INDEX_IS_DROPPED";
+ field public static final String MISMATCHED_GETTER = "ROOM_MISMATCHED_GETTER_TYPE";
+ field public static final String MISMATCHED_SETTER = "ROOM_MISMATCHED_SETTER_TYPE";
field public static final String MISSING_INDEX_ON_FOREIGN_KEY_CHILD = "ROOM_MISSING_FOREIGN_KEY_CHILD_INDEX";
field public static final String MISSING_JAVA_TMP_DIR = "ROOM_MISSING_JAVA_TMP_DIR";
field public static final String MISSING_SCHEMA_LOCATION = "ROOM_MISSING_SCHEMA_LOCATION";
diff --git a/room/common/api/public_plus_experimental_2.3.0-alpha01.txt b/room/common/api/public_plus_experimental_2.3.0-alpha01.txt
index 238967d..4e032bd 100644
--- a/room/common/api/public_plus_experimental_2.3.0-alpha01.txt
+++ b/room/common/api/public_plus_experimental_2.3.0-alpha01.txt
@@ -167,6 +167,8 @@
field public static final String INDEX_FROM_EMBEDDED_FIELD_IS_DROPPED = "ROOM_EMBEDDED_INDEX_IS_DROPPED";
field public static final String INDEX_FROM_PARENT_FIELD_IS_DROPPED = "ROOM_PARENT_FIELD_INDEX_IS_DROPPED";
field public static final String INDEX_FROM_PARENT_IS_DROPPED = "ROOM_PARENT_INDEX_IS_DROPPED";
+ field public static final String MISMATCHED_GETTER = "ROOM_MISMATCHED_GETTER_TYPE";
+ field public static final String MISMATCHED_SETTER = "ROOM_MISMATCHED_SETTER_TYPE";
field public static final String MISSING_INDEX_ON_FOREIGN_KEY_CHILD = "ROOM_MISSING_FOREIGN_KEY_CHILD_INDEX";
field public static final String MISSING_JAVA_TMP_DIR = "ROOM_MISSING_JAVA_TMP_DIR";
field public static final String MISSING_SCHEMA_LOCATION = "ROOM_MISSING_SCHEMA_LOCATION";
diff --git a/room/common/api/public_plus_experimental_current.txt b/room/common/api/public_plus_experimental_current.txt
index 238967d..4e032bd 100644
--- a/room/common/api/public_plus_experimental_current.txt
+++ b/room/common/api/public_plus_experimental_current.txt
@@ -167,6 +167,8 @@
field public static final String INDEX_FROM_EMBEDDED_FIELD_IS_DROPPED = "ROOM_EMBEDDED_INDEX_IS_DROPPED";
field public static final String INDEX_FROM_PARENT_FIELD_IS_DROPPED = "ROOM_PARENT_FIELD_INDEX_IS_DROPPED";
field public static final String INDEX_FROM_PARENT_IS_DROPPED = "ROOM_PARENT_INDEX_IS_DROPPED";
+ field public static final String MISMATCHED_GETTER = "ROOM_MISMATCHED_GETTER_TYPE";
+ field public static final String MISMATCHED_SETTER = "ROOM_MISMATCHED_SETTER_TYPE";
field public static final String MISSING_INDEX_ON_FOREIGN_KEY_CHILD = "ROOM_MISSING_FOREIGN_KEY_CHILD_INDEX";
field public static final String MISSING_JAVA_TMP_DIR = "ROOM_MISSING_JAVA_TMP_DIR";
field public static final String MISSING_SCHEMA_LOCATION = "ROOM_MISSING_SCHEMA_LOCATION";
diff --git a/room/common/api/restricted_2.3.0-alpha01.txt b/room/common/api/restricted_2.3.0-alpha01.txt
index ed6c4ee..a2a0510 100644
--- a/room/common/api/restricted_2.3.0-alpha01.txt
+++ b/room/common/api/restricted_2.3.0-alpha01.txt
@@ -176,6 +176,8 @@
field public static final String INDEX_FROM_EMBEDDED_FIELD_IS_DROPPED = "ROOM_EMBEDDED_INDEX_IS_DROPPED";
field public static final String INDEX_FROM_PARENT_FIELD_IS_DROPPED = "ROOM_PARENT_FIELD_INDEX_IS_DROPPED";
field public static final String INDEX_FROM_PARENT_IS_DROPPED = "ROOM_PARENT_INDEX_IS_DROPPED";
+ field public static final String MISMATCHED_GETTER = "ROOM_MISMATCHED_GETTER_TYPE";
+ field public static final String MISMATCHED_SETTER = "ROOM_MISMATCHED_SETTER_TYPE";
field public static final String MISSING_INDEX_ON_FOREIGN_KEY_CHILD = "ROOM_MISSING_FOREIGN_KEY_CHILD_INDEX";
field public static final String MISSING_JAVA_TMP_DIR = "ROOM_MISSING_JAVA_TMP_DIR";
field public static final String MISSING_SCHEMA_LOCATION = "ROOM_MISSING_SCHEMA_LOCATION";
diff --git a/room/common/api/restricted_current.txt b/room/common/api/restricted_current.txt
index ed6c4ee..a2a0510 100644
--- a/room/common/api/restricted_current.txt
+++ b/room/common/api/restricted_current.txt
@@ -176,6 +176,8 @@
field public static final String INDEX_FROM_EMBEDDED_FIELD_IS_DROPPED = "ROOM_EMBEDDED_INDEX_IS_DROPPED";
field public static final String INDEX_FROM_PARENT_FIELD_IS_DROPPED = "ROOM_PARENT_FIELD_INDEX_IS_DROPPED";
field public static final String INDEX_FROM_PARENT_IS_DROPPED = "ROOM_PARENT_INDEX_IS_DROPPED";
+ field public static final String MISMATCHED_GETTER = "ROOM_MISMATCHED_GETTER_TYPE";
+ field public static final String MISMATCHED_SETTER = "ROOM_MISMATCHED_SETTER_TYPE";
field public static final String MISSING_INDEX_ON_FOREIGN_KEY_CHILD = "ROOM_MISSING_FOREIGN_KEY_CHILD_INDEX";
field public static final String MISSING_JAVA_TMP_DIR = "ROOM_MISSING_JAVA_TMP_DIR";
field public static final String MISSING_SCHEMA_LOCATION = "ROOM_MISSING_SCHEMA_LOCATION";
diff --git a/room/common/src/main/java/androidx/room/RoomWarnings.java b/room/common/src/main/java/androidx/room/RoomWarnings.java
index e8ad213..66cc1b8 100644
--- a/room/common/src/main/java/androidx/room/RoomWarnings.java
+++ b/room/common/src/main/java/androidx/room/RoomWarnings.java
@@ -134,6 +134,47 @@
public static final String RELATION_QUERY_WITHOUT_TRANSACTION =
"ROOM_RELATION_QUERY_WITHOUT_TRANSACTION";
+ /**
+ * Reported when an `@Entity` field's type do not exactly match the getter type.
+ * For instance, in the following class:
+ * <pre>
+ * {@code @}Entity
+ * class Foo {
+ * ...
+ * private Boolean value;
+ * public boolean getValue() {
+ * return value == null ? false : value;
+ * }
+ * }
+ * </pre>
+ *
+ * Trying to insert this entity into database will always set {@code value} column to
+ * {@code false} when {@code Foo.value} is {@code null} since Room will use the {@code getValue}
+ * method to read the value. So even thought the database column is nullable, it will never
+ * be inserted as {@code null} if inserted as a {@code Foo} instance.
+ */
+ public static final String MISMATCHED_GETTER = "ROOM_MISMATCHED_GETTER_TYPE";
+
+ /**
+ * Reported when an `@Entity` field's type do not exactly match the setter type.
+ * For instance, in the following class:
+ * <pre>
+ * {@code @}Entity
+ * class Foo {
+ * ...
+ * private Boolean value;
+ * public void setValue(boolean value) {
+ * this.value = value;
+ * }
+ * }
+ * </pre>
+ *
+ * If Room reads this entity from the database, it will always set {@code Foo.value} to
+ * {@code false} when the column value is {@code null} since Room will use the {@code setValue}
+ * method to write the value.
+ */
+ public static final String MISMATCHED_SETTER = "ROOM_MISMATCHED_SETTER_TYPE";
+
/** @deprecated This type should not be instantiated as it contains only static methods. */
@Deprecated
@SuppressWarnings("PrivateConstructorForUtilityClass")
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt b/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
index 235a457..745c40f 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/PojoProcessor.kt
@@ -718,6 +718,23 @@
context.checker.check(
success || bindingScope == FieldProcessor.BindingScope.READ_FROM_CURSOR,
field.element, CANNOT_FIND_GETTER_FOR_FIELD)
+ if (success && !context.processingEnv.typeUtils.isSameType(field.getter.type, field.type)) {
+ // getter's parameter type is not exactly the same as the field type.
+ // put a warning and update the value statement binder.
+ context.logger.w(
+ warning = Warning.MISMATCHED_GETTER_TYPE,
+ element = field.element,
+ msg = ProcessorErrors.mismatchedGetter(
+ fieldName = field.name,
+ ownerType = element.asType().typeName(),
+ getterType = field.getter.type.typeName(),
+ fieldType = field.typeName
+ ))
+ field.statementBinder = context.typeAdapterStore.findStatementValueBinder(
+ input = field.getter.type,
+ affinity = field.affinity
+ )
+ }
}
private fun assignSetters(
@@ -769,6 +786,23 @@
context.checker.check(
success || bindingScope == FieldProcessor.BindingScope.BIND_TO_STMT,
field.element, CANNOT_FIND_SETTER_FOR_FIELD)
+ if (success && !context.processingEnv.typeUtils.isSameType(field.setter.type, field.type)) {
+ // setter's parameter type is not exactly the same as the field type.
+ // put a warning and update the value reader adapter.
+ context.logger.w(
+ warning = Warning.MISMATCHED_SETTER_TYPE,
+ element = field.element,
+ msg = ProcessorErrors.mismatchedSetter(
+ fieldName = field.name,
+ ownerType = element.asType().typeName(),
+ setterType = field.setter.type.typeName(),
+ fieldType = field.typeName
+ ))
+ field.cursorValueReader = context.typeAdapterStore.findCursorValueReader(
+ output = field.setter.type,
+ affinity = field.affinity
+ )
+ }
}
/**
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt b/room/compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt
index d331aa1..d5b85f4 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt
@@ -730,4 +730,26 @@
fun invalidChannelType(typeName: String) = "'$typeName' is not supported as a return type. " +
"Instead declare return type as ${KotlinTypeNames.FLOW} and use Flow transforming " +
"functions that converts the Flow into a Channel."
+
+ fun mismatchedGetter(
+ fieldName: String,
+ ownerType: TypeName,
+ getterType: TypeName,
+ fieldType: TypeName
+ ) = """
+ $ownerType's $fieldName field has type $fieldType but its getter returns $getterType.
+ This mismatch might cause unexpected $fieldName values in the database when $ownerType
+ is inserted into database.
+ """.trim()
+
+ fun mismatchedSetter(
+ fieldName: String,
+ ownerType: TypeName,
+ setterType: TypeName,
+ fieldType: TypeName
+ ) = """
+ $ownerType's $fieldName field has type $fieldType but its setter accepts $setterType.
+ This mismatch might cause unexpected $fieldName values when $ownerType is read from the
+ database.
+ """.trim()
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/vo/Warning.kt b/room/compiler/src/main/kotlin/androidx/room/vo/Warning.kt
index 0abd15e9..f959979 100644
--- a/room/compiler/src/main/kotlin/androidx/room/vo/Warning.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/vo/Warning.kt
@@ -36,7 +36,9 @@
DEFAULT_CONSTRUCTOR("ROOM_DEFAULT_CONSTRUCTOR"),
MISSING_COPY_ANNOTATIONS("MISSING_COPY_ANNOTATIONS"),
MISSING_INDEX_ON_JUNCTION("MISSING_INDEX_ON_JUNCTION"),
- JDK_VERSION_HAS_BUG("JDK_VERSION_HAS_BUG");
+ JDK_VERSION_HAS_BUG("JDK_VERSION_HAS_BUG"),
+ MISMATCHED_GETTER_TYPE("ROOM_MISMATCHED_GETTER_TYPE"),
+ MISMATCHED_SETTER_TYPE("ROOM_MISMATCHED_SETTER_TYPE");
companion object {
val PUBLIC_KEY_MAP = Warning.values().associateBy { it.publicKey }
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/FieldReadWriteWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/FieldReadWriteWriter.kt
index 448ab8f..4ffb54a 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/FieldReadWriteWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/FieldReadWriteWriter.kt
@@ -189,7 +189,10 @@
val constructorFields = node.directFields.filter {
it.field.setter.callType == CallType.CONSTRUCTOR
}.associateBy { fwi ->
- FieldReadWriteWriter(fwi).readIntoTmpVar(cursorVar, scope)
+ FieldReadWriteWriter(fwi).readIntoTmpVar(
+ cursorVar,
+ fwi.field.setter.type.typeName(),
+ scope)
}
// read decomposed fields (e.g. embedded)
node.subNodes.forEach(::visitNode)
@@ -349,9 +352,12 @@
/**
* Reads the value into a temporary local variable.
*/
- fun readIntoTmpVar(cursorVar: String, scope: CodeGenScope): String {
+ fun readIntoTmpVar(
+ cursorVar: String,
+ typeName: TypeName,
+ scope: CodeGenScope
+ ): String {
val tmpField = scope.getTmpVar("_tmp${field.name.capitalize()}")
- val typeName = field.getter.type.typeName()
scope.builder().apply {
addStatement("final $T $L", typeName, tmpField)
if (alwaysExists) {
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/TableEntityProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/TableEntityProcessorTest.kt
index b9ec119..f9b4038 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/TableEntityProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/TableEntityProcessorTest.kt
@@ -17,6 +17,7 @@
package androidx.room.processor
import COMMON
+import androidx.room.ext.typeName
import androidx.room.parser.SQLTypeAffinity
import androidx.room.processor.ProcessorErrors.RELATION_IN_ENTITY
import androidx.room.vo.CallType
@@ -28,6 +29,8 @@
import androidx.room.vo.Pojo
import androidx.room.vo.columnNames
import com.google.testing.compile.JavaFileObjects
+import com.squareup.javapoet.ClassName
+import com.squareup.javapoet.TypeName
import compileLibrarySource
import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.CoreMatchers.hasItems
@@ -35,6 +38,7 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+import java.lang.AssertionError
import javax.lang.model.type.TypeKind.INT
@RunWith(JUnit4::class)
@@ -141,6 +145,46 @@
}
@Test
+ fun setterWithAssignableType_2() {
+ singleEntity("""
+ @PrimaryKey
+ private Integer id;
+ public Integer getId() {return id;}
+ public void setId(int id) {}
+ """) { entity, invocation ->
+ val idField = entity.fields.first()
+ val cursorValueReader = idField.cursorValueReader
+ ?: throw AssertionError("must have a cursor value reader")
+ assertThat(cursorValueReader.typeMirror().typeName(),
+ `is`(invocation.typeUtils.getPrimitiveType(INT).typeName()))
+ }.compilesWithoutError()
+ .withWarningContaining(
+ ProcessorErrors.mismatchedSetter(
+ fieldName = "id",
+ ownerType = ClassName.bestGuess("foo.bar.MyEntity"),
+ setterType = TypeName.INT,
+ fieldType = TypeName.INT.box()
+ )
+ )
+ }
+
+ @Test
+ fun getterWithAssignableType_2() {
+ singleEntity("""
+ @PrimaryKey
+ private Integer id;
+ public int getId() {return id == null ? 0 : id;}
+ public void setId(Integer id) {}
+ """) { entity, invocation ->
+ val idField = entity.fields.first()
+ val statementBinder = idField.statementBinder
+ ?: throw AssertionError("must have a statement binder")
+ assertThat(statementBinder.typeMirror().typeName(),
+ `is`(invocation.typeUtils.getPrimitiveType(INT).typeName()))
+ }.compilesWithoutError()
+ }
+
+ @Test
fun noSetter() {
singleEntity("""
@PrimaryKey
diff --git a/room/integration-tests/testapp/build.gradle b/room/integration-tests/testapp/build.gradle
index 7e0f759..5f24684 100644
--- a/room/integration-tests/testapp/build.gradle
+++ b/room/integration-tests/testapp/build.gradle
@@ -75,6 +75,7 @@
androidTestImplementation(ANDROIDX_TEST_RUNNER)
androidTestImplementation(ANDROIDX_TEST_RULES)
androidTestImplementation(ESPRESSO_CORE)
+ androidTestImplementation(TRUTH)
androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it's own MockMaker
androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it's own MockMaker
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/BoxedPrimitivesTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/BoxedPrimitivesTest.java
new file mode 100644
index 0000000..fd2afd2
--- /dev/null
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/BoxedPrimitivesTest.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2019 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.integration.testapp.test;
+
+import static androidx.room.integration.testapp.test.BoxedPrimitivesTest.BaseBoxed.DEFAULT_BOOLEAN_VALUE;
+import static androidx.room.integration.testapp.test.BoxedPrimitivesTest.BaseBoxed.DEFAULT_NUMBER_VALUE;
+
+import android.content.Context;
+
+import androidx.room.ColumnInfo;
+import androidx.room.Dao;
+import androidx.room.Database;
+import androidx.room.Entity;
+import androidx.room.Insert;
+import androidx.room.PrimaryKey;
+import androidx.room.Query;
+import androidx.room.Room;
+import androidx.room.RoomDatabase;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.MediumTest;
+
+import com.google.common.truth.Truth;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class BoxedPrimitivesTest {
+ private BoxingTestDatabase mDb;
+
+ @Before
+ public void initDb() {
+ Context context = ApplicationProvider.getApplicationContext();
+ mDb = Room.inMemoryDatabaseBuilder(
+ context,
+ BoxingTestDatabase.class)
+ .build();
+ }
+
+ @After
+ public void closeDb() {
+ mDb.close();
+ }
+
+ @Test
+ public void unboxedConstructor() {
+ test(mDb.constructor());
+ }
+
+ @Test
+ public void unboxedGetter() {
+ test(mDb.field());
+ }
+
+ /**
+ * Assert that if a nullable pojo is provided, we can actually insert/read null
+ */
+ private void test(BaseDao<? extends BaseBoxed> dao) {
+ long rowId = dao.insert(new BoxedBooleanHolder(null, null));
+ BaseBoxed read = dao.find(rowId);
+ Truth.assertThat(read.mFlag).isNull();
+ Truth.assertThat(read.mNumber).isNull();
+ }
+
+ @Test
+ public void testInsert_constructor() {
+ long rowId = mDb.constructor().insertTyped(new ConstructorEntity(null, null));
+ testInsertedAsEntity(mDb.constructor(), rowId);
+ }
+
+ @Test
+ public void testInsert_field() {
+ long rowId = mDb.field().insertTyped(new FieldEntity());
+ testInsertedAsEntity(mDb.field(), rowId);
+ }
+
+ /**
+ * assert the case where row was inserted via entity hence we should've read the default values
+ * already.
+ **/
+ private void testInsertedAsEntity(BaseDao<? extends BaseBoxed> dao, long rowId) {
+ BaseBoxed read = dao.find(rowId);
+ // default getter value
+ Truth.assertThat(read.mFlag).isEqualTo(DEFAULT_BOOLEAN_VALUE);
+ Truth.assertThat(read.mNumber).isEqualTo(DEFAULT_NUMBER_VALUE);
+ }
+
+ static class BaseBoxed {
+ @ColumnInfo(name = "boxed_bool")
+ Boolean mFlag;
+ @ColumnInfo(name = "boxed_int")
+ Integer mNumber;
+
+ static final boolean DEFAULT_BOOLEAN_VALUE = true;
+ static final int DEFAULT_NUMBER_VALUE = 41;
+
+ @SuppressWarnings("unused")
+ boolean getFlag() {
+ return mFlag == null ? DEFAULT_BOOLEAN_VALUE : mFlag;
+ }
+
+ @SuppressWarnings("unused")
+ int getNumber() {
+ return mNumber == null ? DEFAULT_NUMBER_VALUE : mNumber;
+ }
+ }
+
+ @Entity
+ static class ConstructorEntity extends BaseBoxed {
+ @PrimaryKey(autoGenerate = true)
+ public long rowId = 0;
+
+ ConstructorEntity(Boolean flag, Integer number) {
+ this.mFlag = flag;
+ this.mNumber = number;
+ }
+ }
+
+ @Entity
+ static class FieldEntity extends BaseBoxed {
+ @PrimaryKey(autoGenerate = true)
+ public long rowId = 0;
+
+ void setBoxed(Boolean boxed) {
+ this.mFlag = boxed;
+ }
+
+ void setNumber(Integer number) {
+ this.mNumber = number;
+ }
+ }
+
+ static class BoxedBooleanHolder {
+ @ColumnInfo(name = "boxed_bool")
+ final Boolean mFlag;
+ @ColumnInfo(name = "boxed_int")
+ final Integer mNumber;
+
+ BoxedBooleanHolder(Boolean flag, Integer number) {
+ mFlag = flag;
+ mNumber = number;
+ }
+ }
+
+ interface BaseDao<T> {
+ long insert(BoxedBooleanHolder t);
+
+ @Insert
+ long insertTyped(T t);
+
+ T find(long rowId);
+ }
+
+ @Dao
+ interface BoxedConstructorDao extends BaseDao<ConstructorEntity> {
+ @Override
+ @Insert(entity = ConstructorEntity.class)
+ long insert(BoxedBooleanHolder item);
+
+ @Override
+ @Query("SELECT * FROM ConstructorEntity WHERE rowId = :rowId")
+ ConstructorEntity find(long rowId);
+ }
+
+ @Dao
+ interface BoxedFieldDao extends BaseDao<FieldEntity> {
+
+ @Insert(entity = FieldEntity.class)
+ long insert(BoxedBooleanHolder item);
+
+ @Override
+ @Query("SELECT * FROM FieldEntity WHERE rowId = :rowId")
+ FieldEntity find(long rowId);
+ }
+
+ @Database(
+ entities = {FieldEntity.class, ConstructorEntity.class},
+ version = 1,
+ exportSchema = false
+ )
+ abstract static class BoxingTestDatabase extends RoomDatabase {
+ abstract BoxedConstructorDao constructor();
+
+ abstract BoxedFieldDao field();
+ }
+}
diff --git a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/ModelReadsTest.kt b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/ModelReadsTest.kt
index 5175929..500c1f6a 100644
--- a/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/ModelReadsTest.kt
+++ b/ui/ui-framework/src/androidTest/java/androidx/ui/core/test/ModelReadsTest.kt
@@ -263,6 +263,8 @@
}
}
assertTrue(latch.await(1, TimeUnit.SECONDS))
+
+ assertCountDownOnlyWhileEnabled(enabled, model)
}
@Test